阅读Erlang中的文件

h6my8fg2  于 2022-12-08  发布在  Erlang
关注(0)|答案(1)|浏览(162)

我有一个Erlang应用程序,它可以从文件中获取一些键/值对。
在其中一个文件中,我有一个到另一个文件夹的路径,而不是键/值对,其中有键/值对。
文件的读取工作正常,但每当我必须从文件中读取路径,然后再读取后续文件时,应用程序就会抱怨文件不存在。
如果我跳到容器中检查,我可以看到文件和后续文件。所以我猜我遗漏了一些东西。
这是我所拥有的:

get_kvs("keyvalue.properties"), %% <-- This works

{ok, PathToFile} = file:read_file("pathtofile.properties"),
get_kvs(PathToFile), %% <-- This crashes

档案:

  • keyvalue.properties
key_1=val_1
key_2=val_2
key_3=val_3
  • pathtofile.properties
/data/myfolder/hidden_keyvalue.properties
  • /data/myfolder/hidden_keyvalue.properties
extra_key1=extra_val1
extra_key2=extra_val2
extra_key3=extra_val3

get_metadata函数:

get_metadata(FileName) ->
    io:format(FileName),
    {ok, MetadataFile} = file:read_file(FileName),
    io:format(MetadataFile),
    Lines = binary:split(MetadataFile, <<"\n">>, [trim, global]),
    make_tuples(Lines, []).

make_tuples([Line|Lines], Acc) ->
    [Key, Value] = binary:split(Line, <<"=">>),
    make_tuples(Lines, [{Key, Value}|Acc]);
make_tuples([], Acc) -> lists:reverse(Acc).

无论何时运行它,我都可以看到PathToFile被正确填充,但当我试图读取路径时,我得到下面的错误:

keyvalue.propertiesextra_key_1=extra_val_1
extra_key_2=extra_val_2
extra_key_3=extra_val_3
/data/myfolder/hidden_keyvalue.properties
=CRASH REPORT==== 23-Mar-2022::07:46:30.612093 ===
  crasher:
    initial call: cowboy_stream_h:request_process/3
    pid: <0.735.0>
    registered_name: []
    exception error: no match of right hand side value {error,enoent}
      in function  hello_handler:get_metadata/1 (/data/apps/hello_server/src/hello_handler.erl, line 40)
      in call from hello_handler:child_call/1 (/data/apps/hello_server/src/hello_handler.erl, line 28)

你知道我错过了什么吗

pbpqsu0x

pbpqsu0x1#

After the OP has been modified to reflect the actual point of failure by removing try-catch , the error seems to be {error, enoent } which means The file does not exist . However, the same function is working in some scenarios and not when the path of the file to be read is itself taken from another file.
Just make sure there are mo additional characters, like newlines or non-printable characters after the content of the file which should actually be a valid path.
For example, when I tried with a value as such, <<"hidden_keyvalue.properties\n\n">> , then read_file gave me same result as {error, enoent} .
So it could be possible that the content of the file from which paths are read has additional non-printable characters at the end.

Ignore (Wrong Assumption)

I tried with a local setup and I think this line inside make_tuples is causing that behavior.

[Key, Value] = binary:split(Line, <<"=">>) %% <--- This match will succeed only if there are exactly 2 elements in the list produced by binary:split(...).

Given we are doing inside get_metadata

Lines = binary:split(MetadataFile, <<"\n">>, [trim, global]), %% <-- This splits the contents of the keyvalue.properties file into a List
make_tuples(Lines, [])

From the provided text, it appears that the content of keyvalue.proiperties file is ...

key_1=val_1
key_2=val_2
key_3=val_3
/data/myfolder/hidden_keyvalue.properties %% <-- This isn't a valid key-value pair

And with that last line, make_tuples while doing a match will fail the following way...

[Key, Value] = binary:split(<<"/data/myfolder/hidden_keyvalue.properties">>, <<"=">>).
** exception error: no match of right hand side value [<<"/data/myfolder/hidden_keyvalue.properties">>]

That pattern-match expression requires exactly 2 elements on the right-hand side(the Term/Value side). Since the line with path-entry in the keyvalue.properties does not have an = , so the split produces a list with 1 element, and so the match fails.
To address this...

  1. We can change the format of keyvalue.properties so that every line is a valid key-value pair, but not sure how feasible it will be in the context of the program.
  2. Or, we can change that pattern-match form of list so that it can accept non-exact number of terms while matching
make_tuples([Line|Lines], Acc) ->
    %% [Key|Value] is at least 1 element list, [Key, Value] is exactly 2 elements list
    [Key|Value] = binary:split(Line, <<"=">>), %% <-- Now Value becomes a list of binary
    make_tuples(Lines, [{Key, get_value(Value)}|Acc]); %% <-- Additional get_value function to extract 'Value binary' from the head of the 'Value List' produced in the previous line
make_tuples([], Acc) -> lists:reverse(Acc).

get_value([]) ->
    <<>>;
get_value([V|_]) -> V.

Assumptions

get_kvs invokes get_metadata which in turn invokes make_tuples .
keyvalue.properties file content has both valid key-value pairs and also some non-key-value entries

相关问题