2010-03-19 18 views
11

So che si può fare qualcosa di simile:come leggere il contenuto di un file In Erlang?

readlines(FileName) -> 
    {ok, Device} = file:open(FileName, [read]), 
    get_all_lines(Device, []). 

get_all_lines(Device, Accum) -> 
    case io:get_line(Device, "") of 
     eof -> file:close(Device), Accum; 
     Line -> get_all_lines(Device, Accum ++ [Line]) 
    end. 

: C'è uno BIF di linea che può fare anche questo?

risposta

23

file:read_file/1 è quello che stai cercando. Solo per scopi didattici, Accum ++ [Line] è una cattiva pratica. Il problema è che l'argomento di sinistra di ++ viene copiato e right viene usato così com'è. Nel tuo codice copi una parte sempre più grande in ogni iterazione. La soluzione è lists:reverse(Line,Accum) e restituire lists:reverse(Accum) nella filiale eof (oppure [Line|Accum] e lists:append(lists:reverse(Accum)) allo eof o utilizzare il binario con un'operazione di aggiunta migliore o ...). Un altro modo non è usare la funzione ricorsiva della coda che non è così male come sembra a prima volta in base allo Myth: Tail-recursive functions are MUCH faster than recursive functions.

Quindi la funzione readlines/1 dovrebbe essere simile

readlines(FileName) -> 
    {ok, Device} = file:open(FileName, [read]), 
    try get_all_lines(Device) 
     after file:close(Device) 
    end. 

get_all_lines(Device) -> 
    case io:get_line(Device, "") of 
     eof -> []; 
     Line -> Line ++ get_all_lines(Device) 
    end. 
+0

Ok, grazie, buon consiglio! – Zubair

+0

Il file non è: read_file un po 'pericoloso? Voglio dire che sta usando file_server che sembra bloccarsi (gen_server che sta avvolgendo prim_file). Sembra che prim_file o file_io_server possano essere soluzioni migliori. – mkorszun

+0

Non ho mai sentito o sentito alcun problema con 'file: read_file'. Non capisco cosa dovrebbe bloccare. –

9

Si potrebbe sfruttare file:read_file/1 e binary:split/3 a fare questo lavoro in due fasi:

readlines(FileName) -> 
    {ok, Data} = file:read_file(FileName), 
    binary:split(Data, [<<"\n">>], [global]). 
+0

Si vuole davvero fare una dichiarazione di caso qui, perché il file non potrebbe esistere. caso file: read_file (FileName) di {ok, Data} -> ... {error, _} -> ... end. –

Problemi correlati