Найти - Пользователи
Полная версия: Ускорение обработки двоичного файла
Начало » Python для новичков » Ускорение обработки двоичного файла
1 2 3 4 5 6 7 8
Александр Кошелев
erl
то вроде как уходим с разработкой на яву :-), а честное слово не хочется, это поновой изучать язык…
Так вы этот ещё не изучили, куда там новый. Выкладывайте код и принимайте критику.
erl
я принимаю критику…
try:
begin_date1 = datetime.datetime.now()
#block_read = 10000000
block_read = 100000000
#fh = os.open(options_value.source_file,os.O_RDONLY)
fh = file(options_value.source_file,"rb")
s = ""
record = []
#s = list(os.read(fh,block_read))
#s.extend([char for char in fh.read(block_read)])
s = fh.read(block_read).encode('hex_codec')
if block_read > os.stat(options_value.source_file)[6]:
block_read = len(s)
number_irc = 0
record1 =[]
print "<ADM RECORD>" + s[:64] + "<RECORD>"
s = s[64:]
while s:
record = s.replace("ff32", "ff<RECORD>32").replace("ff33", "ff<RECORD>33").replace("ff34", "ff<RECORD>34").replace("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "<RECORD>").split("<RECORD>")
s = ""
#print record
for rec_idx, rec_str in enumerate(record):
#print rec_str
if (rec_str[:2] == "32" and rec_str[len(rec_str) - 2:] == "ff") or (rec_str[:2] == "34" and rec_str[len(rec_str) - 2:] == "ff"):
if rec_str[:2] == "32" and len(rec_str) <= 32:
if len(record) >= rec_idx + 2:
record[rec_idx] = record[rec_idx] + record[rec_idx + 1]
record[rec_idx + 1] = ""
print "<RECORD>" + record[rec_idx] + "</RECORD>"
else:
print "<RECORD>" + rec_str + "</RECORD>"
else:
if rec_str == record[-1] and record[-1]:
s = record[-1]
else:
if rec_str[:2] == "33":
print "<RECORD>" + rec_str + "</RECORD>"
print "Total time for while " + str(datetime.datetime.now() - begin_date1)
sys.exit()
s += fh.read(block_read).encode('hex_codec')
print "Total time for while " + str(datetime.datetime.now() - begin_date1)
finally:
print "END parser difference time: " + str(datetime.datetime.now() - begin_date1) + " PARSER"
print "CLOSE FILE\n"
#c = os.close(fh)
fh.close()
asv13
А вы не пробовали хотя бы вместо print-а - в файл свои строки писать? Если 500 меговый файл на экран весь выводить, то сам вывод на экран много времени займет.
erl
Пробовал лучше не стало.
asv13
Isem
А если метка находится на нечетной позиции? uint16 уже не прокатит.
Я же общий принцип указал, остальное мелочи
from numpy import *
a = memmap(r'c:\test\W1_RB.EGRID', uint8)
c = where(a==0xff)[0] # позиции всех элементов со значением ff
d = where((a[c+1]>0x31) & (a[c+1]<0x35))[0] # позиции всех элементов со значениями ff32-ff34
# проверка найденных индексов
print a[c[d]] # -> [255 255 255 255 255 ...
print a[c[d]+1] # -> [51 51 51 51 51 51 51 ...
Последовательность из двух символов это просто. Хуже выполнять поиск чего-то более длинного и более сложного чем куча нолей. Тут в отличие от некоторых других языков у библиотеки numpy прямого средства нету :(, а очень жаль, по крайней мере в рассылке советуют использовать стандартный поиск в строке (вот зачем массив в строки перегонять?)

erl
хоть кусок этого файла выложить можешь? Что-то тяжеловато твой код воспринимается, проще начисто переписать. В С# тоже данные перегонял в HEX-строки ? Непойму зачем так усложнять, только для split-ов чтоли…
erl
извините но выдать кусок файлаа не мгу. единственнное чтО могу рассказать ротом. начинается файл заголовком 32 байта. далее шпарят байты начало записи 0х32 конец записи 0хff между началом и концом могут встречаться и байты ff и 32 и всякие разные но вот точно ни когда не встречается ff и началоо следующей запис, а записи бывают трех видов 32 33 34, вот собственно вся для мня ложность в том что между началом и концом могут быть похожиена метки символы, если хоть кто нить предложит элегантное и простое решени будет очень здорово.
erl
Андрей Светлов
Не нужен здесь pypy и Ява не правит в автоматическом режиме кривые руки.
Кстати, а характерная длина записи какая? Ну там сотня-другая байт или они обычно мегабайтные?
Да, и код - очень помогает выявить проблему.
н ет ни какой характерной длины записи, все различны. Если есть поможительные предложения рад выслушать.
PooH
Если размеры записей отличаются не сильно, то выбираем кусок файла в буфер заведомо большей длины чем запись. Бежим с конца по байтово конечным автоматом с тремя состояниями - <исходное>/<последний байт метки>/<первый байт метки>. При нахождении метки - запись у нас уже в буфере - обрабатываем, и читаем снова в буфер начиная с метки, и все по новой. Если размеры записей отличаются сильно, так же через буфер, но только бежим уже с начала буфера.
pyuser
erl я не совсем понял ваш алгоритм обработки :( попробуйте:
import os
import binascii
import time as _time

from io import StringIO

from enum import enum

STATE = enum("original", "end", "begin", "stop")

def main(BLOCK_SIZE=4096):
out = StringIO()
write = out.write
hexlify = binascii.hexlify

begin = _time.time()
file_size = os.path.getsize(options_value.source_file)

with open(options_value.source_file, "rb") as f:
write("<ADM RECORD>{0}<RECORD>\n".format(hexlify(f.read(32))))
pos = 0
bfr = b""
state = STATE.original
while state != STATE.stop:
if state == STATE.original:
pos = 0
bfr += f.read(BLOCK_SIZE)
state = STATE.begin
elif state == STATE.begin:
pos = bfr.find(b"\xff", pos)
if -1 == pos:
state = STATE.original
else:
try:
if bfr[pos + 1] in (b"\x32", b"\x33", b"\x34"):
state = STATE.end
except IndexError:
if file_size == f.tell():
state = STATE.end
else:
state = STATE.original
elif state ==STATE.end:
write("<RECORD>{0}<RECORD>\n".format(hexlify(bfr[:pos])))
bfr = bfr[pos + 1:]
state = STATE.begin if bfr else STATE.stop
print("total time:", _time.time() - begin)

with open("outfile", "wb") as f:
f.write(out.getvalue())
ЗЫ. сам не проверял :(
erl
PooH
Если размеры записей отличаются не сильно, то выбираем кусок файла в буфер заведомо большей длины чем запись. Бежим с конца по байтово конечным автоматом с тремя состояниями - <исходное>/<последний байт метки>/<первый байт метки>. При нахождении метки - запись у нас уже в буфере - обрабатываем, и читаем снова в буфер начиная с метки, и все по новой. Если размеры записей отличаются сильно, так же через буфер, но только бежим уже с начала буфера.
Зачем, не проще ли и быстрее сразу в буфере заменить все значения ff32 и ff34 на соответствующие тэги и потоv выбрать все теги в массив.
Что собственно я и сделал, проблема в том что берем из файла в буфер 100 байт, выбрали все что соответствует шаблону, но в конце остается кусок байт который не поддается расшифровки потому что это не полная запись, переопределить бы метод чтение из файла, что бы он читать до ближайшей метки ff32 или ff34.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB