2010-03-19 30 views
11

Tôi biết bạn có thể làm một cái gì đó như thế này:cách đọc nội dung của tệp trong 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ó một liner BIF có thể làm được điều này không?

Trả lời

23

file:read_file/1 là những gì bạn đang tìm kiếm. Chỉ vì mục đích giảng dạy, Accum ++ [Line] là thực hành không tốt. Vấn đề là đối số trái của ++ được sao chép và quyền được sử dụng như nguyên trạng. Trong mã của bạn, bạn sẽ sao chép phần lớn hơn và lớn hơn trong mỗi lần lặp. Giải pháp là lists:reverse(Line,Accum) và trả lại lists:reverse(Accum) trong chi nhánh eof của bạn (Hoặc [Line|Accum]lists:append(lists:reverse(Accum)) tại số eof hoặc sử dụng nhị phân có hoạt động nối thêm tốt hơn hoặc ...). Một cách khác là không sử dụng chức năng đệ quy đuôi mà không phải là xấu như lần đầu tiên theo Myth: Tail-recursive functions are MUCH faster than recursive functions.

Vì vậy, chức năng readlines/1 của bạn sẽ trông như thế

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, cảm ơn, lời khuyên tốt! – Zubair

+0

Không phải là tệp: read_file có hơi nguy hiểm không? Tôi có nghĩa là nó đang sử dụng file_server trông giống như nó chặn (gen_server được gói prim_file). Có vẻ như prim_file hoặc file_io_server có thể là giải pháp tốt hơn. – mkorszun

+0

Tôi chưa có kinh nghiệm hay nghe về bất kỳ vấn đề nào với 'file: read_file'. Tôi không hiểu những gì nó nên chặn. –

9

Bạn có thể tận dụng file:read_file/1binary:split/3 để làm công việc này theo hai bước:

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

Bạn thực sự muốn làm một tuyên bố trường hợp ở đây, bởi vì tập tin không thể tồn tại. file case: read_file (FileName) của {ok, Data} -> ... {error, _} -> ... end. –

Các vấn đề liên quan