Как побайтово считать файл python
у меня есть файл, где первый байт содержит закодированную информацию. В Matlab я могу читать байт бит за битом с помощью var = fread(file, 8, 'ubit1') , а затем получить каждый бит по var(1), var(2) , etc.
есть ли эквивалентный бит-ридер в python?
прочитайте биты из файла, сначала низкие биты.
наименьшая единица, с которой вы сможете работать, - это байт. Для работы на битовом уровне необходимо использовать побитовые операторы.
вы не сможете читать каждый бит один за другим - вы должны читать его байт за байтом. Вы можете легко извлечь биты, хотя:
С numpy это легко, как это:
чтобы прочитать байт из файла: bytestring = open(filename, 'rb').read(1) . Примечание: файл открывается в бинарные режим.
чтобы получить биты, преобразуйте bytestring в целое число: byte = bytestring[0] (Python 3) или byte = ord(bytestring[0]) (Python 2) и извлеките нужный бит: (byte >> i) & 1 :
существует два возможных способа вернуть i-й бит байта. "Первый бит" может относиться к биту высокого порядка или к биту нижнего порядка.
здесь-это функция, которая принимает строку и индекс в качестве параметров и возвращает значение бита в этом месте. Как написано, он рассматривает бит низкого порядка как Первый БИТ. Если вы хотите бит высокого порядка первым, просто раскомментируйте указанную строку.
индексирование начинается с 0. Если вы хотите индексирование, чтобы начать с 1, Вы можете настроить индекс в функции перед вызовом divmod .
теперь, как это работает:
- i : индекс правильного байта в строке
- j : индекс правильного бита в пределах этого байта
мы используем ord() функция преобразования символа в string[i] в целочисленный тип. Затем: (1 << j) вычисляет значение j-го бита по левому сдвигу 1 на j . Наконец, мы используем побитовое-и для проверки, установлен ли этот бит. Если да, возвращает 1, иначе возвращает 0.
для каждого байта, считанного из файла. Результаты для примера 0x88 byte:
вы можете назначить его переменной и работать в соответствии с вашим первоначальным запросом. " " должен гарантировать полную длину байта
Это довольно быстро, я думаю:
Предположим, у вас есть файл с именем bloom_filter.bin, который содержит массив битов, и вы хотите прочитать весь файл и использовать эти биты в массив.
сначала создайте массив, где биты будут храниться после чтения,
открыть файл, используя open или with, все в порядке. Я придерживаюсь open здесь,
В Python, как я читаю в двоичном файле и петлю над каждым байтом этого файла?
По предложению chrispy:
Обратите внимание, что оператор with не доступен в версиях Python ниже 2.5. Чтобы использовать его в версии 2.5, вам необходимо импортировать его:
В 2.6 это не требуется.
В Python 3 это немного отличается. Мы больше не будем получать сырые символы из потока в байтовом режиме, кроме байт-объектов, поэтому нам нужно изменить условие:
Или, как говорит benhoyt, пропустите не равное и воспользуйтесь тем, что b"" оценивается как false. Это делает код совместимым между 2.6 и 3.x без каких-либо изменений. Это также избавит вас от изменения условия, если вы переходите из режима байта в текст или наоборот.
Этот генератор дает байты из файла, считывая файл в кусках:
Информацию о iterators и .
Если файл не слишком большой, что проблема с хранением в памяти - это проблема:
где process_byte представляет некоторую операцию, которую вы хотите выполнить на байте с передачей.
Если вы хотите обработать фрагмент за раз:
Для чтения файла - по одному байту за раз (без учета буферизации) - вы можете использовать встроенную функцию two-argument iter(callable, sentinel) :
Он вызывает file.read(1) , пока не вернет ничего b'' (пустая bytestring). Для больших файлов память не увеличивается неограниченно. Вы можете передать buffering=0 в open() , чтобы отключить буферизацию - это гарантирует, что на каждую итерацию (медленную) считывается только один байт.
with -statement автоматически закрывает файл - включая случай, когда код под ним вызывает исключение.
Несмотря на наличие внутренней буферизации по умолчанию, все равно неэффективно обрабатывать один байт за раз. Например, здесь утилита blackhole.py , которая ест все, что ей дано:
1.5 GB/s, когда chunksize == 32768 на моей машине и только
7.5 MB/s, когда chunksize == 1 . То есть, в 200 раз медленнее читать по одному байту за раз. Учитывайте это, если вы можете переписать свою обработку для использования более одного байта за раз, и если вам нужна производительность.
mmap позволяет обрабатывать файл как bytearray и объект файла одновременно. Он может служить альтернативой загрузке всего файла в память, если вам нужен доступ к обоим интерфейсам. В частности, вы можете перебирать один байт за один раз над файлом с отображением памяти, используя простой for -loop:
Большие объемы данных хранят не в списках или словарях, а в файлах и базах данных. В этом уроке изучим особенности работы с текстовыми файлами в Python. Такие файлы рассматриваются как содержащие символы и строки.
Бывают еще байтовые (бинарные) файлы, которые рассматриваются как потоки байтов. Побайтово считываются, например, файлы изображений. Работа с бинарными файлами несколько сложнее. Нередко их обрабатывают с помощью специальных модулей Python (pickle, struct).
Работа с бинарными файлами несколько сложнее. Нередко их обрабатывают с помощью специальных модулей Python (pickle, struct). В этом уроке будут рассмотрены базовые приемы чтения текстовых файлов и записи в них.
Функция open
Связь с файлом на жестком диске выполняется с помощью встроенной в Python функции open() . Обычно ей передают один или два аргумента. Первый – имя файла или имя с адресом, если файл находится не в том каталоге, где находится сама программа. Второй аргумент – режим, в котором открывается файл.
Обычно используются режимы чтения ( 'r' ) и записи ( 'w' ). Если файл открыт в режиме чтения, то запись в него невозможна. Можно только считывать данные. Если файл открыт в режиме записи, то в него можно только записывать данные, считывать нельзя.
Если файл открывается в режиме 'w' , то все данные, которые в нем были до этого, стираются. Файл становится пустым. Если не надо удалять существующие в файле данные, тогда следует использовать вместо режима записи, режим дозаписи ( 'a' ).
Если файл отсутствует, то открытие его в режиме 'w' создаст новый файл. Бывают ситуации, когда надо гарантировано создать новый файл, избежав случайной перезаписи данных существующего. В этом случае вместо режима 'w' используется режим 'x' . В нем всегда создается новый файл для записи. Если указано имя существующего файла, то будет выброшено исключение. Потери данных в уже имеющемся файле не произойдет.
Если при вызове open() второй аргумент не указан, то файл открывается в режиме чтения как текстовый файл. Чтобы открыть файл как байтовый, дополнительно к букве режима чтения/записи добавляется символ 'b' . Буква 't' обозначает текстовый файл. Поскольку это тип файла по умолчанию, то обычно ее не указывают.
Нельзя указывать только тип файла, то есть open("имя_файла", 'b') есть ошибка, даже если файл открывается на чтение. Правильно – open("имя_файла", 'rb') . Только текстовые файлы мы можем открыть командой open("имя_файла") , потому что и 'r' и 't' подразумеваются по-умолчанию.
Функция open() возвращает объект файлового типа. Его надо либо сразу связать с переменной, чтобы не потерять, либо сразу прочитать.
Чтение файла
С помощью файлового метода read() можно прочитать файл целиком или только определенное количество байт. Пусть у нас имеется файл data.txt с таким содержимым:
Откроем его и почитаем:
Сначала считываются первые десять символов. Последующий вызов read() считывает весь оставшийся текст. После этого объект файлового типа f1 становится пустым.
Заметим, что метод read() возвращает строку, и что конец строки считывается как '\n' .
Для того, чтобы читать файл построчно существует метод readline() :
Метод readlines() считывает сразу все строки и создает список:
Объект файлового типа относится к итераторам. Из таких объектов происходит последовательное извлечение элементов. Элементами в данном случае являются строки-линии файла. Поэтому считывать данные из них можно сразу в цикле без использования методов чтения:
Здесь выводятся лишние пустые строки, потому что функция print() преобразует '\n' в переход на новую строку. К этому добавляет свой переход на новую строку. Создадим список строк файла без '\n' :
Переменной i присваивается очередная строка файла. Мы берем ее срез от начала до последнего символа, не включая его. Следует иметь в виду, что '\n' это один символ, а не два.
Запись в файл
Запись в файл выполняется с помощью методов write() и writelines() . Во второй можно передать структуру данных:
Метод write() возвращает количество записанных символов.
Закрытие файла
После того как работа с файлом закончена, важно не забывать его закрыть, чтобы освободить место в памяти. Делается это с помощью файлового метода close() . Свойство файлового объекта closed позволяет проверить закрыт ли файл.
Если файл открывается в заголовке цикла ( for i in open('fname') ), то видимо интерпретатор его закрывает при завершении работы цикла или через какое-то время.
Практическая работа
Создайте файл data.txt по образцу урока. Напишите программу, которая открывает этот файл на чтение, построчно считывает из него данные и записывает строки в другой файл ( dataRu.txt ), заменяя английские числительные русскими, которые содержатся в списке ( ["один", "два", "три", "четыре", "пять"] ), определенном до открытия файлов.
Создайте файл nums.txt , содержащий несколько чисел, записанных через пробел. Напишите программу, которая подсчитывает и выводит на экран общую сумму чисел, хранящихся в этом файле.
Примеры решения и дополнительные уроки в android-приложении и pdf-версии курса
На этом занятии мы поговорим, как в Python можно считывать информацию из файлов и записывать ее в файлы. Что такое файлы и зачем они нужны, думаю объяснять не надо, т.к. если вы дошли до этого занятия, значит, проблем с пониманием таких базовых вещей у вас нет. Поэтому сразу перейдем к функции
open(file [, mode=’r’, encoding=None, …])
- file – это путь к файлу вместе с его именем;
- mode – режим доступа к файлу;
- encoding – кодировка файла.
Для начала определимся с понятием «путь к файлу». Представим, что наш файл ex1.py находится в каталоге app:
Тогда, чтобы обратиться к файлу my_file.txt путь можно записать так:
Последние два варианта представляют собой абсолютный путь к файлу, то есть, полный путь, начиная с указания диска. Причем, обычно используют обратный слеш в качестве разделителя: так короче писать и такой путь будет корректно восприниматься как под ОС Windows, так и Linux. Первый же вариант – это относительный путь, относительно рабочего каталога.
Теперь, предположим, мы хотим обратиться к файлу img.txt. Это можно сделать так:
Для доступа к out.txt пути будут записаны так:
Обратите внимание, здесь две точки означают переход к родительскому каталогу, то есть, выход из каталога app на один уровень вверх.
И, наконец, для доступа к файлу prt.dat пути запишутся так:
Вот так следует прописывать пути к файлам. В нашем случае мы имеем текстовый файл «myfile.txt», который находится в том же каталоге, что и программа ex1.py, поэтому путь можно записать просто указав имя файла:
В результате переменная file будет ссылаться на файловый объект, через который и происходит работа с файлами. Если указать неверный путь, например, так:
то возникнет ошибка FileNotFoundError. Это стандартное исключение и как их обрабатывать мы с вами говорили на предыдущем занятии. Поэтому, запишем этот критический код в блоке try:
Изменим имя файла на верное и посмотрим, как далее можно с ним работать. По умолчанию функция open открывает файл в текстовом режиме на чтение. Это режим
Если нам нужно поменять режим доступа к файлу, например, открыть его на запись, то это явно указывается вторым параметром функции open:
- 'rt' – чтение в текстовом режиме;
- 'wb' – запись в бинарном режиме;
- 'a+' – дозапись или чтение данных из файла.
Чтение информации из файла
В чем отличие текстового режима от бинарного мы поговорим позже, а сейчас откроем файл на чтение в текстовом режиме:
и прочитаем его содержимое с помощью метода read:
Теперь все будет работать корректно. Далее, в методе read мы можем указать некий числовой аргумент, например,
Тогда из файла будут считаны первые два символа. И смотрите, если мы запишем два таких вызова подряд:
то увидим, что при следующем вызове метод read продолжил читать следующие два символа. Почему так произошло? Дело в том, что у файлового объекта, на который ссылается переменная file, имеется внутренний указатель позиции (file position), который показывает с какого места производить считывание информации.
Когда мы вызываем метод read(2) эта позиция автоматически сдвигается от начала файла на два символа, т.к. мы именно столько считываем. И при повторном вызове read(2) считывание продолжается, т.е. берутся следующие два символа. Соответственно, позиция файла сдвигается дальше. И так, пока не дойдем до конца.
Но мы в Python можем управлять этой файловой позицией с помощью метода
Например, вот такая запись:
будет означать, что мы устанавливаем позицию в начало и тогда такие строчки:
будут считывать одни и те же первые символы. Если же мы хотим узнать текущую позицию в файле, то следует вызвать метод tell:
Следующий полезный метод – это readline позволяет построчно считывать информацию из текстового файла:
Здесь концом строки считается символ переноса ‘\n’, либо конец файла. Причем, этот символ переноса строки будет также присутствовать в строке. Мы в этом можем убедиться, вызвав дважды эту функцию:
Здесь в консоли строчки будут разделены пустой строкой. Это как раз из-за того, что один перенос идет из прочитанной строки, а второй добавляется самой функцией print. Поэтому, если их записать вот так:
то вывод будет построчным с одним переносом.
Если нам нужно последовательно прочитать все строчки из файла, то для этого обычно используют цикл for следующим образом:
Этот пример показывает, что объект файл является итерируемым и на каждой итерации возвращает очередную строку.
Или же, все строчки можно прочитать методом
и тогда переменная s будет ссылаться на упорядоченный список с этими строками:
Однако этот метод следует использовать с осторожностью, т.к. для больших файлов может возникнуть ошибка нехватки памяти для хранения полученного списка.
По сути это все методы для считывания информации из файла. И, смотрите, как только мы завершили работу с файлом, его следует закрыть. Для этого используется метод close:
Конечно, прописывая эту строчку, мы не увидим никакой разницы в работе программы. Но, во-первых, закрывая файл, мы освобождаем память, связанную с этим файлом и, во-вторых, у нас не будет проблем в потере данных при их записи в файл. А, вообще, лучше просто запомнить: после завершения работы с файлом, его нужно закрыть. Причем, организовать программу лучше так:
Мы здесь создаем вложенный блок try, в который помещаем критический текст программы при работе с файлом и далее блок finally, который будет выполнен при любом стечении обстоятельств, а значит, файл гарантированно будет закрыт.
Или же, забегая немного вперед, отмечу, что часто для открытия файла пользуются так называемым менеджером контекста, когда файл открывают при помощи оператора with:
При таком подходе файл закрывается автоматически после выполнения всех инструкций внутри этого менеджера. В этом можно убедиться, выведем в консоль флаг, сигнализирующий закрытие файла:
Запустим программу, видите, все работает также и при этом файл автоматически закрывается. Даже если произойдет критическая ошибка, например, пропишем такую конструкцию:
то, как видим, файл все равно закрывается. Вот в этом удобство такого подхода при работе с файлами.
Запись информации в файл
Теперь давайте посмотрим, как происходит запись информации в файл. Во-первых, нам нужно открыть файл на запись, например, так:
и далее вызвать метод write:
В результате у нас будет создан файл out.txt со строкой «Hello World!». Причем, этот файл будет располагаться в том же каталоге, что и файл с текстом программы на Python.
Далее сделаем такую операцию: запишем метод write следующим образом:
И снова выполним эту программу. Смотрите, в нашем файле out.txt прежнее содержимое исчезло и появилось новое – строка «Hello». То есть, когда мы открываем файл на запись в режимах
то прежнее содержимое файла удаляется. Вот этот момент следует всегда помнить.
Теперь посмотрим, что будет, если вызвать метод write несколько раз подряд:
Смотрите, у нас в файле появились эти строчки друг за другом. То есть, здесь как и со считыванием: объект file записывает информацию, начиная с текущей файловой позиции, и автоматически перемещает ее при выполнении метода write.
Если мы хотим записать эти строчки в файл каждую с новой строки, то в конце каждой пропишем символ переноса строки:
Далее, для дозаписи информации в файл, то есть, записи с сохранением предыдущего содержимого, файл следует открыть в режиме ‘a’:
Тогда, выполняя эту программу, мы в файле увидим уже шесть строчек. И смотрите, в зависимости от режима доступа к файлу, мы должны использовать или методы для записи, или методы для чтения. Например, если вот здесь попытаться прочитать информацию с помощью метода read:
то возникнет ошибка доступа. Если же мы хотим и записывать и считывать информацию, то можно воспользоваться режимом a+:
Так как здесь файловый указатель стоит на последней позиции, то для считывания информации, поставим его в самое начало:
А вот запись данных всегда осуществляется в конец файла.
Следующий полезный метод для записи информации – это writelines:
Он записывает несколько строк, указанных в коллекции. Иногда это бывает удобно, если в процессе обработки текста мы имеем список и его требуется целиком поместить в файл.
Чтение и запись в бинарном режиме доступа
Что такое бинарный режим доступа? Это когда данные из файла считываются один в один без какой-либо обработки. Обычно это используется для сохранения и считывания объектов. Давайте предположим, что нужно сохранить в файл вот такой список:
Откроем файл на запись в бинарном режиме:
Далее, для работы с бинарными данными подключим специальный встроенный модуль pickle:
И вызовем него метод dump:
Все, мы сохранили этот объект в файл. Теперь прочитаем эти данные. Откроем файл на чтение в бинарном режиме:
и далее вызовем метод load модуля pickle:
Все, теперь переменная bs ссылается на эквивалентный список:
Аналогичным образом можно записывать и считывать сразу несколько объектов. Например, так:
А, затем, считывание в том же порядке:
Вот так в Python выполняется запись и считывание данных из файла.
Задания для самоподготовки
1. Выполните считывание данных из текстового файла через символ и записи прочитанных данных в другой текстовый файл. Прочитывайте так не более 100 символов.
2. Пользователь вводит предложение с клавиатуры. Разбейте это предложение по словам (считать, что слова разделены пробелом) и сохраните их в столбец в файл.
3. Пусть имеется словарь:
Необходимо каждый элемент этого словаря сохранить в бинарном файле как объект. Затем, прочитать этот файл и вывести считанные объекты в консоль.
Видео по теме
© 2021 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта
Читайте также: