Как избежать спотыкания о спецификации UTF-8 при чтении файлов

StackOverflow https://stackoverflow.com/questions/543225

Вопрос

Я использую канал данных, в который недавно был добавлен заголовок спецификации Unicode (U+FEFF), и теперь моя задача по сбору данных из-за этого испорчена.

Я могу пропустить первые 3 байта с помощью file.gets[3..-1] но есть ли более элегантный способ чтения файлов в Ruby, который может справиться с этим правильно, независимо от того, присутствует ли спецификация или нет?

Это было полезно?

Решение

В Ruby 1.9.2 вы можете использовать режим r:bom|utf-8

text_without_bom = nil #define the variable outside the block to keep the data
File.open('file.txt', "r:bom|utf-8"){|file|
  text_without_bom = file.read
}

или

text_without_bom = File.read('file.txt', encoding: 'bom|utf-8')

или

text_without_bom = File.read('file.txt', mode: 'r:bom|utf-8')

Не имеет значения, доступна ли в файле спецификация или нет.


Вы также можете использовать опцию кодирования с другими командами:

text_without_bom = File.readlines(@filename, "r:utf-8")

(Вы получаете массив со всеми строками).

Или с CSV:

require 'csv'
CSV.open(@filename, 'r:bom|utf-8'){|csv|
  csv.each{ |row| p row }
}

Другие советы

Я бы не стал слепо пропускать первые три байта;что если продюсер останавливается добавить спецификацию еще раз?Что вам следует сделать, это исследовать первые несколько байтов, и если они 0xEF 0xBB 0xBF, игнорируйте их.Именно такую ​​форму принимает символ спецификации (U+FEFF) в UTF-8;Я предпочитаю разобраться с этим, прежде чем пытаться декодировать поток, потому что обработка спецификации очень непоследовательна в разных языках/инструментах/фреймворках.

На самом деле, ты такой предполагаемый иметь дело со спецификацией.Если файл был обработан в формате UTF-16, вам необходимо проверить первые два байта, прежде чем начать декодирование, чтобы знать, следует ли читать его как с прямым порядком байтов или с прямым порядком байтов.Конечно, спецификация UTF-8 не имеет ничего общего с порядком байтов, она просто предназначена для того, чтобы вы знали, что используется кодировка UTF-8, если вы еще этого не знали.

Я бы не «доверял» какому-либо файлу в кодировке UTF-8, когда присутствует спецификация 0xEF 0xBB 0xBF, вы можете потерпеть неудачу.Обычно при обнаружении спецификации UTF-8 это, конечно, действительно должен быть файл в кодировке UTF-8.Но если, например, кто-то только что добавил спецификацию UTF-8 в файл ISO, вам не удастся так плохо закодировать такой файл, если в нем есть байты выше 0x0F.Вы можете доверять файлу, если у вас внутри есть только байты до 0x0F, потому что в этом случае это ASCII-файл, совместимый с UTF-8, и в то же время это действительный файл UTF-8.

Если в файле есть не только байты <= 0x0F (после спецификации), чтобы убедиться, что он правильно закодирован UTF-8, вам придется проверить допустимые последовательности и - даже если все последовательности действительны - также проверить, если каждая кодовая точка из последовательности использует самую короткую возможную последовательность, а также проверяет, нет ли кодовой точки, соответствующей суррогату с высоким или низким уровнем.Также проверьте, не превышает ли максимальное количество байтов последовательности 4, а самый высокий код — 0x10FFFF.Самый высокий код ограничивает также биты полезной нагрузки стартового байта не выше 0x4, а полезную нагрузку первого следующего байта - не выше 0xF.Если все упомянутые проверки пройдены успешно, ваша спецификация UTF-8 говорит правду.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top