无法捕获错误子句

Can not catch error clause

我正在尝试读取一个文件,当发生任何错误时,它应该匹配模式和 return 值

我的代码看起来像

read(File) ->
  try file:read_file(File) of
    {ok, Content} -> Content
  catch
    error:E -> {"Error reading", File, E};
    _:_     -> {allError}
  end.

当我运行时,我看到

1> file_read:read("/Users/harith/Downloads/er.txt").
<<"This file is read by erlang program\n">>
2> file_read:read("non-existent-file").
** exception error: no try clause matching {error,enoent}
     in function  file_read:read/1 (/Users/harith/code/IdeaProjects/others/erlang/programmingErlang/src/file_read.erl, line 16)
3>

为什么它没有捕捉到最通用的子句 _:_

仅仅是因为file:read当文件不存在时不会抛出异常,而是抛出一个元组{error,Error}。这是有道理的,因为不存在的文件是常见的,最难避免的。你可以这样写:

read(File) ->
  case file:read_file(File) of
    {ok, Content} -> Content;
    {error,E} -> {"Error reading", File, E}
  end. %% not very smart since read_file already does the job
read_file(Filename) -> {ok, Binary} | {error, Reason}

请阅读文档:http://www.erlang.org/doc/man/file.html#read_file-1

{error,enoent}file:read_file(File)的结果,你应该写成:

 case file:read_file(File) of
    {ok, Content} -> Content;
    {error:Error} -> {error: Error}
 end


-module(wy).
-compile(export_all).

read_hlp(File) ->
    try file:read_file(File) of
    {ok, Content} -> Content
    catch
    error:E -> {"Error reading", File, E};
    _:_     -> {allError}
    end.


read(File) ->
    try read_hlp(File) of
    Res -> Res
    catch
    error:Error ->
        Error
    _:_ -> all_exception
    end.

当您 运行 以上代码时,您将得到 {try_clause,{error,enoent}}。 原因是: 函数 read_hlp/1 中存在不匹配,因此异常将被调用的函数 read/1.

捕获

原因是因为 match_clause 错误发生在 tryof 之后的 "case" 部分,这超出了 try 捕获错误的范围。最简单的方法是按照@Pascal 的建议或做:

read(File) ->
    try
        {ok,Content} = file:read_file(File)
    catch
        error:E -> {"Error reading", File, E};
        _:_     -> {allError}
end.

如果 file:read_file 无法读取文件,那么它将 return {error,Reason} 导致匹配失败,您将收到 badmatch 错误。