2010-01-31 16 views
9

Qual è il modo più efficiente dal tempo impiegato per leggere un file di testo in un elenco di stringhe binarie in erlang? L'ovvia soluzioneIl modo più efficace per leggere un file in un elenco di stringhe

-module(test). 
-export([run/1]). 

open_file(FileName, Mode) -> 
    {ok, Device} = file:open(FileName, [Mode, binary]), 
    Device. 

close_file(Device) -> 
    ok = file:close(Device). 

read_lines(Device, L) -> 
    case io:get_line(Device, L) of 
     eof -> 
      lists:reverse(L); 
     String -> 
      read_lines(Device, [String | L]) 
    end. 

run(InputFileName) -> 
    Device = open_file(InputFileName, read), 
    Data = read_lines(Device, []), 
    close_file(Device), 
    io:format("Read ~p lines~n", [length(Data)]). 

diventa troppo lento quando il file contiene più di 100000 linee.

+1

perché passate il contenuto letto a get_line come richiesto? – Zed

+0

@Zed, è stato un mio errore. Ora tutto funziona con una velocità accettabile. Grazie! A volte vorrei che Erlang avesse un sistema di tipo forte ... – Konstantin

risposta

15
{ok, Bin} = file:read_file(Filename). 

o se è necessario la linea di contenuti per riga

read(File) -> 
    case file:read_line(File) of 
     {ok, Data} -> [Data | read(File)]; 
     eof  -> [] 
    end. 
2

leggere l'intero file in in un binario. Converti in una lista e strappa le linee.

Questo è molto più efficiente di qualsiasi altro metodo. Se non mi credi tempo it.

 
file2lines(File) -> 
    {ok, Bin} = file:read_file(File), 
    string2lines(binary_to_list(bin), []). 

string2lines("\n" ++ Str, Acc) -> [reverse([$\n|Acc]) | string2lines(Str,[])]; 
string2lines([H|T], Acc)  -> string2lines(T, [H|Acc]); 
string2lines([], Acc)   -> [reverse(Acc)]. 
Problemi correlati