读取D中的文本文件

读取D中的文本文件,d,phobos,D,Phobos,是否有任何一刀切(或多或少)的方法来读取D中的文本文件 要求函数自动检测编码并以一致的格式提供文件的全部数据,如字符串或数据字符串。它应该自动检测BOM,并根据需要对其进行解释 我尝试了std.file.readText(),但它不能很好地处理不同的编码 (当然,这将有一个非零的故障率,这对我的应用程序来说是可以接受的。)我认为,在这一点上,Phobos中文件I/O的唯一实际选项(除了调用C函数)是std.file.readText和std.stdio.filereadText将以字符、wcha

是否有任何一刀切(或多或少)的方法来读取D中的文本文件

要求函数自动检测编码并以一致的格式提供文件的全部数据,如
字符串
数据字符串
。它应该自动检测BOM,并根据需要对其进行解释

我尝试了
std.file.readText()
,但它不能很好地处理不同的编码


(当然,这将有一个非零的故障率,这对我的应用程序来说是可以接受的。)

我认为,在这一点上,Phobos中文件I/O的唯一实际选项(除了调用C函数)是
std.file.readText
std.stdio.file
readText
将以字符、wchars或dchars数组的形式读取文件(默认为不可变(char)[]-即字符串)。我认为chars、wchars和dchars的编码必须分别为UTF-8、UTF-16和UTF-32,尽管我必须深入研究源代码才能确定。任何与这些编码兼容的编码(例如,ASCII与UTF-8兼容)都可以正常工作

如果使用
文件
,则可以使用多个函数选项读取文件-包括
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
几乎总是可以正常工作。

至于检查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表留给读者作为练习。

Hm。。。知道如何处理BOM吗?@Lambert,我强烈建议使用read(),因为它不会进行任何验证,但您可以自己执行,并且不会多次读取文件。对于BOM表,您可以强制转换为ubyte并比较第一个字节,然后对切片的其余部分执行强制转换…嗯。。。这不是我希望的解决方案(我不想手动检查BOM),但我想这也不算太糟;谢谢。@Lambert:检查BOM应该不会太糟糕。IIRC它只有32位(或更少),只有大约六个值(包括大/小结束)。@BCS:o__oBOM是32位吗?UTF-8的
0xEF、0xBB、0xBF
呢?