2016-10-14 2 views
2

Я пытаюсь создать инструмент для очистки имен пользователей из файлов журнала Minecraft. В них есть много символов раздела, потому что это то, что игра использует для форматирования цветов, и я хочу удалить их и следующий символ из каждой строки файла. Однако, когда я пытаюсь прочитать файл с Ruby, я не могу получить нужный символ. Чтобы попытаться понять это, я проверил множество файлов, содержащих знак раздела разными способами. Файлы: a.log, b.log и c.log.Почему символ раздела (§) не читается правильно в зависимости от того, где он был создан?

  • a.log был создан echo ИНГ § в файл
  • b.log был создан cat ИНГАМИ один из моих собственных логов Minecraft, а затем удалить все другие символы в Vim
  • c.log был создан в блокноте

Когда я смотрю на них в блокноте, все они будут правильно отображаться:

a.log:
a.log in notepad
b.log:
b.log in notepad
c.log:
c.log in notepad

Это то же самое, когда я смотрю на них все в Vim:

logfiles in vim

Тогда вещи начинают стать странным Я открываю их в Ruby. Вот код, который я использовал:

a = File.open("./a.log") 
aa = a.read 
puts aa.encoding 
puts aa.ord 
puts aa 

b = File.open("./b.log") 
bb = b.read 
puts bb.encoding 
puts bb.ord 
puts bb 

c = File.open("./c.log") 
cc = c.read 
puts cc.encoding 
puts cc.ord 
puts cc 

А вот выход:

IBM437 
239 
§ 
IBM437 
167 
▒ 
IBM437 
167 
▒ 

Я подумал, что, возможно, это был просто Руби быть странным, пока я не использовал cat, чтобы отобразить содержимое каждого файла:

$ cat a.log b.log c.log 
§ 
▒ 
▒ 

Это не имеет никакого смысла, потому что кодировка была показана одинаковой. Поэтому я решил открыть каждый файл в шестнадцатеричном зрителя (HxD):

a.log:
a.log in hex viewer
b.log:
b.log in hex viewer
c.log:
c.log in hex viewer

Что !? Все они содержат один и тот же символ. Единственное различие между тем, которое работает, и теми, что нет, EF BB BF C2 в a.log! Почему это имеет значение, и как я могу исправить это, чтобы он работал с Ruby's gsub?

(Я попытался сделать это, используя кучу вещей, которые я нашел в Интернете с String.force_encoding и String.encode, но не получил нигде, кроме как начать видеть градусные символы на выходе. Если вы можете привести пример который работает для всех трех типов журнальных файлов, я был бы очень признателен.)

EDIT: Я немного поиграл и нашел, что это необходимо для байта C2. UTF-8 использует 0xC2 0xA7, а UTF-16 использует 0x00A7. Что я могу сделать для правильной конвертации (и почему у Notepad и Vim нет какой-либо проблемы, отображающей ее как знак раздела?)

+0

Какую версию Ruby вы используете (<2.0)? Возможно, вас заинтересует [Byte Order Mark] (https://en.wikipedia.org/wiki/Byte_order_mark). – spickermann

+0

@spickermann 'ruby 2.3.1p112 (версия 2016-04-26 54768) [i386-mingw32]' – Peril

ответ

1

Проблема в том, что некоторые системы не всегда уверены в том, какую кодировку они используют. В этом случае Ruby считает, что входной файл IBM437, но когда мы просматриваем эту кодовую страницу, символ в A7 не является секвенсором. Зачастую интерпретатор будет смешивать ISO-8859-1, IBM437 и другие кодировки. ISO-8859-1 имеет символ раздела в A7, поэтому на самом деле это правильная кодировка. Причина, по которой Notepad и Vim могут правильно отобразить ее, - это то, что они лучше угадывают кодировку, чем cat и интерпретатор Ruby.

Чтобы исправить это, используйте только force_encoding с ISO-8859-1, а затем encode! до UTF-8.

1

Убедитесь, что ваш исходный файл ruby ​​также закодирован в кодировке UTF-8. Я видел симптомы, которые вы описываете много раз, используя PHP: мои исходные файлы были в ISO и доступ к XML или другим данным в UTF-8 - или наоборот.

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

 Смежные вопросы

  • Нет связанных вопросов^_^