2011-01-17 13 views
8

Dのテキストファイルを読むのにどれほどの方法がありますか?Dのテキストファイルを読む

この機能では、エンコードを自動検出し、stringまたはdstringのように一貫した形式でファイルのデータ全体を渡します。 BOMを自動検出し、適切に解釈する必要があります。

std.file.readText()を試しましたが、別のエンコードをうまく処理しません。

(もちろん、これは非ゼロの故障率を持つことになり、それは私のアプリケーションのための許容可能です。)

答えて

8

を私は信じている私、この時点でのフォボス中/ O(脇からのファイルのための唯一の本当のオプションC関数を呼び出す)はstd.file.readTextstd.stdio.Fileです。 readTextは、char、wchars、またはdcharsの配列としてファイルを読み込みます(デフォルトはimmutable(char)[] - 文字列)。私は、ソースコードを掘り下げなければならないが、エンコーディングはそれぞれchar、wchars、dcharsのUTF-8、UTF-16、UTF-32でなければならないと思う。これらのエンコーディングと互換性のあるエンコーディング(たとえば、ASCIIはUTF-8と互換性があります)はうまく動作します。

Fileを使用する場合は、ファイルを読むための関数がいくつか用意されています(readlnrawReadなど)。しかし、あなたは本質的にUTF-8、UTF-16、またはUTF-32互換のエンコーディングをreadTextのように使用して読み込むか、バイナリデータとして読み込んで操作します。

Dの文字型は、それぞれUTF-8、UTF-16、UTF-32のコード単位であるchar、wchar、およびdcharであるため、バイナリ形式でデータを読み込みたい場合を除き、これら3種類のユニコードのいずれかと互換性のあるエンコードでエンコードする必要があります。特定のエンコーディングの文字列を指定すると、std.utfの関数を使用して別のエンコーディングに変換できます。しかし、特定のエンコーディングでファイルを読み込んで成功するかどうかを確認するために、readTextを使用する以外の方法で、ファイルのエンコーディングタイプを問い合せる方法は認識していません。

ファイルを自分で処理し、どのエンコーディングがあるかを判断しない限り、成功した最初の文字列を使用して、連続した文字列タイプごとにreadTextを使用することをお勧めします。しかし、テキストファイルは通常UTF-8またはUTF-8互換のエンコーディングであるため、普通の文字列で使用されるreadTextはほとんどの場合うまく動作すると思います。

+0

Hm ...任意のアイデアBOMとは何ですか? – Mehrdad

+1

@Lambert、私は非常に検証をしないので、read()を使うことを強くお勧めしますが、あなた自身でそれを行うことができ、複数回に渡ってファイルを読み込んでいません。 BOMの場合は、ubyteにキャストして最初のバイトを比較し、スライスの残りの部分をキャストします。 –

+0

Hm ...私が望んでいた解決策ではありませんでした(手動でBOMをチェックしたくなかった)しかしそれはあまりにも悪いことではないと私は推測する。ありがとう。 – Mehrdad

4

BOMを確認するに対処するためとして:

char[] ConvertViaBOM(ubyte[] data) { 
    char[] UTF8() { /*...*/ } 
    char[] UTF16LE(){ /*...*/ } 
    char[] UTF16BE(){ /*...*/ } 
    char[] UTF32LE(){ /*...*/ } 
    char[] UTF32BE(){ /*...*/ } 

    switch (data.length) { 
    default: 
    case 4: 
     if (data[0..4] == [cast(ubyte)0x00, 0x00, 0xFE, 0xFF]) return UTF32BE(); 
     if (data[0..4] == [cast(ubyte)0xFF, 0xFE, 0x00, 0x00]) return UTF32LE(); 
     goto case 3; 

    case 3: 
     if (data[0..3] == [cast(ubyte)0xEF, 0xBB, 0xBF]) return UTF8(); 
     goto case 2; 

    case 2: 
     if (data[0..2] == [cast(ubyte)0xFE, 0xFF]) return UTF16BE(); 
     if (data[0..2] == [cast(ubyte)0xFF, 0xFE]) return UTF16LE(); 
     goto case 1; 

    case 1: 
     return UTF8(); 
    } 
} 

よりあいまいなBOMのは、読者の演習として残して追加。

関連する問題