nirvair
nirvair

Reputation: 4180

Issues with reading file in erlang

So, I am trying to read and write into a file. While writing into the file, I need to check if a particular index exist in file then I don't write and throw error. The data in file will look like this:

{1,{data,dcA,1}}.
{2, {data, dcA, 2}}.
{3,{data,dcA,3}}.

I added the dot at the end of each line because file:consult() needs the file like this.

Which is in this format.

{Index, {Data, Node, Index}}

When I have to add a new file, I check with this Index.

Here's what I have tried so far - https://pastebin.com/apnWLk45

And I run it like this:

193> {ok, P9} = poc:start(test1, self()).
{ok,<0.2863.0>}
194> poc:add(P9, Node, {6, data}).

In poc:add/3, P9 is the process id from the file:open. I defined before in shell as dcA And the third is the data - which is in this format - {Index, data}

Since I am using file:consult/1, it takes the filename as parameter. At that point, I only have process id. So I take the name from file:pid2name(_Server).

This runs perfectly when I run it for the first time.

When I run this again - poc:add(P9, Node, {6, data2}), I get an error in this line file:pid2name(_Server).

exception error: no match of right hand side value undefined

How can I solve this issue?

I am new to Erlang. Just been a week that I started learning.

Upvotes: 0

Views: 453

Answers (1)

7stud
7stud

Reputation: 48599

I am trying to read and write into a file. While writing into the file, I need to check if a particular index exist in file then I don't write and throw error.

A DETS table can easily do what you want:

-module(my).
-compile(export_all).

open_table() ->
    dets:open_file(my_data, [{type, set}, {file, "./my_data.dets"}]).

close_table() ->
    dets:close(my_data).

clear_table() ->
    dets:delete_all_objects(my_data).

insert({Key, _Rest}=Data) ->
    case dets:member(my_data, Key) of 
        true    -> throw(index_already_exists);
        false   -> dets:insert(my_data, Data)
    end.

all_items() ->
    dets:match(my_data, '$1').

In the shell:

~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V9.2  (abort with ^G)

1> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}

2> my:open_table().
{ok,my_data}

3> my:clear_table().
ok

4> my:all_items().
[]

5> my:insert({1, {data, a, b}}).
ok

6> my:insert({2, {data, c, d}}).
ok

7> my:insert({3, {data, e, f}}).
ok

8> my:all_items(). 
[[{1,{data,a,b}}],[{2,{data,c,d}}],[{3,{data,e,f}}]]

9> my:insert({1, {data, e, f}}).
** exception throw: index_already_exists
    in function  my:insert/1 (my.erl, line 15)

When I run this again - poc:add(P9, Node, {6, data2}), I get an error in this line file:pid2name(_Server):

exception error: no match of right hand side value undefined

When a process opens a file, it becomes linked to a process that handles the file I/O, which means that if the process that opens the file terminates abnormally, the I/O process will also terminate. Here is an example:

-module(my).
-compile(export_all).

start() ->
    {ok, Pid} = file:open('data.txt', [read, write]),
    spawn(my, add, [Pid, x, y]),
    exit("bye").


add(Pid, _X, _Y) ->
    timer:sleep(1000),  %Let start() process terminate.
    {ok, Fname} = file:pid2name(Pid),
    io:format("~s~n", [Fname]).

In the shell:

1> c(my).     
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}

2> my:start().
** exception exit: "bye"
     in function  my:start/0 (my.erl, line 7)
3> 
=ERROR REPORT==== 25-Jun-2018::13:28:48 ===
Error in process <0.72.0> with exit value:
{{badmatch,undefined},[{my,add,3,[{file,"my.erl"},{line,12}]}]}

According to the pid2name() docs:

pid2name(Pid) -> {ok, Filename} | undefined

the function can return undefined, which is what the error message is saying happened.

Upvotes: 2

Related Questions