Dのテキストファイルを読むための万能の(多かれ少なかれ)方法はありますか?
要件は、関数がエンコーディングを自動検出し、ファイルのデータ全体をastring
や。などの一貫した形式で提供することdstring
です。BOMを自動検出し、適切に解釈する必要があります。
試しstd.file.readText()
ましたが、異なるエンコーディングをうまく処理できません。
(もちろん、これはゼロ以外の失敗率になります、そしてそれは私のアプリケーションにとって許容できます。)
現時点で(C関数の呼び出しを除いて)PhobosでのファイルI / Oの実際のオプションは、とだけだと思いstd.file.readText
ますstd.stdio.File
。readText
chars、wchars、またはdcharsの配列としてファイルを読み込みます(デフォルトはimmutable(char)[]-つまり文字列)。確実にソースコードを掘り下げる必要がありますが、chars、wchars、およびdcharsのエンコーディングはそれぞれUTF-8、UTF-16、およびUTF-32である必要があると思います。それらのエンコーディングと互換性のあるエンコーディング(たとえば、ASCIIはUTF-8と互換性があります)は問題なく動作するはずです。
を使用する場合は、-includeおよび。File
を使用してファイルを読み取る関数にいくつかのオプションがあります。ただし、基本的には、と同じようにUTF-8、UTF-16、またはUTF-32互換のエンコーディングを使用してファイルを読み取るか、バイナリデータとして読み込んで自分で操作します。readln
rawRead
readText
Dの文字タイプはchar、wchar、およびdcharであり、それぞれUTF-8、UTF-16、およびUTF-32コード単位であるため、データをバイナリ形式で読み取りたい場合を除き、ファイルには次のようになります。これらの3つのタイプのユニコードのいずれかと互換性のあるエンコーディングでエンコードされます。特定のエンコーディングの文字列を指定すると、の関数を使用して別のエンコーディングに変換できますstd.utf
。readText
ただし、特定のエンコーディングでファイルを読み取って成功するかどうかを確認する以外に、ファイルのエンコーディングタイプをクエリする方法を知りません。
readText
したがって、ファイルを自分で処理して、そのファイルがどのエンコーディングであるかをその場で判断したい場合を除いて、おそらく、成功する最初の文字列を使用して、連続する各文字列タイプで使用するのが最善の策です。ただし、テキストファイルは通常UTF-8またはUTF-8互換のエンコーディングであるreadText
ため、通常の文字列で使用すると、ほとんどの場合問題なく機能すると思います。
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を追加することは、読者の演習として残されています。