一、查找erlang源代码方法:
code:which(module)
例子:
code:which(file)
运行结果:
1> code:which(file).
"d:/erl9.3/lib/kernel-5.4.3/ebin/file.beam"
说明:一般直接使用code:which(module)返回的是module.beam的目录,这是一个erlang编译后的可执行文件。在 Erlang 的标准库里面,每个库有两个子目录。一个名为 src,包含源代码;另一个名为 ebin,包含编译后的 Erlang 代码。因此, file.erl 的源代码应该在下面这个目录:
"d:/erl9.3/lib/kernel-5.4.3/src/file.erl"
二、file:consult/1 函数源码阅读:
%%%-----------------------------------------------------------------
%%% The following functions, built upon the other interface functions,
%%% provide a higher-lever interface to files.
-spec consult(Filename) -> {ok, Terms} | {error, Reason} when
Filename :: name_all(),
Terms :: [term()],
Reason :: posix() | badarg | terminated | system_limit
| {Line :: integer(), Mod :: module(), Term :: term()}.
consult(File) ->
case open(File, [read]) of
{ok, Fd} ->
R = consult_stream(Fd),
_ = close(Fd),
R;
Error ->
Error
end.
file:open/2
%%%-----------------------------------------------------------------
%%% File io server functions.
%%% They operate on a single open file.
%%% Stateful.
%% Contemporary mode specification - list of options
-spec open(File, Modes) -> {ok, IoDevice} | {error, Reason} when
File :: Filename | iodata(),
Filename :: name_all(),
Modes :: [mode() | ram],
IoDevice :: io_device(),
Reason :: posix() | badarg | system_limit.
open(Item, ModeList) when is_list(ModeList) ->
case lists:member(raw, ModeList) of
%% Raw file, use ?PRIM_FILE to handle this file
true ->
Args = [file_name(Item) | ModeList],
case check_args(Args) of
ok ->
[FileName | _] = Args,
%% We rely on the returned Handle (in {ok, Handle})
%% being a pid() or a #file_descriptor{}
?PRIM_FILE:open(FileName, ModeList);
Error ->
Error
end;
false ->
case lists:member(ram, ModeList) of
%% RAM file, use ?RAM_FILE to handle this file
true ->
case check_args(ModeList) of
ok ->
?RAM_FILE:open(Item, ModeList);
Error ->
Error
end;
%% File server file
false ->
Args = [file_name(Item) | ModeList],
case check_args(Args) of
ok ->
[FileName | _] = Args,
call(open, [FileName, ModeList]);
Error ->
Error
end
end
end;
%% Old obsolete mode specification in atom or 2-tuple format
open(Item, Mode) ->
open(Item, mode_list(Mode)).
file:consult_stream/1
%%%-----------------------------------------------------------------
%%% Helpers
consult_stream(Fd) ->
_ = epp:set_encoding(Fd),
consult_stream(Fd, 1, []).
consult_stream(Fd, Line, Acc) ->
case io:read(Fd, '', Line) of
{ok,Term,EndLine} ->
consult_stream(Fd, EndLine, [Term|Acc]);
{error,Error,_Line} ->
{error,Error};
{eof,_Line} ->
{ok,lists:reverse(Acc)}
end.
三、个人理解
1.函数作用。
file:consult/1 的作用是读取文件里所有的数据类型,成功返回 {ok, [Tream]},否则返回 {error, Reason}。
2.参数类型。
参数 Filename 必须是 name_all() 类型。name_all() 的定义如下:
-type name_all() :: string() | atom() | deep_list() | (RawFilename :: binary()).
返回值terms是一个由 erlang项构成的列表,Reason 是posix() | badarg | terminated | system_limit | {Line :: integer(), Mod :: module(), Term :: term()} 中的任意一项。
3.函数逻辑
函数consult调用file:open(File, [read])函数,意思是使用 read 方式打开文件 File。
如果file:open/1 返回 {ok, Fd},则调用 file:consilt_stream(Fd) 解析文件到 R, 然后调用 close(Fd) 关闭文件, 再返回结果 R;
如果file:open/1 返回 {Error} ,则直接返回 Error。