1

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.

ただし、この関数はユーザーテーブルにデータを挿入しません

4

2 に答える 2

2

あなたはいくつかのことをする必要があります:

  • データを保持するスキーマをmnesiaで作成します。それは#user{}レコードを作成することです。
  • あなたのラインを取り、それをタイプの記録にしましょうR = #user{}
  • mnesia:write(R)トランザクション内で呼び出します。高速化するには、同じトランザクション内で2、3の書き込みをバッチ処理するか、単にを使用しますmnesia:dirty_write(R)
于 2013-01-26T14:26:17.040 に答える
1

私はこのモジュールの作成者です。これで、ライブラリに渡して見つかったすべての Line に適用する Functional Object を好みに合わせてカスタマイズできます。例えば:

F = fun(Line,_) ->
        [ID、名、姓、誕生日] = 行、
        U = #ユーザー{
            ID = ID、
            ファーストネーム = ファーストネーム、
            姓 = 姓、
            誕生日=誕生日
        }、
        mnesia:dirty_write(U),
        []
    終わり。

ここで、ファイルが のように非常に適切にフォーマットされている場合、つまり、.csvすべての行が次の行と同じであることを意味し、Fun上記で行ったようにパターン マッチは問題ないことを覚えておいてください。通常、見出し (.csvファイルの最初の行) にはデータセット全体の列が表示されるため、前の行は最初の行をテンプレートとして使用できます。

それはさておき、行を見て、それLineを erlang レコードに変換します。Bufferこの変数は、呼び出しごとに後で更新されるため、カウンターとして使用できますFun。ファイル内の次の行に適用できるようにFun、更新された変数で終了することに注意してください。したがって、あなたがよく理解していれば、Buffer 変数は Integer である可能性があり、各呼び出しの最後でそれをインクリメントします。次に例を示します。Buffer.csvrecursionZeroFun

F = fun(ライン、カウンター) ->
        [ID、名、姓、誕生日] = 行、
        U = #ユーザー{
            ID = ID、
            ファーストネーム = ファーストネーム、
            姓 = 姓、
            誕生日=誕生日
        }、
        mnesia:dirty_write(U),
        カウンター+1
    終わり。
上記の例では、 yourBufferは単なるカウンターです。これにより、ファイルから mnesia に挿入されたレコードの総数が自動的に表示され.csvます。

erlang のデータ構造がいかに一般的であるかを覚えておいてください。あなたFunの は、最初の変数が Line である 2 つの変数を取るように構築されている限り、それを何にでもカスタマイズできます。の内部では、を別の erlang ノードまたは erlang プロセスFunに送信することもできます。Lineこのような:

F = fun(回線、サーバー)->
        [ID、名、姓、誕生日] = 行、
        U = #ユーザー{
            ID = ID、
            ファーストネーム = ファーストネーム、
            姓 = 姓、
            誕生日=誕生日
        }、
        サーバー!{from_csv,U}
        サーバ
    終わり。
上記の例では、Buffer変数は定数であり、ファイルからすべてのレコードを送信するプロセスのPidまたはです。結論として、次の行への後続のすべての呼び出しで Buffer 変数が更新される場合と更新されない場合があります。の最後に同じ定数変数(タプル、アトム、Pid、または文字列など、それが何であるかを知っていて、プログラムで使用できる限り)を渡しているだけかもしれません。次に、それぞれをパターン マッチングしてから、適切な .xml に変換する必要があります。Registered Name.csvFunFunLineMnesia record
主な回答 編集

さて、ライブラリ モジュールではdelimiter.csvファイルの がcomma. そのモジュールで、 function: を見てもらいたいのですが、traverse_text/2現在は次のようになっています。
traverse_text(テキスト、バフ)->
    case scan("",$,,Text) の
        {done,SomeText}-> [SomeText|バフ];
        {値,レム}-> traverse_text(レム,[値|バフ])
    終わり。

を反映するために、上記の機能を変更してDELIMITERください。たとえば、 がdelimiterの場合semi-colon ( ; )、その関数は次のように変更されます。

traverse_text(テキスト、バフ)->
    case scan("",$;,Text) の
        {done,SomeText}-> [SomeText|バフ];
        {値,レム}-> traverse_text(レム,[値|バフ])
    終わり。

したがって、あなたdelimiterが違う場合は、上で示したようにその関数を変更してください(シンボルがどこにあるのか、どこにあるのかがわかると思いますdollar sign, followed by your actual delimiter)。次に、そのモジュールを再コンパイルして再ロードします。さらに課題が発生した場合はお知らせください。

于 2013-01-27T14:11:37.707 に答える