| by suyi | No comments

Erlang:csv文件操作

%%%-------------------------------------------------------------------
%%% @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,[Head|Buffer]) when Head == Char ->
  {lists:reverse(InitString),Buffer};
scan(InitString,Char,[Head|Buffer]) when Head =/= Char ->
  scan([Head|InitString],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}-> [SomeText|Buff];
    {Value,Rem}-> traverse_text(Rem,[Value|Buff])
  end.

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

代码运行测试:

(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)-> [Line|Buffer] 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> 

发表评论