Читать текстовый файл в D - PullRequest
8 голосов
/ 18 января 2011

Существует ли какой-либо универсальный (более или менее) способ чтения текстового файла в D?

Требуется, чтобы функция автоматически определяла кодировку и выдавала мне все данные файла в согласованном формате, например string или dstring. Он должен автоматически определять спецификации и интерпретировать их соответствующим образом.

Я пытался std.file.readText(), но он плохо обрабатывает разные кодировки.

(Конечно, это будет иметь ненулевую частоту отказов, и это приемлемо для моего приложения.)

Ответы [ 2 ]

8 голосов
/ 18 января 2011

Я считаю, что единственными реальными вариантами ввода / вывода файлов в Фобосе на данный момент (кроме вызова функций C) являются std.file.readText и std.stdio.File. readText будет считываться в файле как массив символов, wchars или dchars (по умолчанию неизменяемый (char) [] - то есть строка). Я считаю, что кодировка должна быть UTF-8, UTF-16 и UTF-32 для chars, wchars и dchars соответственно, хотя я должен был бы покопаться в исходном коде, чтобы быть уверенным. Любые кодировки, которые совместимы с этими кодировками (например, ASCII совместим с UTF-8), должны нормально работать.

Если вы используете File, у вас есть несколько опций для функций чтения файла, включая readln и rawRead. Однако вы, по сути, читаете файл, используя кодировку, совместимую с UTF-8, UTF-16 или UTF-32, точно так же, как с readText, или считываете его как двоичные данные и управляете им самостоятельно.

Поскольку типами символов в D являются char, wchar и dchar, которые являются кодовыми единицами UTF-8, UTF-16 и UTF-32 соответственно, если вы не хотите читать данные в двоичном формате, файл придется кодировать в кодировке, совместимой с одним из этих трех типов юникода. Задав строку в определенной кодировке, вы можете преобразовать ее в другую кодировку, используя функции из std.utf. Однако я не знаю ни одного способа запросить у файла тип кодировки, кроме использования readText, чтобы попытаться прочитать файл в заданной кодировке и посмотреть, удастся ли это.

Итак, если вы не хотите обрабатывать файл самостоятельно и определять на лету, в какой кодировке он находится, лучше всего просто использовать readText с каждым последовательным типом строки, используя первый, который завершится успешно. Однако, поскольку текстовые файлы обычно имеют кодировку UTF-8 или UTF-8, я ожидаю, что readText, используемый с нормальной строкой, почти всегда будет работать нормально.

4 голосов
/ 19 января 2011

Что касается проверки спецификации:

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();
  }
}

Добавление более неясных спецификаций оставлено читателю в качестве упражнения.

...