Reading textual data

この記事では、ストリーム、ファイル、ソケットからテキストデータを読み込む方法を説明します。

警告:この記事では仕様が未確定のインタフェースを使用しています。これらのインタフェースは新しい Mozilla では変更になる可能性があり、そのときはコードが機能しなくなるかもしれません。

テキストデータを読み込むには、そのデータがどんな 文字エンコーディング なのかを知る必要があります。ファイルやネットワークソケットは、文字ではなくバイト列から成り立っています。このバイト列に意味を持たせるために文字エンコーディングを知る必要があるのです。

データの文字エンコーディングの決定

ネットワークチャンネル (nsIChannel) を使っているのであれば、その contentCharset プロパティを使うことができます。すべてのチャンネルからデータの文字エンコーディングがわかるわけではないので注意してください。代わりに、設定(intl.charset.default、ローカライズされた設定値)で保存されているデフォルトの文字エンコーディングを使うこともできます。

ファイルから読み込むとなると、これは答えづらい質問です。システムの文字エンコーディングを使うとうまくいくかもしれません。また、同様に設定からデフォルトの文字エンコーディングを取得し、それを使ってもいいでしょう。

Gecko 1.8 以降

文字列の読み込み

Gecko 1.8 (SeaMonkey 1.0、Firefox 1.5) では、ストリーム (nsIInputStream) から文字列を読み込むのに nsIConverterInputStream を使うことができます。この作業は バグ 295047 でなされました。

使用法:

var charset = /* 文字エンコーディングを調べる必要あり。この例では UTF-8 を使用。 */ "UTF-8";
const replacementChar = Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER;
var is = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
                   .createInstance(Components.interfaces.nsIConverterInputStream);
is.init(fis, charset, 1024, replacementChar);

すると、is から文字列を読み込むことができます:

var str = {};
var numChars = is.readString(4096, str);
if (numChars != 0 /* EOF */)
  var read_string = str.value;

ストリーム全体を読み取り、そのデータを処理するには:

var str = {};
while (is.readString(4096, str) != 0) {
  processData(str.value);
}

一通り終わったら、ストリームを閉じるのを忘れないでください (is.close())。プラットフォームによっては、その作業を忘れると後でファイルをリネームしたり削除しようとしたときに問題が生じることもあります。

特にファイル(ストリーム)の終わりだと(この場合だけというわけではありません)、要求より少ない文字を得ることになるかもしれないということに注意してください。

未サポートのバイト列

対応する妥当な文字がないバイト列に対してどのような処理をするかを指定することができます。init の最後の(第 4)引数を使って置換すべき文字を指定します。nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER は U+FFFD 置換文字であり、これを使うのがよいでしょう。

置換を望まないのであれば、置換文字として 0x0000 を指定できます。そうすると、未サポートのバイトに達すると readString が例外を投げます。

行の読み込み

nsIUnicharLineInputStream インタフェースを使用すると、簡単に Unicode 文字のストリームから行全体を読み込めるようになります。これが非 ASCII 文字をサポートしているのを除いて、nsILineInputStream と同じように使うことができます。また、ヌルが埋め込まれた文字集合(UTF-16 や UTF-32)を問題なく扱えます。

使用例:

var charset = /* 文字エンコーディングを調べる必要あり。この例では UTF-8 を使用。 */ "UTF-8";
var is = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
                   .createInstance(Components.interfaces.nsIConverterInputStream);
// ここで、fis は読み込み元にしたい nsIInputStream と仮定
is.init(fis, charset, 1024, 0xFFFD);
if (is instanceof Components.interfaces.nsIUnicharLineInputStream) {
  var line = {};
  var cont;
  do {
    cont = is.readLine(line);

    // line.value を利用できるようになった
  } while (cont);
}

この例では EOF までストリーム全体を読み込みます。

もっと古いバージョン

文字列の読み込み

古い gecko にはストリームから unicode データを読み込む簡単な方法はありません。手動でデータのブロックを読み込み、nsIScriptableUnicodeConverter を使って変換しなければなりません。

例:

// まずコンバータの取得と初期化
var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
                          .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
converter.charset = /* 使いたい文字エンコーディング:この例では UTF-8 */ "UTF-8";

// ストリームから文字列の読み込み
// ここで istream は読み込み元にしたいストリームと仮定
var scriptableStream = Components.classes["@mozilla.org/scriptableinputstream;1"]
                                 .createInstance(Components.interfaces.nsIScriptableInputStream);
scriptableStream.init(istream);
var chunk = scriptableStream.read(4096);
var text = converter.ConvertToUnicode(chunk);

しかしながら、UTF-16 や UTF-32 のような、ヌルが埋め込まれたバイトがある文字エンコーディングではこのメソッドは機能しないことに注意してください。

行の読み込み

ストリームから unicode 行を読み込む、簡単で一般的な方法というものはありません。

ローカルファイルから行を読み込むという限られた用途では、以下の nsIScriptableUnicodeConverter を使ったコードでうまくいきます。UTF-16 や UTF-32 のようなヌルが埋め込まれた文字エンコーディングでは、このコードはうまくいきません

// まずコンバータの取得と初期化
var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
                          .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
converter.charset = /* 使いたい文字エンコーディング:この例では UTF-8 */ "UTF-8";

// 'file' は 読み込みたいファイルを示す nsIFile の変数と仮定
var fis = Components.classes["@mozilla.org/network/file-input-stream;1"]
                    .createInstance(Components.interfaces.nsIFileInputStream);
fis.init(file, -1, -1, 0);

var lis = fis.QueryInterface(Components.interfaces.nsILineInputStream);
var lineData = {};
var cont;
do {
  cont = lis.readLine(lineData);
  var line = converter.ConvertToUnicode(lineData.value);

  // line を利用できるようになった

} while (cont);
fis.close();


関連項目

ドキュメントのタグと貢献者

 このページの貢献者: Marsf, Electrolysis, Akanemoto
 最終更新者: Marsf,