2010-06-22 3 views
0

Я открываю файл CSV и считываю значения из него с помощью File.open (filename).Ruby - Как распаковать двоичную строку в обычную строку?

Так что я сделать что-то вроде этого:

my_file = File.open(filename) 
my_file.each_line do |line| 
line_array = line.split("\t") 
ratio = line_array[1] 
puts "#{ratio}" 
puts ratio.isutf8? 
end 

Проблема у меня есть значения в line_array, кажется, в странном формате. Например, одно из значений в ячейке файла CSV равно 0,86. Когда я распечатываю его, это выглядит как «0. 8 6»

Так что это ведет себя как строка, но я не уверен, как он закодирован. Когда я пытаюсь сделать какую-то интроспекцию:

ratio.isutf8? 
I get this: 
=> undefined method 'isutf8?' for "\0000\000.\0008\0006\000":String 

Что, черт возьми, происходит ?! Как получить отношение к нормальной строке, которую я могу затем вызвать ratio.to_f?

Спасибо.

ответ

2

Похоже, что ваши входные данные закодированы как UTF-16 or UCS-2.

попробовать что-то вроде этого:

require 'iconv' 

ratio = Iconv.conv('UTF-8', 'UTF-16', line_array[1]) 
puts "Ratio is now '#{ratio}'." 

Давай думать об этом, вы, вероятно, следует запустить Iconv.conv по всей линии перед вызовом раскола на него, в противном случае будет бродячие нулевые байты в конце строки (если вы не измените свой разделитель на «\ 000 \ t», который выглядит довольно уродливым.)

+0

Удивительный - позвольте мне попробовать. Позвольте вам знать, как это происходит! – mymmaster

3

Распаковка двоичной строки обычно называется декодированием. Похоже, что ваши данные находятся в UTF-16, но должны найти вам, какую кодировку он фактически использует (например, исследуя рабочий процесс/конфигурацию, которая его создала), прежде чем считать, что это правда.

В Ruby 1.9 (декодирования на лету):

my_file = File.open(filename).set_encoding('UTF-16BE:UTF-8') 
# the rest as in the original 

В Ruby 1.8 (чтение в целом файл, а затем декодировать и разобрать его, может не работать для супер больших файлов):

require 'iconv' 

# … 

my_file = File.open(filename) 
my_text = Iconv.conv('UTF-8', 'UTF-16BE', my_file.read) 
my_text.each_line do |line| 
# the rest as in the original 
end 
+0

Отличный ответ. Благодаря! – mymmaster