2012-06-13 8 views
5

Ich scanne gerne größere (> 500M) Binärdateien für Strukturen/Muster. Ich bin neu in der Sprache und hoffe, dass mir jemand anfangen kann. Tatsächlich sind die Dateien eine Datenbank, die Segmente enthält. Ein Segment beginnt mit einem Kopf fester Größe, gefolgt von einem optionalen Teil fester Größe, gefolgt von dem Nutzlast/Datenteil variabler Länge. Für einen ersten Test möchte ich nur die Anzahl der Segmente in der Datei protokollieren. Ich habe schon für ein Tutorial gegoogelt aber nichts gefunden was geholfen hat. Ich brauche einen Hinweis oder ein Tutorial, das nicht zu weit von meinem Anwendungsfall entfernt ist, um loszulegen.Scannen von großen Binärdateien mit Erlang

Greets Stefan

+1

Es wäre auch hilfreich mit einem Beispiel der Binärdatei, die Sie analysieren möchten und wie das Endergebnis aussehen soll. – Lukas

Antwort

3

Sie müssen lernen, über Bit Syntax und Binary Comprehensions. Weitere nützliche Links folgen: http://www.erlang.org/documentation/doc-5.6/doc/programming_examples/bit_syntax.html und http://goto0.cubelogic.org/a/90.

Sie müssen auch lernen, Dateien zu verarbeiten, von Dateien (Zeile für Zeile, Chunk-by-Chunk, an bestimmten Positionen in einer Datei, e.t.c.) zu lesen und auf verschiedene Arten in Dateien zu schreiben. Die Dateiverarbeitungsfunktionen sind erläutert here

Sie können auch wählen, um den Quellcode von großen Dateiverarbeitungsbibliotheken innerhalb der Erlang-Pakete, z. Disk Log, Dets und mnesia. Diese Bibliotheken lesen und schreiben stark in Dateien und ihr Quellcode ist offen für Sie zu sehen.

Ich hoffe, dass

1

Hier ist eine synthetisierte Probe Problem hilft: Ich habe eine Binärdatei (test.txt), die ich analysieren möchten. Ich möchte alle binären Muster von <<$a, $b, $c>> in der Datei finden.

den Inhalt von "test.txt":

I arbitrarily decide to choose the string "abc" as my target string for my test. I want to find all the abc's in my testing file. 

Ein Beispielprogramm (lab.erl):

-module(lab). 
-compile(export_all). 

find(BinPattern, InputFile) -> 
    BinPatternLength = length(binary_to_list(BinPattern)), 
    {ok, S} = file:open(InputFile, [read, binary, raw]), 
    loop(S, BinPattern, 0, BinPatternLength, 0), 
    file:close(S), 
    io:format("Done!~n", []). 

loop(S, BinPattern, StartPos, Length, Acc) -> 
    case file:pread(S, StartPos, Length) of 
    {ok, Bin} -> 
     case Bin of 
     BinPattern -> 
      io:format("Found one at position: ~p.~n", [StartPos]), 
      loop(S, BinPattern, StartPos + 1, Length, Acc + 1); 
     _ -> 
      loop(S, BinPattern, StartPos + 1, Length, Acc) 
     end; 
    eof -> 
     io:format("I've proudly found ~p matches:)~n", [Acc]) 
    end. 

Run es:

1> c(lab). 
{ok,lab} 
2> lab:find(<<"abc">>, "./test.txt").  
Found one at position: 43. 
Found one at position: 103. 
I've proudly found 2 matches:) 
Done! 
ok 

Beachten Sie, dass der obige Code nicht sehr effizient ist (Der Scanvorgang verschiebt sich jeweils um ein Byte) und es ist sequenziell (es werden nicht alle "Kerne" auf Ihrem Computer verwendet). Es ist nur dafür gedacht, dass Sie beginnen.

1

Wenn Ihre Daten in den Speicher passen, können Sie die Daten als Ganzes mit file:read_file/1 lesen. Wenn Sie die Datei nicht im raw-Modus verwenden können. Dann können Sie Daten mit bit_syntax analysieren. Wenn Sie es richtig schreiben, können Sie eine Parsing-Geschwindigkeit von mehreren zehn MB/s erreichen, wenn das Parsing-Modul mit HiPE kompiliert wird. Genaue Techniken des Parsens hängen vom genauen Segmentdatenformat und davon ab, wie robust/genau das Ergebnis ist, nach dem Sie suchen. Zum parallelen Parsen können Sie sich von Tim Bray's Wide Finder project inspirieren lassen.