2016-05-30 7 views
2

Was ist der schnellste Weg zu überprüfen, ob Blöcke von Nullen in vielen Dateien sind. Die Blöcke sollten größer als 32000 Bytes von Nullen sein. Der folgende Code langsam ist:Nullblöcke größer als 32 KB in Dateien finden

empty_blocks = [] 
min_length = 32000 
block = False 
begin = -1 
data = open(file_name,'rb').read() 
for i,byte in enumerate(data): 
     byte = ord(byte) 
     if byte == 0x00 and block == False: 
      block = True 
      begin = i 
     elif byte != 0x00 and block == True: 
      block = False 
      if length >= min_length: 
       empty_blocks.append((begin, i - begin)) 
      begin = -1 
+0

Müssen die Blöcke auch eine Ausrichtungsanforderung erfüllen? Was ist mit Überschneidungen, wenn die Ausrichtungsanforderung nicht 32k ist? – Flexo

+0

Die Dateien wurden durch das Bittorrent-Synchronisationsprotokoll beschädigt. Ich habe die Information, dass die kleinste Stückgröße, die das Bittorrent-Protokoll überträgt, 32kb ist. Ich bin mir nicht sicher, ob die Nullblöcke n * 32kb mit n = 1,2,3,4 oder irgendeinem Wert größer als 32768 sind. –

Antwort

3

also die Blockgröße von 32.768 Bytes unter der Annahme, kam ich mit etwas entlang der Linien:

from functools import partial 

BLOCKSIZE = 32 * 1024 

with open('testfile.bin', 'rb') as f: 
    for block_number, data in enumerate(iter(partial(f.read, BLOCKSIZE), b'')): 
     if not any(data): 
      print('Block #{0} is empty!'.format(block_number)) 

Die sum() ist der schnellste Weg, um zu bestimmen, wenn jedes Byte in einer Sequenz den Wert Null hat. Ich glaube nicht, dass es schneller geht als O(n).
VPfB vorgeschlagen mit any(), die sehr, sehr schnell ist, da es auf dem ersten Nicht-Null-Element endet, anstatt durch die gesamte Sequenz zu gehen.

Ausgabebeispiel:

Block #0 is empty! 
Block #100 is empty! 
Block #200 is empty! 

Es verarbeitet etwa ~ 100 MB/s 2 GB/s auf meiner Maschine, die schnell genug ist, hoffe ich.

+1

Ich denke, der Test sollte beendet werden, wenn das erste Nicht-Null-Byte gefunden wird. 'block_is_empty = nicht vorhanden (Daten)' – VPfB

+0

Ja! Wie konnte ich etwas so Offensichtliches nicht sehen? Es ist jetzt etwa 20 mal schneller, danke! – leovp

+0

Ich habe versucht, Sie Code, aber es wird nicht funktionieren. Die any (...) gibt True für einen leeren Block zurück. Die Datenvariable enthält einen String mit chr (0) -Werten –

0

Starten von mmapping die Datei:

import mmap, os, re 
f = open(filename) 
m = mmap.mmap(f.fileno(), os.fstat(f.fileno()).st_size, prot=mmap.PROT_READ) 

Verwenden von regulären Ausdrücken ist bequem:

for match in re.findall(b'\0{32768}, m): 
    print(match.start()) 

aber Strings sind noch schneller:

z32k = '\0' * 32768 
start = 0 
while True: 
    start = m.find(z32k, start) 
    if start < 0: 
     break 
    print(start) 

nur 32k ausgerichtete Blöcke:

for match in re.finditer('.{32768}', m, re.DOTALL): 
    if max(match.group()) == '\0': 
     print(match.start()) 
Verwandte Themen