将csv文件中的数据注册到mnesia数据库

将csv文件中的数据注册到mnesia数据库,csv,erlang,Csv,Erlang,我想将csv文件中的数据存储在mnesia数据库中(特别是在名为“user”的表中) 我在这个论坛上发现了这种解决方案: 创建名为csv.erl的外商投资企业: %%% --- csv parser in Erlang. ------ %%% To help process large csv files without loading them into %%% memory. Similar to the xml parsing technique of SAX -module(csv).

我想将csv文件中的数据存储在mnesia数据库中(特别是在名为“user”的表中)

我在这个论坛上发现了这种解决方案:

创建名为csv.erl的外商投资企业:

%%% --- csv parser in Erlang. ------
%%% To help process large csv files without loading them into
%%% memory. Similar to the xml parsing technique of SAX

-module(csv).
-compile(export_all).

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).
创建函数测试:

test()->

    ForEachLine = fun(Line,Buffer)-> io:format("Line: ~p~n",[Line]),Buffer end,

 InitialBuffer = [],

 csv:parse("/home/include/user.csv",ForEachLine,InitialBuffer).
但是这个解决方案只显示Erlang控制台中的数据(它显示csv文件中的每一行),但我的目标是将csv文件中的这些行存储在用户表中

我已经创建了用户的记录

-record(user, {id, firstname, lastname, birthday}).
要将csv文件中的行注册到用户表中,我尝试使用

test()->

    ForEachLine = fun(Line,Buffer)-> io:format("Line: ~p~n",[Line]),Buffer end,

 InitialBuffer = [],

 csv:parse("/home/test/user.csv",ForEachLine,InitialBuffer),



   F = fun() ->
         Line=#user{},
         mnesia:write(Line),                               
         {ok}

     end,
     {atomic, Val} = mnesia:transaction(F),
     Val.

但此函数不在用户表中插入数据

您需要做几件事:

  • 在mnesia中创建一个模式,它将保存您的数据。即创建一个
    #user{}
    记录
  • 将您的行放入
    R=#user{}
  • 调用
    mnesia:在事务内部写入(R)
    。为了加快速度,您可以在同一事务中批处理几次写入,或者只需使用
    mnesia:dirty\u write(R)

我是本模块的作者。现在,您已经将传递给库的函数对象应用于它找到的每一行,您可以根据自己的喜好对其进行自定义。例如:

F = fun(Line,_) -> [Id,Firstname, Lastname, Birthday] = Line, U = #user{ id = Id, firstname = Firstname, lastname = Lastname, birthday = Birthday }, mnesia:dirty_write(U), [] end. 在上面的示例中,您的
缓冲区现在只是一个计数器。这将自动显示从
.csv
文件插入mnesia的记录总数

请记住erlang数据结构的通用性。您的
乐趣
,只要它被构造为包含两个变量,第一个变量是行,您就可以将其自定义为任何变量。在
Fun
中,您甚至可以将
发送到另一个erlang节点或erlang进程。像这样:

F = fun(Line,Server)-> [Id,Firstname, Lastname, Birthday] = Line, U = #user{ id = Id, firstname = Firstname, lastname = Lastname, birthday = Birthday }, Server ! {from_csv,U} Server end. 请更改上述函数以反映您的
分隔符。例如,如果分隔符
是分号(;)
,则该函数将更改为: traverse_text(Text,Buff)-> case scan("",$;,Text) of {done,SomeText}-> [SomeText|Buff]; {Value,Rem}-> traverse_text(Rem,[Value|Buff]) end. 遍历文本(文本,浅黄色)-> 大小写扫描(“,$;文本) {done,SomeText}->[SomeText|Buff]; {Value,Rem}->遍历文本(Rem,[Value}Buff]) 结束。


因此,如果您的
定界符
不同,只需对该函数进行更改,如我上面所示(我希望您看到符号的位置,看到的是
美元符号,后面是实际的定界符
)。然后,重新编译并重新加载该模块。如果遇到更多挑战,请告诉我。

分隔符可能会在不同的
.csv
文件中更改。查看答案编辑,了解如何自定义
.csv解析器
,以适应任何
分隔符
。在解析器中,我假设了一个
逗号
。 traverse_text(Text,Buff)-> case scan("",$,,Text) of {done,SomeText}-> [SomeText|Buff]; {Value,Rem}-> traverse_text(Rem,[Value|Buff]) end. traverse_text(Text,Buff)-> case scan("",$;,Text) of {done,SomeText}-> [SomeText|Buff]; {Value,Rem}-> traverse_text(Rem,[Value|Buff]) end.