2015-04-22 6 views
0

Мне просто интересно, как функция фактически хранит данные. Потому что для меня это выглядит совершенно странно. Скажем, у меня есть следующий код:numpy.array.tofile() двоичный файл выглядит «странно» в блокноте ++

import numpy as np 
filename = "test.dat" 
print(filename) 
fileobj = open(filename, mode='wb') 
off = np.array([1, 300], dtype=np.int32) 
off.tofile(fileobj) 
fileobj.close() 

fileobj2 = open(filename, mode='rb') 
off = np.fromfile(fileobj2, dtype = np.int32) 
print(off) 
fileobj2.close() 

Теперь я ожидаю 8 байт внутри файла, где каждый элемент представлен 4 байта (и я мог бы жить с любыми байтами). Однако, когда я открываю файл в шестнадцатеричном редакторе (используется Notepad ++ с шестигранной редактор плагин) Я получаю следующие байты:

01 00 C4 AC 00 

5 байт, и я понятия не имею, на все, что он представляет. Первый байт выглядит так, как будто это число, но тогда что-то странное, конечно, не «300».

Но перезагрузка показывает исходный массив.

Это что-то, что я не понимаю в python, или это проблема в блокноте ++? - Я замечаю, что hex выглядит иначе, если я выбираю другую «кодировку» (да?). Также: Windows сообщает, что она имеет длину 8 байтов.

+2

Во-первых, 'int32' занимает 4 байта, а не 2. – abarnert

+3

Далее вы пробовали читать файл в любой другой программе, кроме Notepad ++? Вы можете сделать это довольно легко в самом Python; вместо 'off = np.fromfile (fileobj2, dtype = np.int32)', просто сделайте 'off = fileobj2.read()', а затем напечатайте байты. Вы должны увидеть что-то вроде 'b '\ x01 \ x00 \ x00 \ x00, \ x01 \ x00 \ x00''; если вы видите 'b '\ x01 \ x00 \ xc4 \ xac \ x00'', то вы знаете, что это файл, который был сломан, а не Notepad ++. – abarnert

+0

@abarnert, который был на самом деле опечаткой (уведомление я уже сказал «Я ожидаю 8 байт ...»). Хм, похоже, что notepad ++ сломан, это странно, никогда раньше этого не было: /, могу ли я спросить/преобразовать этот вопрос в «как сделать notepad ++ работу с шестнадцатеричным плагином» или это слишком offtopic здесь? – paul23

ответ

2

Вы можете сказать, очень легко, что файл на самом деле делает есть 8 байт, те же 8 байт вы ожидали бы (01 00 00 00 2C 01 00 00), просто используя ничего, кроме Notepad ++, чтобы посмотреть файл, в том числе просто заменить ваш off = np.fromfile(fileobj2, dtype=np.int32) с off = fileobj2.read() then print ing the bytes (which will give you b '\ x01 \ x00 \ x00 \ x00, \ x01 \ x00 \ x00'` *).

И, из ваших комментариев, после того, как я предложил это, вы попробовали это и увидели именно это.

Это означает, что это ошибка в Notepad ++ или проблема с тем, как вы ее используете; Python, NumPy и ваш собственный код отлично подходят.


* В случае, если это не ясно: '\x2c' и ',' такие же характер, и bytes использует для печати представление ASCII для печатаемых символов ASCII, а также знакомые побеги как '\n', когда это возможно, только с помощью шестнадцатеричная обратная косая черта для других значений.

+0

Почему мы ожидаем всего восемь байтов? не представляет собой размерность сохраненного массива? если нет, то как бы, например, 5-мерный массив отличался от 10-D, если бы оба имели одинаковое количество элементов? – dbliss

+1

@dbliss: Короткий ответ: нет, их нет, и поэтому мы ожидаем 8 байтов. Это объясняет 'tofile' /' fromfile' docs. Но вы можете легко протестировать его с помощью 'np.array ([[1,2], [3,4]], dtype = np.int8) .tofile (f)', затем 'a = np.fromfile (f, dtype = np.int8) '; вы возвращаетесь '[1,2,3,4]', а не '[[1,2], [3,4]]'. – abarnert

+1

@dbliss: Обратите внимание, что он даже не сохраняет тип данных. Это означает, что в дополнение к потере информации о шагах измерения (и C против Fortran), вы также теряете информацию о сущности, различиях в реализации платформы float и т. Д. Это предназначено для «быстрого хранения», где вы выгружаете данные и читаете их обратно в том же сеансе, например, у вас недостаточно памяти для одновременного хранения всех ваших массивов или вы хотите передать их дочернию «многопроцессорности». – abarnert

0

Что вы ожидаете от 300?

Написать массив, и читать его обратно в двоичном виде (в IPython):

In [478]: np.array([1,300],np.int32).tofile('test') 

In [479]: with open('test','rb') as f: print(f.read()) 
b'\x01\x00\x00\x00,\x01\x00\x00' 

Есть 8 байт, , просто отображаемые байты.

На самом деле, я не должен идти через файл, чтобы получить это:

In [505]: np.array([1,300]).tostring() 
Out[505]: b'\x01\x00\x00\x00,\x01\x00\x00' 

Сделайте то же самое с:

[255]  
b'\xff\x00\x00\x00' 

[256] 
b'\x00\x01\x00\x00' 

[300] 
b',\x01\x00\x00' 

[1,255] 
b'\x01\x00\x00\x00\xff\x00\x00\x00' 

С силами 2 (и 1 меньше) это легко идентифицировать шаблон в байтах.


frombuffer преобразует строку байт обратно в массив:

In [513]: np.frombuffer(np.array([1,300]).tostring(),int) 
Out[513]: array([ 1, 300]) 

In [514]: np.frombuffer(np.array([1,300]).data,int) 
Out[514]: array([ 1, 300]) 

Судя из этого последнего выражения, то tofile только записи буфера массива в файл в байтах.

+0

Но его вопрос в том, почему он получает 5 байтов '01 00 C4 AC 00' вместо 8 байтов' 01 00 00 00 2C 01 00 00'; это не отвечает на это вообще. – abarnert

+0

Но это дает ему способ проверить файл из Python. Предполагая, что он получает то же самое, тогда проблема явно связана с «notepad ++». Я позволю другим решить эту проблему, поскольку у меня нет этого редактора на стороне Linux моей машины. Плюс тестирование с легко узнаваемым значением, например, 255 или 256, может помочь. – hpaulj

+0

Если вы прочтете комментарии, он уже выполнил эквивалентный тест за 7 часов до того, как вы напишете ответ. Да, было бы лучше, если бы он отредактировал вопрос, чтобы сделать это ясно, вместо того, чтобы просто писать комментарий, но это все еще не означает, что это полезный ответ на вопрос, как заданный, так и предполагаемый. – abarnert

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