2010-01-31 3 views
9

Cách hiệu quả nhất từ ​​thời gian được tiêu thụ để đọc một tệp văn bản vào danh sách các chuỗi nhị phân trong erlang là gì? Giải pháp rõ ràngCách hiệu quả nhất để đọc một tệp thành danh sách các chuỗi

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

trở nên quá chậm khi tệp chứa hơn 100000 dòng.

+1

tại sao bạn chuyển nội dung đã đọc vào get_line như lời nhắc? – Zed

+0

@Zed, đó là lỗi của tôi. Bây giờ tất cả đang làm việc với tốc độ chấp nhận được. Cảm ơn bạn! Đôi khi tôi muốn erlang có một hệ thống kiểu mạnh ... – Konstantin

Trả lời

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

hoặc nếu bạn cần dòng nội dung bởi dòng

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

đọc toàn bộ tập tin trong thành nhị phân. Chuyển đổi thành danh sách và trích xuất các dòng.

Điều này hiệu quả hơn nhiều so với bất kỳ phương pháp nào khác. Nếu bạn không tin tôi thời gian nó.

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