2013-09-04 3 views
1

У меня есть двоичный файл, который хранит числа как повторение двух беззнаковых 32-битных целых чисел, за которыми следует одно целое число без знака. Я читаю этот файл как строку и хочу его декодировать в массив массивов, каждый из которых содержит три числа. Так что я делаю это:Распаковать двоичный файл, содержащий повторения

File.open("file", "r"){|f| f.read.unpack("LLC")} 

Однако, это не работает, так как он обрабатывает только первые три числа в файле. Это также не работает:

File.open("file", "r"){|f| f.read.unpack("LLC*")} 

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

+0

Это сообщение было ответил "f.read.unpack ('L * L * C *') each_slice (3) .to_a" , Это отличный ответ, который делает именно то, что мне нужно; пожалуйста, верните ответ, чтобы я мог проголосовать за него. –

+0

После публикации я экспериментировал и обнаружил, что это неправильное решение. давая неправильный результат. – falsetru

+0

Например, '' \ x01 \ x00 \ x00 \ x00 \ x02 \ x00 \ x00 \ x00 \ x03 \ x04 \ x00 \ x00 \ x00 \ x05 \ x00 \ x00 \ x00 \ x06 ".unpack ('L * L * C * '). Each_slice (3) .to_a' дает '[[1, 2, 1027], [1280, 0, 6]]', пока я ожидал '[[1,2,3], [4,5 , 6]] '. (предположим, немного endian) – falsetru

ответ

1

Попробуйте следующее:

File.open("file", "rb") { |f| 
    result = [] 
    while true 
    data = f.read(9) 
    break unless data && data.length == 9 
    result << data.unpack('LLC') 
    end 
    result 
} 

КСТАТИ использовать бинарный режим (rb).


АЛЬТЕРНАТИВНЫЙ:

File.open("file", "rb") { |f| 
    result = f.read.chars.each_slice(9).map { |data| 
    data.join.unpack("LLC") 
    } 
} 

"\x01\x00\x00\x00\x02\x00\x00\x00\x03\x04\x00\x00\x00\x05\x00\x00\x00\x06".chars.each_slice(9).map { |chs| chs.join.unpack("LLC") } 
# => [[1, 2, 3], [4, 5, 6]] 
Смежные вопросы