Erlang源码阅读方法和file:consult函数源码级解析

本文深入探讨了Erlang中查找源代码的方法,详细解析了file:consult/1函数的实现原理及其内部调用的file:open/2和file:consult_stream/1函数。通过代码示例,读者可以了解如何读取文件并解析其内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、查找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。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值