EUCとSJIS

[上に] [前に] [次に]
snow 2000/02/16(水) 11:13:57
文字コードについて教えてください。
CGIプログラムをUNIX上で作成している(EUC)のですが、その中でHTMLファイル出力をさせています。その際、HTML出力部分のソースのみSJISでUNIXに取りこんでコンパイルしているのですが、UNIX上では全てEUCにして表示のみSJISにすることはできるのでしょうか?
(meta で SJISを指定してもNG?)

コウノトリ 2000/02/16(水) 11:39:19
取り込んだHTMLを「そのまま」吐き出すなら、現状のままでOKです。
CGI中に埋め込んだ文字列を追加するなどで加工する場合は、文字コードが混在して化けることがあります。
(それ以前に加工に失敗することもある)

snow 2000/02/16(水) 19:37:39
コウノトリさん、ありがとうございます。
CGIでの結果によって、HTML上に表示する文字列を変えようとしているので、今は文字化けしてしまっています。こういった場合は、普通どのような処理をしておけばよいのでしょうか?

saka 2000/02/16(水) 23:49:43
日本語の処理は、ここを参考にしてみてください。
http://www.tohoho-web.com/wwwperl4.htm#Japanese
通常は
sjis -> euc -> sjis
という様なを変換して処理する事になると思います。

私は、CGIの中で直接sjisの漢字を操作したりしてますが..
通常なら変換して処理した方がやり易いと思います。

B-Cus 2000/02/16(水) 23:50:55
全部 EUC にするのが一番簡単。あるいは、SJIS の HTML データを
いじくる必要がなければ、
   FILE *nkfout;
   nkfout = popen("/usr/local/bin/nkf -s","w");
   fprintf(nkfout,"%s",buf);
で、nkf に全部任せるとか。それなりの負荷はかかりますけど。


ところで、perl で言うところの
   open(STDOUT,"|/usr/local/bin/nkf -s");
相当の処理 (標準出力に出力すれば、nkf を経由する)って
C ではどうやるんでしょう?

stdio ライブラリだけでできる?
stdout を fclose(3) して pipe(2) して  fdopen(3)?
pipe(2) して stdout を fclose(3) して dup(2) して fdopen(3)?
# ↑うそくせ〜

Hanhan4 [E-Mail] 2000/02/17(木) 23:25:17
> ところで、perl で言うところの
> open(STDOUT,"|/usr/local/bin/nkf -s");
> 相当の処理 (標準出力に出力すれば、nkf を経由する)って
> C ではどうやるんでしょう?

stdio でよければ popen() を使います。
これは /bin/sh を起動するので UNIX ローカルで使う分には
便利ですが,WWW プログラミングで使うのは要注意です。

/bin/sh を避けたいのならば B-Cus さんが見当を付けている
とおりで pipe(), fork(), exec(), dup(), open(), close()
あたりを駆使します。
ここらへんのことはアスキーの
「UNIX システムコール・プログラミング」に出ています。
ちょっと古い本ですが,UNIX 上のプログラミングの
理解に役立つでしょう。

storms 2000/02/19(土) 00:47:38
> ところで、perl で言うところの
>    open(STDOUT,"|/usr/local/bin/nkf -s");
> 相当の処理 (標準出力に出力すれば、nkf を経由する)って
> C ではどうやるんでしょう?
stdioだけじゃ無理
運が良ければ/dev/fd+freopenで何とかなる、移植性悪いがFILE構造体を弄るよりはまし。

B-Cus 2000/02/19(土) 01:37:44
> 運が良ければ/dev/fd+freopenで何とかなる
これを試してみたんですが、全然わからなかったので
早々にギブアップ。結局まともな方法としては、
fork/exec から自前でやらなきゃダメってことですね。

別に今必要なわけではないので、今後の課題としておきます。

storms 2000/02/19(土) 14:18:36
こんな感じ。
しかし、ここって自信たっぷりに嘘教える人が多いね。

#include <stdio.h>
main()
{
  FILE *p;
  char s[] = "/dev/fd/xx";
  int i;

  if(!(p = popen("cat -n", "w")))
    perror("popen"), exit(1);

  snprintf(s, sizeof(s) - 1 , "/dev/fd/%d", fileno(p));
  if(!freopen(s, "w", stdout))
    perror(s), exit(1);

  for(i = 0; i < 10; i++)
    printf("%c\n", 'a' + i);

  fclose(stdout);
  pclose(p);
}

Hanhan4 [E-Mail] 2000/02/19(土) 18:12:33
ああ,わかった。storms さんは「必要とされている条件は
『標準出力』だから

fp = popen(...);
fprintf(fp, ..);

ではダメだ」とおっしゃるのですね。なるほど。うむう。
私にしてみれば stdout も fp も FILE * の一つなので
「同じじゃん」ということであのように書きました。
うかつだったかな。

どーしても stdout じゃなきゃダメ,fprintf(fp, ...) なんか
許せないということでしたら,これはどうでしょう?

*stdout = *fp;
printf(...);

# われながら屁理屈...
# こういうことをしていいものかどうかも自信がない。

B-Cus 2000/02/19(土) 23:55:15
ん〜、なるほど。/dev/fd/、*stdout=*fp どちらも
Solaris,FreeBSD でうまく動きました。

ディスクリプタ x へ出力 (入力も) するのと
/dev/fd/x へ出力するのは等価なわけですね 。

> # こういうことをしていいものかどうかも自信がない。
どうなんですかね。素人目には問題ないように
思えますが、もちろん根拠ナシ。

storms 2000/02/20(日) 00:13:03
> *stdout = *fp;
> printf(...);
却下

http://www.catnet.ne.jp/~kouno/c_faq/c12.html#33
http://www.catnet.ne.jp/~kouno/c_faq/c12.html#34

B-Cus 2000/02/20(日) 00:25:30
う、C FAQ を調べるのをすっかり忘れてた。

> 却下
その理由をご存知ですか? 移植性の問題?

storms 2000/02/20(日) 00:59:31
> その理由をご存知ですか? 移植性の問題?
ドキュメントで公開されていない構造体に依存してはいけない。
(この場合は構造体のサイズ)

stdlibのユーザに見える構造体と内部で使用している構造体が
同一と言う保証は無い。
例えばユーザみえは
typedef struct {
   ....
} FILE;

stdlibの内部では
struct internal_file_t {
  FILE fp;
  ...
}

storms 2000/02/20(日) 16:48:43
> (この場合は構造体のサイズ)
< (この場合は構造体のサイズおよび構造)

致命的な例
typedef struct file_t {
  struct file_t *next;
  ...
} FILE;
このようにFILE構造体がリンクリストで管理されていて、新規にオープンされたファイル(fp)が
root => stdin => stdout => stderr => fp
となるとする
*stdout = *fp
などすると
root => stdin => fp
とリンクリストが破壊される。

fclose(stdout)した後で
*stdout = *fp
は論外。

B-Cus 2000/02/20(日) 18:07:59
なるほど。ユーザに許されているのは FILE へのポインタを
stdio ライブラリ {から受け取る,に渡す} ことだけであって、
うかつに内部を触ると stdio の実装によっては動かなくなる
かもしれんぞ、ということですね。

ありがとうございました。

[上に] [前に] [次に]