在D中读取文本文件是否有任何一刀切(或多或少)的方法?
要求是该功能会自动检测编码并以一致的格式提供文件的整个数据,例如string
或dstring
。它应该自动检测BOM并在适当时解释它们。
我尝试了std.file.readText()
,但它不能很好地处理不同的编码。
(当然,这将是一个非零失败率,这对我的应用程序来说是可以接受的。)
答案 0 :(得分:8)
我认为此时Phobos中文件I / O的唯一真正选项(除了调用C函数之外)是std.file.readText
和std.stdio.File
。 readText
将在文件中读取字符,wchars或dchars数组(默认为immutable(char)[] - 即字符串)。我认为编码对于字符,wchars和dchars分别必须是UTF-8,UTF-16和UTF-32,尽管我必须深入挖掘源代码才能确定。任何与这些编码兼容的编码(例如ASCII与UTF-8兼容)应该可以正常工作。
如果您使用File
,那么您可以使用多种选项来读取文件 - 包括readln
和rawRead
。但是,您基本上使用UTF-8,UTF-16或UTF-32兼容编码来读取文件,就像使用readText
一样,或者您将其作为二进制数据读取并自行操作。
因为D中的字符类型分别是char,wchar和dchar,它们分别是UTF-8,UTF-16和UTF-32代码单元,除非你想以二进制格式读取数据,文件是必须以与这三种类型的unicode之一兼容的编码进行编码。给定特定编码中的字符串,您可以使用std.utf
中的函数将其转换为其他编码。但是,除了使用readText
尝试以给定的编码读取文件并查看是否成功之外,我不知道有任何方法可以查询文件的编码类型。
所以,除非你想自己处理一个文件并立即确定它是什么编码,你最好的选择可能只是使用readText
和每个连续的字符串类型,使用第一个成功的字符串。但是,由于文本文件通常采用UTF-8或UTF-8兼容编码,因此我认为与普通字符串一起使用的readText
几乎总能正常工作。
答案 1 :(得分:4)
至于处理检查物料清单:
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是留给读者的练习。