2010-01-31 8 views
9

¿Cuál es la forma más eficiente desde el tiempo consumido para leer un archivo de texto en una lista de cadenas binarias en erlang? La solución obviaLa manera más eficiente de leer un archivo en una lista de cadenas

-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)]). 

se vuelve demasiado lenta cuando el archivo contiene más de 100000 líneas.

+1

¿Por qué está pasando el contenido de lectura a get_line como un mensaje? – Zed

+0

@Zed, ese fue mi error. Ahora todo está funcionando con velocidad aceptable. ¡Gracias! A veces desearía que Erlang tuviera un sistema de tipo fuerte ... – Konstantin

Respuesta

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

o si necesita la línea de contenidos por parte de la línea

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

leer todo el archivo en un binario. Convierte a una lista y arranca las líneas.

Esto es mucho más eficiente que cualquier otro método. Si no me crees el tiempo .

 
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)]. 
Cuestiones relacionadas