Erlang:将 mnesia table 写入 .csv 每行一条记录
Erlang: Writing mnesia table to .csv one record per line
我有一个 Mnesia table,它包含以下格式:
-record(state, {key, tuple, state, timestamp, fin_from}).
条目如下所示(用 ets:tab2list(Tab)
阅读):
[{state,{80,43252,tcp,tcp_syn_received,{192,168,101,5},{192,168,101,89}},
{80,43252,tcp,{192,168,101,5},{192,168,101,89}},
tcp_syn_received,1463850419221,undefined},
{state,{80,41570,tcp,tcp_syn_received,{192,168,101,5},{192,168,101,89}},
{80,41570,tcp,{192,168,101,5},{192,168,101,89}},
tcp_syn_received,1463850403214,undefined},
...]
我想将这些数据写入一个 .csv 文件,每行一个条目 - 首选格式如下:
state,80,43252,tcp,tcp_syn_received,192.168.101.5,192.168.101.89,80,43252,tcp,192.168.101.5,192.168.101.89,tcp_syn_received,1463850419221,undefined
state,80,41570,tcp,tcp_syn_received,192.168.101.5,192.168.101.89,80,41570,tcp,192.168.101.5,192.168.101.89,tcp_syn_received,1463850419221,undefined
undefined
后应该有一个换行符。
我尝试使用以下代码(Content = ets:tab2list(states)
):
do_logging_async(File, Format, Content, Append)->
F = fun() ->
file:write_file(File, io_lib:fwrite(Format, [Content]), [Append])
end,
spawn(F).
但是,我无法得到与我的输出类似的任何内容。
之后应使用 R.
评估数据
更新:关键是逐行读取table并用~w
而不是~p
解析它。我最终得到了以下解决方案(它产生的输出略有不同,但是冗余数据较少):
do_state_logging(File, EtsAsList) ->
% write header (columnnames)
file:write_file(File, io_lib:fwrite("~w,~w,~w,~w,~w,~w,~w,~w~n", [record,dstPort,srcPort,proto,dstIP,srcIP,state,timestamp]),[append]),
case EtsAsList of
[] ->
ok;
_ ->
F = fun({Record,_Key,
[P1, P2, Proto, {D_Ip_1,D_Ip_2,D_Ip_3,D_Ip_4}, {S_Ip_1,S_Ip_2,S_Ip_3,S_Ip_4}],
State, Timestamp, _}) ->
file:write_file(File, io_lib:fwrite("~w,", [Record]),[append]),
file:write_file(File, io_lib:fwrite("~w,~w,~w,", [P1,P2,Proto]),[append]),
file:write_file(File, io_lib:fwrite("~w.~w.~w.~w,", [D_Ip_1,D_Ip_2,D_Ip_3,D_Ip_4]), [append]),
file:write_file(File, io_lib:fwrite("~w.~w.~w.~w,", [S_Ip_1,S_Ip_2,S_Ip_3,S_Ip_4]), [append]),
file:write_file(File, io_lib:fwrite("~w,", [State]),[append]),
file:write_file(File, io_lib:fwrite("~w", [Timestamp]),[append]),
file:write_file(File, ["\n"],[append])
end,
lists:foreach(F, EtsAsList)
end,
io:format("Finished logging of statetable to file: ~p~n" , [File]).
感谢促使我产生这个想法的答案。
假设您将 ets 记录值更改为列表而不是元组,您可以使用此代码将 ETS Table 写入文件。
do_logging_async(File, EtsAsList) ->
F = fun({Key, Value}) ->
file:write_file(File, [atom_to_list(Key) ++ ","],[append]),
write_value(File,lists:flatten(Value)),
file:write_file(File, ["\n"],[append])
end,
lists:foreach(F,EtsAsList).
write_value(_File, []) -> ok;
write_value(File, [H|T]) ->
case is_integer(H) of
true -> file:write_file(File, [integer_to_list(H)],[append]);
false -> file:write_file(File, [atom_to_list(H)],[append])
end,
case T=:=[] of
true -> ok;
false -> file:write_file(File, [","],[append])
end,
write_value(File,T).
do_logging_async/2
取每 {Key, Value}
对。首先,它将 Key
写入文件,然后在 Value
上运行 write_value/2
,在每一对的末尾写入 \n
.
write_value/2
获取展平值列表(假设它是展平列表,仅包含整数和原子)并将其写入文件。
我有一个 Mnesia table,它包含以下格式:
-record(state, {key, tuple, state, timestamp, fin_from}).
条目如下所示(用 ets:tab2list(Tab)
阅读):
[{state,{80,43252,tcp,tcp_syn_received,{192,168,101,5},{192,168,101,89}},
{80,43252,tcp,{192,168,101,5},{192,168,101,89}},
tcp_syn_received,1463850419221,undefined},
{state,{80,41570,tcp,tcp_syn_received,{192,168,101,5},{192,168,101,89}},
{80,41570,tcp,{192,168,101,5},{192,168,101,89}},
tcp_syn_received,1463850403214,undefined},
...]
我想将这些数据写入一个 .csv 文件,每行一个条目 - 首选格式如下:
state,80,43252,tcp,tcp_syn_received,192.168.101.5,192.168.101.89,80,43252,tcp,192.168.101.5,192.168.101.89,tcp_syn_received,1463850419221,undefined
state,80,41570,tcp,tcp_syn_received,192.168.101.5,192.168.101.89,80,41570,tcp,192.168.101.5,192.168.101.89,tcp_syn_received,1463850419221,undefined
undefined
后应该有一个换行符。
我尝试使用以下代码(Content = ets:tab2list(states)
):
do_logging_async(File, Format, Content, Append)->
F = fun() ->
file:write_file(File, io_lib:fwrite(Format, [Content]), [Append])
end,
spawn(F).
但是,我无法得到与我的输出类似的任何内容。 之后应使用 R.
评估数据更新:关键是逐行读取table并用~w
而不是~p
解析它。我最终得到了以下解决方案(它产生的输出略有不同,但是冗余数据较少):
do_state_logging(File, EtsAsList) ->
% write header (columnnames)
file:write_file(File, io_lib:fwrite("~w,~w,~w,~w,~w,~w,~w,~w~n", [record,dstPort,srcPort,proto,dstIP,srcIP,state,timestamp]),[append]),
case EtsAsList of
[] ->
ok;
_ ->
F = fun({Record,_Key,
[P1, P2, Proto, {D_Ip_1,D_Ip_2,D_Ip_3,D_Ip_4}, {S_Ip_1,S_Ip_2,S_Ip_3,S_Ip_4}],
State, Timestamp, _}) ->
file:write_file(File, io_lib:fwrite("~w,", [Record]),[append]),
file:write_file(File, io_lib:fwrite("~w,~w,~w,", [P1,P2,Proto]),[append]),
file:write_file(File, io_lib:fwrite("~w.~w.~w.~w,", [D_Ip_1,D_Ip_2,D_Ip_3,D_Ip_4]), [append]),
file:write_file(File, io_lib:fwrite("~w.~w.~w.~w,", [S_Ip_1,S_Ip_2,S_Ip_3,S_Ip_4]), [append]),
file:write_file(File, io_lib:fwrite("~w,", [State]),[append]),
file:write_file(File, io_lib:fwrite("~w", [Timestamp]),[append]),
file:write_file(File, ["\n"],[append])
end,
lists:foreach(F, EtsAsList)
end,
io:format("Finished logging of statetable to file: ~p~n" , [File]).
感谢促使我产生这个想法的答案。
假设您将 ets 记录值更改为列表而不是元组,您可以使用此代码将 ETS Table 写入文件。
do_logging_async(File, EtsAsList) ->
F = fun({Key, Value}) ->
file:write_file(File, [atom_to_list(Key) ++ ","],[append]),
write_value(File,lists:flatten(Value)),
file:write_file(File, ["\n"],[append])
end,
lists:foreach(F,EtsAsList).
write_value(_File, []) -> ok;
write_value(File, [H|T]) ->
case is_integer(H) of
true -> file:write_file(File, [integer_to_list(H)],[append]);
false -> file:write_file(File, [atom_to_list(H)],[append])
end,
case T=:=[] of
true -> ok;
false -> file:write_file(File, [","],[append])
end,
write_value(File,T).
do_logging_async/2
取每 {Key, Value}
对。首先,它将 Key
写入文件,然后在 Value
上运行 write_value/2
,在每一对的末尾写入 \n
.
write_value/2
获取展平值列表(假设它是展平列表,仅包含整数和原子)并将其写入文件。