Erlang:csv文件操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
%%%-------------------------------------------------------------------
%%% @author sy
%%% @copyright (C) 2020, <COMPANY>
%%% @doc
%%% csv
%%% @end
%%% Created : 30. 06月 2020 09:33
%%%-------------------------------------------------------------------
-module(csv).
-author("sy").

%% API
-compile(export_all).

row(File, Elem) when is_tuple(Elem) ->
ListElem = tuple_to_list(Elem),
row(File, ListElem);
row(File, []) ->
newline(File);
row(File, [Value]) ->
field(File, Value),
newline(File);
row(File, [Value Rest]) ->
field(File, Value),
comma(File),
row(File, Rest).

newline(File) ->
file:write(File, "\n").

comma(File) ->
file:write(File, ",").

field(File, Value) when is_tuple(Value) ->
file:write(File, "\""),
file:write(File, io_lib:format("~p",[Value])),
file:write(File, "\"");
field(File, Value) when is_binary(Value) ->
Match = binary:match(Value, [<<",">>, <<"\n">>, <<"\"">>]),
case Match of
nomatch ->
file:write(File, Value);
_ ->
file:write(File, "\""),
file:write(File, binary:replace(Value, <<"\"">>, <<"\"\"">>, [global])),
file:write(File, "\"")
end;
field(File, Value) when is_list(Value) ->
field(File, unicode:characters_to_binary(Value));
field(File, Value) when is_integer(Value) ->
file:write(File, integer_to_list(Value));
field(File, Value) when is_atom(Value) ->
file:write(File, io_lib:write_atom(Value));
field(File, Value) when is_float(Value) ->
file:write(File, io_lib:format("~f",[Value]));
field(File, Value) ->
file:write(File, io_lib:format("\"~p\"",[Value])).

parse(FilePath,ForEachLine,Opaque)->
case file:open(FilePath,[read]) of
{_,S} ->
start_parsing(S,ForEachLine,Opaque);
Error -> Error
end.

start_parsing(S,ForEachLine,Opaque)->
Line = io:get_line(S,''),
case Line of
eof -> {ok,Opaque};
"\n" -> start_parsing(S,ForEachLine,Opaque);
"\r\n" -> start_parsing(S,ForEachLine,Opaque);
_ ->
NewOpaque = ForEachLine(scanner(clean(clean(Line,10),13)),Opaque),
start_parsing(S,ForEachLine,NewOpaque)
end.

scan(InitString,Char,[HeadBuffer]) when Head == Char ->
{lists:reverse(InitString),Buffer};
scan(InitString,Char,[HeadBuffer]) when Head =/= Char ->
scan([HeadInitString],Char,Buffer);
scan(X,_,Buffer) when Buffer == [] -> {done,lists:reverse(X)}.
scanner(Text)-> lists:reverse(traverse_text(Text,[])).

traverse_text(Text,Buff)->
case scan("",$,,Text) of
{done,SomeText}-> [SomeTextBuff];
{Value,Rem}-> traverse_text(Rem,[ValueBuff])
end.

clean(Text,Char)->
string:strip(string:strip(Text,right,Char),left,Char).

代码运行测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
(server@DESKTOP-LSB1V8C)1> {ok, FilePid} = file:open("D:/test.csv", [append]).
{ok,<0.327.0>}
(server@DESKTOP-LSB1V8C)2> csv:row(FilePid, ["Id","Data"]).
ok
(server@DESKTOP-LSB1V8C)3> csv:row(FilePid, ["100","text..."]).
ok
(server@DESKTOP-LSB1V8C)4> ForEachLine = fun(Line,Buffer)-> [LineBuffer] end.
#Fun<erl_eval.12.54118792>
(server@DESKTOP-LSB1V8C)5> {ok, Data} = csv:parse("D:/test.csv",ForEachLine,[]).
{ok,[["100","text..."],["Id","Data"]]}
(server@DESKTOP-LSB1V8C)6> file:close(FilePid).
ok
(server@DESKTOP-LSB1V8C)7>