2015-10-08 3 views
2

Я имею 10GB данных в бинарных файлах с небольшим форматом Endian и я их преобразования в целое, как:Лучший способ преобразовать Hex строка файла в целое

with open(myfile, 'rb') as inh: 
    data = inh.read() 

for i in range(0, len(data), 4): 
    pos = struct.unpack('i', data[i:i+4]) 

Но это занимает очень много времени, чтобы преобразовать каждый файл с 100 МБ данных. Есть ли способ ускорить процесс?

+2

возможно ТСМА будет быстрее читать 4 байта за один раз –

+1

У файлов есть шестнадцатеричные строки, такие как «FFFF» или двоичные числа, такие как 0xFFFF? –

ответ

4

Если вы не возражаете против использования NumPy, вы можете использовать numpy.memmap:

import numpy as np 

data = np.memmap('foo.bin', dtype='<i4', mode='r') 

Например,

In [122]: !hexdump foo.bin 
0000000 01 00 00 00 02 00 00 00 03 00 00 00 ff 00 00 00 
0000010 00 01 00 00 01 01 00 00 ff ff ff ff fe ff ff ff 
0000020 

In [123]: data = np.memmap('foo.bin', dtype='<i4', mode='r') 

In [124]: data 
Out[124]: memmap([ 1, 2, 3, 255, 256, 257, -1, -2], dtype=int32) 

In [125]: data[6] 
Out[125]: -1 

Это не может быть необходимо для памяти, отображение данных, в этом случае вы можете просто прочитать его в массиве с numpy.fromfile. Например,

In [129]: data = np.fromfile('foo.bin', dtype='<i4') 

In [130]: data 
Out[130]: array([ 1, 2, 3, 255, 256, 257, -1, -2], dtype=int32) 
+0

Возможно ли получить двоичную строку вместо целого типа '100101001000000111010010101011'? Мы подсчитываем фотоны, и я должен разбить двоичную строку на два [от 0 до 28 бит для порядка отсчетов, 29-32 бит - для счетчика. – Aung

+1

Для каждого целого 'a' вы можете попробовать что-то вроде' order = a & (2 ** 29-1) 'и' counter = a >> 29'. Для дальнейшего обсуждения задайте новый вопрос (но сначала попробуйте найти похожие вопросы). –

4

numpy, вероятно, быстрее, но вы также можете позволить struct.unpack сделать цикл вместо Python:

L = struct.unpack('{}i'.format(len(data)//4),data) 

В результате весь список целых чисел распакованы.

Потребовалось несколько секунд, чтобы сделать кадр данных 400 МБ. Вот короткий пример:

>>> L=list(range(20)) 
>>> struct.pack('20i',*L) 
b'\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\t\x00\x00\x00\n\x00\x00\x00\x0b\x00\x00\x00\x0c\x00\x00\x00\r\x00\x00\x00\x0e\x00\x00\x00\x0f\x00\x00\x00\x10\x00\x00\x00\x11\x00\x00\x00\x12\x00\x00\x00\x13\x00\x00\x00' 
>>> b = struct.pack('20i',*L) 
>>> struct.unpack('20i',b) 
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19) 
0

По предложению Padraic Каннингема, используя отображаемые в память файлы:

import mmap 
import contextlib 

with open(myfile, 'rb') as inh: 
    with contextlib.closing(mmap.mmap(inh.fileno(), 0, access=mmap.ACCESS_READ)) as m: 
     for i in range(0, len(m), 4): 
      pos = struct.unpack('i', m[i:i+4]) 

Пожалуйста, ознакомьтесь с here для получения дополнительной информации о mmap модуль в стандартной библиотеке

+0

Вы потеряете прибыль в цикле 'for' Python. –

+0

@MarkTolonen Да, я знаю, что это не может быть лучшим решением. Мой ответ заключается в том, чтобы показать, как это можно сделать с файлами с отображением памяти, так как это довольно близко к коду в вопросе, который читает всю память в памяти – Pynchia

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