查看源代码 io (stdlib v6.2)

标准 I/O 服务器接口函数。

此模块提供到标准 Erlang I/O 服务器的接口。输出函数如果成功都返回 ok,如果不成功则会退出。

此模块中的所有函数都有一个可选参数 IoDevice。如果包含此参数,则它必须是处理 I/O 协议的进程的 pid。通常,它是 file:open/2 返回的 IoDevice。如果没有给出 IoDevice,则使用 standard_io

有关 I/O 协议的描述,请参阅用户指南中的 Erlang I/O 协议部分。

警告

提供给函数 put_chars/2 的数据应为 unicode:chardata/0 格式。这意味着向此函数提供二进制文件的程序必须先将其转换为 UTF-8,然后再尝试在 I/O 设备上输出数据。

如果 I/O 设备设置为二进制模式,则函数 get_chars/2,3get_line/1,2 可以返回二进制文件而不是列表。二进制文件以 UTF-8 编码。

要使用 ISO Latin-1 编码的二进制文件,请改用 file 模块。

有关字符编码之间的转换函数,请参阅 unicode 模块。

错误信息

此模块中提到的 ErrorInfo 是从所有 I/O 模块返回的标准 ErrorInfo 结构。它具有以下格式

{ErrorLocation, Module, ErrorDescriptor}

使用以下调用获取描述错误的字符串

Module:format_error(ErrorDescriptor)

概述

类型

I/O 设备,可以是 standard_io/0standard_error/0user/0file:io_server/0、注册的名称,或任何处理 I/O 协议的 pid。

当没有数据时,I/O 服务器发送的内容。

I/O 设备 standard_error 可用于将输出定向到当前操作系统认为适合错误输出的任何 I/O 设备。当标准输出被重定向时,这会很有用。

分配给进程的默认标准 I/O 设备。当此模块的函数调用中未指定 IoDevice 参数时,将使用此设备。

可用于与节点本地 stdoutstdin 交互的 I/O 设备。这可以是终端、管道、文件或它们的组合。

函数

检索 IoDevice 的列数(即终端的宽度)。

IoDevice 读取字符,使用 Prompt 提示。根据 Format 解释字符。

根据 FormatData 中的项写入 IoDevice

IoDevice 读取 Count 个字符,使用 Prompt 提示。

IoDevice 读取一行,使用 Prompt 提示。

请求 IoDevice 的所有可用选项及其当前值。

等效于 nl(standard_io)

将换行符写入标准输出 (IoDevice)。

IoDevice 读取数据,使用 Prompt 提示。

IoDevice 读取数据,使用 Prompt 提示。

返回用户请求的可打印 Unicode 字符范围。

CharData 的字符写入 IoDevice

从标准输入 (IoDevice) 读取一个项 Term,使用 Prompt 提示。

IoDevice 读取一个项 Term,使用 Prompt 提示。

等效于 rows(standard_io)

检索 IoDevice 的行数(即终端的高度)。

IoDevice 读取数据,使用 Prompt 提示。

IoDevice 读取数据,使用 Prompt 提示。

IoDevice 设置选项。可能的选项和值因 I/O 设备而异。

将项 Term 写入 IoDevice

类型

-type device() :: atom() | pid() | file:io_server() | standard_io() | standard_error() | user().

I/O 设备,可以是 standard_io/0standard_error/0user/0file:io_server/0、注册的名称,或任何处理 I/O 协议的 pid。

链接到此类型

encoding()

查看源代码 (未导出)
-type encoding() ::
          latin1 | unicode | utf8 | utf16 | utf32 | {utf16, big | little} | {utf32, big | little}.
链接到此类型

expand_fun()

查看源代码 (未导出)
-type expand_fun() :: fun((string()) -> {yes | no, string(), list()}).
-type format() :: atom() | string() | binary().
链接到此类型

getopt()

查看源代码 (未导出)
-type getopt() :: {terminal | stdin | stdout | stderr, boolean()} | option().
链接到此类型

option()

查看源代码 (未导出)
-type option() ::
          {binary, boolean()} |
          {echo, boolean()} |
          {expand_fun, expand_fun()} |
          {encoding, encoding()} |
          {atom(), term()}.
链接到此类型

parse_form_ret()

查看源代码 (未导出)
-type parse_form_ret() ::
          {ok, AbsForm :: erl_parse:abstract_form(), EndLocation :: erl_anno:location()} |
          {eof, EndLocation :: erl_anno:location()} |
          {error,
           ErrorInfo :: erl_scan:error_info() | erl_parse:error_info(),
           ErrorLocation :: erl_anno:location()} |
          server_no_data().
链接到此类型

parse_ret()

查看源代码 (未导出)
-type parse_ret() ::
          {ok, ExprList :: [erl_parse:abstract_expr()], EndLocation :: erl_anno:location()} |
          {eof, EndLocation :: erl_anno:location()} |
          {error,
           ErrorInfo :: erl_scan:error_info() | erl_parse:error_info(),
           ErrorLocation :: erl_anno:location()} |
          server_no_data().
链接到此类型

prompt()

查看源代码 (未导出)
-type prompt() :: atom() | unicode:chardata().
-type server_no_data() :: {error, ErrorDescription :: term()} | eof.

当没有数据时,I/O 服务器发送的内容。

链接到此类型

setopt()

查看源代码 (未导出)
-type setopt() :: binary | list | option().
-type standard_error() :: standard_error.

I/O 设备 standard_error 可用于将输出定向到当前操作系统认为适合错误输出的任何 I/O 设备。当标准输出被重定向时,这会很有用。

在类 Unix 操作系统上的示例

$ erl -noinput -eval 'io:format(standard_error,"Error: ~s~n",["error 11"]),'\
'init:stop().' > /dev/null
Error: error 11
-type standard_io() :: standard_io.

分配给进程的默认标准 I/O 设备。当此模块的函数调用中未指定 IoDevice 参数时,将使用此设备。

有时需要使用显式的 IoDevice 参数,该参数引用默认的 I/O 设备。在使用可以访问文件或默认 I/O 设备的函数时会出现这种情况。原子 standard_io 具有此特殊含义。以下示例对此进行了说明

27> io:read('enter>').
enter>foo.
{ok,foo}
28> io:read(standard_io, 'enter>').
enter>bar.
{ok,bar}

默认情况下,发送到 standard_io 的所有 I/O 都将最终发送到生成调用进程的节点的 user I/O 设备。

standard_iogroup_leader/0 的别名,因此为了更改默认输入/输出请求的发送位置,您可以使用 group_leader(NewGroupLeader, self()) 更改当前进程的组长。

-type user() :: user.

可用于与节点本地 stdoutstdin 交互的 I/O 设备。这可以是终端、管道、文件或它们的组合。

使用 getopts/1 获取有关 I/O 设备的更多信息。

有关 user 如何处理 Unicode 的详细信息,请参阅 Erlang 用户指南中的 交互式 ShellEscripts 和非交互式 I/O

函数

-spec columns() -> {ok, pos_integer()} | {error, enotsup}.

等效于 columns(standard_io)

-spec columns(IoDevice) -> {ok, pos_integer()} | {error, enotsup} when IoDevice :: device().

检索 IoDevice 的列数(即终端的宽度)。

该函数对于终端设备成功执行,并为所有其他 I/O 设备返回 {error, enotsup}

-spec format(Format) -> ok when Format :: format().

等效于 format(Format, [])

-spec format(Format, Data) -> ok when Format :: format(), Data :: [term()].

等效于 format(standard_io, Format, Data)

链接到此函数

format(IoDevice, Format, Data)

查看源代码
-spec format(IoDevice, Format, Data) -> ok
                when IoDevice :: device(), Format :: format(), Data :: [term()].

等效于 fwrite(IoDevice, Format, Data)

-spec fread(Prompt, Format) -> Result
               when
                   Prompt :: prompt(),
                   Format :: format(),
                   Result :: {ok, Terms :: [term()]} | eof | {error, What :: term()}.

等效于 fread(standard_io, Prompt, Format)

链接到此函数

fread(IoDevice, Prompt, Format)

查看源代码
-spec fread(IoDevice, Prompt, Format) -> Result
               when
                   IoDevice :: device(),
                   Prompt :: prompt(),
                   Format :: format(),
                   Result ::
                       {ok, Terms :: [term()]} |
                       {error, {fread, FreadError :: io_lib:fread_error()}} |
                       server_no_data().

IoDevice 读取字符,使用 Prompt 提示。根据 Format 解释字符。

Format 可以包含以下内容

  • 空白字符(空格制表符换行符),导致读取输入直到下一个非空白字符。
  • 必须与下一个输入字符匹配的普通字符。
  • 控制序列,其通用格式为 ~*FMC,其中
    • 字符 * 是一个可选的返回抑制字符。它提供了一种指定要省略的字段的方法。
    • F 是输入字段的 字段宽度
    • M 是一个可选的转换修饰符(其中 t 是唯一支持的,表示 Unicode 转换)。
    • C 确定控制序列的类型。
    除非另有说明,否则所有控制序列都会忽略前导空格。输入字段的宽度不能超过一行。可用的控制序列:
    • ~ - 输入中应存在单个 ~

    • d - 预期为十进制整数。

    • u - 预期为 2-36 进制的无符号整数。字段宽度参数用于指定进制。不会跳过前导空白字符。

    • - - 预期为可选的符号字符。符号字符 - 返回值 -1。符号字符 + 或无符号返回 1。忽略字段宽度参数。不会跳过前导空白字符。

    • # - 预期为带有 Erlang 样式进制前缀的 2-36 进制整数(例如,"16#ffff")。

    • f - 预期为浮点数。它必须遵循 Erlang 浮点数语法。

    • s - 读取非空白字符的字符串。如果已指定字段宽度,则读取此数量的字符并剥离所有尾随空白字符。返回 Erlang 字符串(字符列表)。

      如果 Unicode 转换生效 (~ts),则接受 > 255 的字符,否则不接受。使用转换修饰符,返回的列表也可以因此包含 > 255 的整数

      1> io:fread("Prompt> ","~s").
      Prompt> <Characters beyond latin1 range not printable in this medium>
      {error,{fread,string}}
      2> io:fread("Prompt> ","~ts").
      Prompt> <Characters beyond latin1 range not printable in this medium>
      {ok,[[1091,1085,1080,1094,1086,1076,1077]]}
    • a - 类似于 s,但结果字符串转换为原子。

    • c - 读取等于字段宽度的字符数(默认为 1),并作为 Erlang 字符串返回。但是,不会像 s 一样省略前导和尾随空白字符。返回所有字符。

      Unicode 转换修饰符的工作方式与 s 相同

      1> io:fread("Prompt> ","~c").
      Prompt> <Character beyond latin1 range not printable in this medium>
      {error,{fread,string}}
      2> io:fread("Prompt> ","~tc").
      Prompt> <Character beyond latin1 range not printable in this medium>
      {ok,[[1091]]}
    • l - 返回到该点为止已扫描的字符数,包括空白字符。

    该函数返回
    • {ok, Terms} - 读取成功,Terms 是成功匹配和读取的项的列表。

    • eof - 遇到文件结尾。

    • {error, FreadError} - 读取失败,FreadError 给出了有关错误的提示。

    • {error, ErrorDescription} - 读取操作失败,参数 ErrorDescription 给出了有关错误的提示。

示例

20> io:fread('enter>', "~f~f~f").
enter>1.9 35.5e3 15.0
{ok,[1.9,3.55e4,15.0]}
21> io:fread('enter>', "~10f~d").
enter>     5.67899
{ok,[5.678,99]}
22> io:fread('enter>', ":~10s:~10c:").
enter>:   alan   :   joe    :
{ok, ["alan", "   joe    "]}
-spec fwrite(Format) -> ok when Format :: format().

等效于 fwrite(Format, [])

-spec fwrite(Format, Data) -> ok when Format :: format(), Data :: [term()].

等效于 fwrite(standard_io, Format, Data)

链接到此函数

fwrite(IoDevice, Format, Data)

查看源代码
-spec fwrite(IoDevice, Format, Data) -> ok
                when IoDevice :: device(), Format :: format(), Data :: [term()].

根据 FormatData 中的项写入 IoDevice

Format 包含复制到输出设备的普通字符,以及用于格式化的控制序列,请参见下文。如果 Format 是原子或二进制,则首先借助 atom_to_list/1binary_to_list/1 将其转换为列表。示例

1> io:fwrite("Hello world!~n", []).
Hello world!
ok

控制序列的通用格式为 ~F.P.PadModC

字符 C 确定要使用的控制序列类型。它是唯一必需的字段。所有 FPPadMod 都是可选的。例如,要使用 # 作为 Pad,但对 FP 使用默认值,可以编写 ~..#C

  • F 是打印参数的 字段宽度。负值表示参数在字段内左对齐,否则为右对齐。如果未指定字段宽度,则使用所需的打印宽度。如果指定的字段宽度太小,则整个字段将填充 * 字符。

  • P 是打印参数的 精度。如果未指定精度,则使用默认值。精度的解释取决于控制序列。除非另有说明,否则使用参数 within 来确定打印宽度。

  • Pad 是填充字符。这是用于填充参数的打印表示形式的字符,以便其符合指定的字段宽度和精度。只能指定一个填充字符,并且在适用时,它将用于字段宽度和精度。默认填充字符是 ' ' (空格)。

  • Mod 是控制序列修饰符。这是一个或多个更改 Data 解释的字符。

    当前的修饰符是

    • t - 用于 Unicode 转换。

    • l - 用于阻止 pP 检测可打印字符。

    • k - 用于 pPwW,以按映射键 ordered 顺序格式化映射(请参阅 maps:iterator_order/0)。

    • K - 类似于 k,用于按映射键顺序格式化映射,但采用一个额外的参数,用于指定 maps:iterator_order/0

      例如

      > M = #{ a => 1, b => 2 }.
      #{a => 1,b => 2}
      > io:format("~Kp~n", [reversed, M]).
      #{b => 2,a => 1}
      ok

如果 FPPad* 字符,则使用 Data 中的下一个参数作为值。例如

1> io:fwrite("~*.*.0f~n",[9, 5, 3.14159265]).
003.14159
ok

要使用文字 * 字符作为 Pad,必须将其作为参数传递

2> io:fwrite("~*.*.*f~n",[9, 5, $*, 3.14159265]).
**3.14159
ok

可用的控制序列

  • ~ - 写入字符 ~

  • c - 该参数是一个被解释为 ASCII 代码的数字。精度是字符打印的次数,默认为字段宽度,字段宽度又默认为 1。示例

    1> io:fwrite("|~10.5c|~-10.5c|~5c|~n", [$a, $b, $c]).
    |     aaaaa|bbbbb     |ccccc|
    ok

    如果 Unicode 转换修饰符 (t) 生效,则整数参数可以是表示有效 Unicode 代码点的任何数字,否则它应是小于或等于 255 的整数,否则使用 16#FF 屏蔽

    2> io:fwrite("~tc~n",[1024]).
    \x{400}
    ok
    3> io:fwrite("~c~n",[1024]).
    ^@
    ok
  • f - 该参数是一个浮点数,写为 [-]ddd.ddd,其中精度是小数点后的位数。默认精度为 6,且不能 < 1。

  • e - 该参数是一个浮点数,写为 [-]d.ddde+-ddd,其中精度是写入的位数。默认精度为 6,且不能 < 2。

  • g - 如果参数 >= 0.1 且 < 10000.0,则该参数是一个浮点数,写为 f。否则,它以 e 格式写入。精度是有效数字的位数。默认为 6,且不能 < 2。如果浮点数的绝对值不允许以所需的有效数字位数以 f 格式写入,则也会以 e 格式写入。

  • s - 使用字符串语法打印参数。如果不存在 Unicode 转换修饰符,则该参数是 iolist/0binary/0atom/0。如果 Unicode 转换修饰符 (t) 生效,则该参数是 unicode:chardata(),这意味着二进制文件是 UTF-8 编码的。字符将不带引号打印。字符串首先会被指定的精度截断,然后填充并调整到指定的字段宽度。默认精度是字段宽度。

    此格式可用于打印任何对象并截断输出,使其适合指定的字段

    1> io:fwrite("|~10w|~n", [{hey, hey, hey}]).
    |**********|
    ok
    2> io:fwrite("|~10s|~n", [io_lib:write({hey, hey, hey})]).
    |{hey,hey,h|
    3> io:fwrite("|~-10.8s|~n", [io_lib:write({hey, hey, hey})]).
    |{hey,hey  |
    ok

    如果未指定 Unicode 转换修饰符,则具有 > 255 的整数的列表被认为是错误

    4> io:fwrite("~ts~n",[[1024]]).
    \x{400}
    ok
    5> io:fwrite("~s~n",[[1024]]).
    ** exception error: bad argument
         in function  io:format/3
            called as io:format(<0.53.0>,"~s~n",[[1024]])
  • w - 使用标准语法写入数据。这用于输出 Erlang 项。如果原子包含嵌入的不可打印字符,则在引号内打印。除非使用 Unicode 转换修饰符 (t),否则原子字符 > 255 将被转义。浮点数将以最短的、正确舍入的字符串精确打印。

  • p - 使用与 ~w 相同的方式以标准语法写入数据,但会将打印表示形式长于一行的项分成多行,并合理缩进每一行。不支持左对齐。它还会尝试检测可打印字符的平面列表,并将这些列表输出为字符串。例如

    1> T = [{attributes,[[{id,age,1.50000},{mode,explicit},
    {typename,"INTEGER"}], [{id,cho},{mode,explicit},{typename,'Cho'}]]},
    {typename,'Person'},{tag,{'PRIVATE',3}},{mode,implicit}].
    ...
    2> io:fwrite("~w~n", [T]).
    [{attributes,[[{id,age,1.5},{mode,explicit},{typename,
    [73,78,84,69,71,69,82]}],[{id,cho},{mode,explicit},{typena
    me,'Cho'}]]},{typename,'Person'},{tag,{'PRIVATE',3}},{mode
    ,implicit}]
    ok
    3> io:fwrite("~62p~n", [T]).
    [{attributes,[[{id,age,1.5},
                   {mode,explicit},
                   {typename,"INTEGER"}],
                  [{id,cho},{mode,explicit},{typename,'Cho'}]]},
     {typename,'Person'},
     {tag,{'PRIVATE',3}},
     {mode,implicit}]
    ok

    字段宽度指定最大行长度。默认为 80。精度指定项的初始缩进。它默认为在相同调用 write/1format/1,2,3 时此行上打印的字符数。例如,使用上面的 T

    4> io:fwrite("Here T = ~62p~n", [T]).
    Here T = [{attributes,[[{id,age,1.5},
                            {mode,explicit},
                            {typename,"INTEGER"}],
                           [{id,cho},
                            {mode,explicit},
                            {typename,'Cho'}]]},
              {typename,'Person'},
              {tag,{'PRIVATE',3}},
              {mode,implicit}]
    ok

    从 Erlang/OTP 21.0 开始,可以使用字段宽度值 0 来指定行是无限长的,这意味着不会插入换行符。例如

    5> io:fwrite("~0p~n", [lists:seq(1, 30)]).
    [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
    ok

    当指定修饰符 l 时,不会进行可打印字符列表的检测,例如

    6> S = [{a,"a"}, {b, "b"}],
       io:fwrite("~15p~n", [S]).
    [{a,"a"},
     {b,"b"}]
    ok
    7> io:fwrite("~15lp~n", [S]).
    [{a,[97]},
     {b,[98]}]
    ok

    Unicode 转换修饰符 t 指定如何处理拉丁语-1 代码点范围之外的字符(在原子、字符串和二进制文件中)。例如,打印包含 > 255 字符的原子

    8> io:fwrite("~p~n",[list_to_atom([1024])]).
    '\x{400}'
    ok
    9> io:fwrite("~tp~n",[list_to_atom([1024])]).
    'Ѐ'
    ok

    默认情况下,Erlang 仅检测拉丁语-1 范围内的字符列表作为字符串,但是可以使用 +pc unicode 标志来更改此设置(有关详细信息,请参阅 printable_range/0)。例如

    10> io:fwrite("~p~n",[[214]]).
    "Ö"
    ok
    11> io:fwrite("~p~n",[[1024]]).
    [1024]
    ok
    12> io:fwrite("~tp~n",[[1024]]).
    [1024]
    ok

    但是,如果 Erlang 使用 +pc unicode 启动

    13> io:fwrite("~p~n",[[1024]]).
    [1024]
    ok
    14> io:fwrite("~tp~n",[[1024]]).
    "Ѐ"
    ok

    类似地,如果指定 t 修饰符,则看起来像 UTF-8 编码字符串的二进制文件将使用二进制字符串语法输出

    15> io:fwrite("~p~n", [<<208,128>>]).
    <<208,128>>
    ok
    16> io:fwrite("~tp~n", [<<208,128>>]).
    <<"Ѐ"/utf8>>
    ok
    17> io:fwrite("~tp~n", [<<128,128>>]).
    <<128,128>>
    ok
  • W - 以与 ~w 相同的方式写入数据,但接受一个额外的参数,即打印术语的最大深度。任何低于此深度的内容都将替换为 ...。例如,使用上面的 T

    8> io:fwrite("~W~n", [T,9]).
    [{attributes,[[{id,age,1.5},{mode,explicit},{typename,...}],
    [{id,cho},{mode,...},{...}]]},{typename,'Person'},
    {tag,{'PRIVATE',3}},{mode,implicit}]
    ok

    如果达到最大深度,则无法在结果输出中读取。此外,元组中的 ,... 形式表示元组中还有更多元素,但这些元素低于打印深度。

  • P - 以与 ~p 相同的方式写入数据,但接受一个额外的参数,即打印术语的最大深度。任何低于此深度的内容都将替换为 ...,例如

    9> io:fwrite("~62P~n", [T,9]).
    [{attributes,[[{id,age,1.5},{mode,explicit},{typename,...}],
                  [{id,cho},{mode,...},{...}]]},
     {typename,'Person'},
     {tag,{'PRIVATE',3}},
     {mode,implicit}]
    ok
  • B - 以 2-36 为基数写入整数,默认基数为 10。负整数会打印前导短划线。

    精度字段选择基数,例如

    1> io:fwrite("~.16B~n", [31]).
    1F
    ok
    2> io:fwrite("~.2B~n", [-19]).
    -10011
    ok
    3> io:fwrite("~.36B~n", [5*36+35]).
    5Z
    ok
  • X - 类似于 B,但接受一个额外的参数,该参数是要插入到数字之前的前缀,但在前导短划线(如果有)之后。

    前缀可以是可能很深的一系列字符或一个原子。示例

    1> io:fwrite("~X~n", [31,"10#"]).
    10#31
    ok
    2> io:fwrite("~.16X~n", [-31,"0x"]).
    -0x1F
    ok
  • # - 类似于 B,但使用 Erlang 风格的 # 分隔的基数前缀打印数字。示例

    1> io:fwrite("~.10#~n", [31]).
    10#31
    ok
    2> io:fwrite("~.16#~n", [-31]).
    -16#1F
    ok
  • b - 类似于 B,但打印小写字母。

  • x - 类似于 X,但打印小写字母。

  • + - 类似于 #,但打印小写字母。

  • n - 写入新行。

  • i - 忽略下一个术语。

该函数返回

  • ok - 格式化成功。

如果发生错误,则没有输出。示例

1> io:fwrite("~s ~w ~i ~w ~c ~n",['abc def', 'abc def', {foo, 1},{foo, 1}, 65]).
abc def 'abc def'  {foo,1} A
ok
2> io:fwrite("~s", [65]).
** exception error: bad argument
     in function  io:format/3
        called as io:format(<0.53.0>,"~s","A")

在此示例中,尝试使用字符串格式化指令 "~s" 输出单个字符 65。

链接到此函数

get_chars(Prompt, Count)

查看源代码
-spec get_chars(Prompt, Count) -> Data | server_no_data()
                   when
                       Prompt :: prompt(),
                       Count :: non_neg_integer(),
                       Data :: string() | unicode:unicode_binary().

等效于 get_chars(standard_io, Prompt, Count)

链接到此函数

get_chars(IoDevice, Prompt, Count)

查看源代码
-spec get_chars(IoDevice, Prompt, Count) -> Data | server_no_data()
                   when
                       IoDevice :: device(),
                       Prompt :: prompt(),
                       Count :: non_neg_integer(),
                       Data :: string() | unicode:unicode_binary().

IoDevice 读取 Count 个字符,使用 Prompt 提示。

该函数返回

  • Data - 输入字符。如果 I/O 设备支持 Unicode,则数据可以表示代码点 > 255(latin1 范围)。如果 I/O 服务器设置为传递二进制文件,则它们以 UTF-8 编码(无论 I/O 设备是否支持 Unicode)。如果要将数据作为 latin1 编码的二进制文件返回,则应改用 file:read/2

  • eof - 遇到文件结尾。

  • {error, ErrorDescription} - 其他(罕见)错误情况,例如,如果从 NFS 文件系统读取,则为 {error, estale}

-spec get_line(Prompt) -> Data | server_no_data()
                  when Prompt :: prompt(), Data :: string() | unicode:unicode_binary().

等效于 get_line(standard_io, Prompt)

链接到此函数

get_line(IoDevice, Prompt)

查看源代码
-spec get_line(IoDevice, Prompt) -> Data | server_no_data()
                  when
                      IoDevice :: device(),
                      Prompt :: prompt(),
                      Data :: string() | unicode:unicode_binary().

IoDevice 读取一行,使用 Prompt 提示。

该函数返回

  • Data - 以换行符(或文件结尾)结尾的行中的字符。如果 I/O 设备支持 Unicode,则数据可以表示代码点 > 255(latin1 范围)。如果 I/O 服务器设置为传递二进制文件,则它们以 UTF-8 编码(无论 I/O 设备是否支持 Unicode)。如果要将数据作为 latin1 编码的二进制文件返回,则应改用 file:read_line/1

  • eof - 遇到文件结尾。

  • {error, ErrorDescription} - 其他(罕见)错误情况,例如,如果从 NFS 文件系统读取,则为 {error, estale}

-spec getopts() -> [getopt()] | {error, Reason} when Reason :: term().

等效于 getopts(standard_io)

-spec getopts(IoDevice) -> [getopt()] | {error, Reason} when IoDevice :: device(), Reason :: term().

请求 IoDevice 的所有可用选项及其当前值。

例如

1> {ok,F} = file:open("/dev/null",[read]).
{ok,<0.42.0>}
2> io:getopts(F).
[{binary,false},{encoding,latin1}]

此处,文件 I/O 服务器返回文件的所有可用选项,这些选项是预期的选项,encodingbinary。但是,标准 shell 还有更多选项

3> io:getopts().
[{expand_fun,#Fun<group.0.120017273>},
 {echo,true},
 {binary,false},
 {encoding,unicode},
 {terminal,true},
 {stdout,true},
 {stderr,true},
 {stdin,true}]

正如所见,此示例是在终端支持 Unicode 输入和输出的环境中运行的。

stdinstdoutstderr 选项是只读的,并指示流是否为终端。当它是终端时,Erlang 运行的大多数系统允许使用 ANSI 转义码来控制终端的输入或输出。

terminalstdout 的别名。

有关其他选项的说明,请参阅 setopts/1

-spec nl() -> ok.

等效于 nl(standard_io)

-spec nl(IoDevice) -> ok when IoDevice :: device().

将换行符写入标准输出 (IoDevice)。

链接到此函数

parse_erl_exprs(Prompt)

查看源代码
-spec parse_erl_exprs(Prompt) -> Result when Prompt :: prompt(), Result :: parse_ret().

等效于 parse_erl_exprs(standard_io, Prompt)

链接到此函数

parse_erl_exprs(IoDevice, Prompt)

查看源代码
-spec parse_erl_exprs(IoDevice, Prompt) -> Result
                         when IoDevice :: device(), Prompt :: prompt(), Result :: parse_ret().

等效于 parse_erl_exprs(IoDevice, Prompt, 1)

链接到此函数

parse_erl_exprs(IoDevice, Prompt, StartLocation)

查看源代码
-spec parse_erl_exprs(IoDevice, Prompt, StartLocation) -> Result
                         when
                             IoDevice :: device(),
                             Prompt :: prompt(),
                             StartLocation :: erl_anno:location(),
                             Result :: parse_ret().

等效于 parse_erl_exprs(IoDevice, Prompt, StartLocation, [])

链接到此函数

parse_erl_exprs(IoDevice, Prompt, StartLocation, Options)

查看源代码 (自 OTP R16B 起)
-spec parse_erl_exprs(IoDevice, Prompt, StartLocation, Options) -> Result
                         when
                             IoDevice :: device(),
                             Prompt :: prompt(),
                             StartLocation :: erl_anno:location(),
                             Options :: erl_scan:options(),
                             Result :: parse_ret().

IoDevice 读取数据,使用 Prompt 提示。

从位置 StartLocation 开始读取。参数 Options 作为函数 erl_scan:tokens/4 的参数 Options 传递。数据被标记化和解析,就像它是一系列 Erlang 表达式一样,直到达到最后一个点 (.)。

该函数返回

  • {ok, ExprList, EndLocation} - 解析成功。

  • {eof, EndLocation} - 标记器遇到文件结尾。

  • eof - I/O 服务器遇到文件结尾。

  • {error, ErrorInfo, ErrorLocation} - 标记化或解析时发生错误。

  • {error, ErrorDescription} - 其他(罕见)错误情况,例如,如果从 NFS 文件系统读取,则为 {error, estale}

示例

25> io:parse_erl_exprs('enter>').
enter>abc(), "hey".
{ok, [{call,1,{atom,1,abc},[]},{string,1,"hey"}],2}
26> io:parse_erl_exprs('enter>').
enter>abc("hey".
{error,{1,erl_parse,["syntax error before: ",["'.'"]]},2}
链接到此函数

parse_erl_form(Prompt)

查看源代码
-spec parse_erl_form(Prompt) -> Result when Prompt :: prompt(), Result :: parse_form_ret().

等效于 parse_erl_form(standard_io, Prompt)

链接到此函数

parse_erl_form(IoDevice, Prompt)

查看源代码
-spec parse_erl_form(IoDevice, Prompt) -> Result
                        when IoDevice :: device(), Prompt :: prompt(), Result :: parse_form_ret().

等效于 parse_erl_form(IoDevice, Prompt, 1)

链接到此函数

parse_erl_form(IoDevice, Prompt, StartLocation)

查看源代码
-spec parse_erl_form(IoDevice, Prompt, StartLocation) -> Result
                        when
                            IoDevice :: device(),
                            Prompt :: prompt(),
                            StartLocation :: erl_anno:location(),
                            Result :: parse_form_ret().

等效于 parse_erl_form(IoDevice, Prompt, StartLocation, [])

链接到此函数

parse_erl_form(IoDevice, Prompt, StartLocation, Options)

查看源代码 (自 OTP R16B 起)
-spec parse_erl_form(IoDevice, Prompt, StartLocation, Options) -> Result
                        when
                            IoDevice :: device(),
                            Prompt :: prompt(),
                            StartLocation :: erl_anno:location(),
                            Options :: erl_scan:options(),
                            Result :: parse_form_ret().

IoDevice 读取数据,使用 Prompt 提示。

从位置 StartLocation 开始读取。参数 Options 作为函数 erl_scan:tokens/4 的参数 Options 传递。数据被标记化和解析,就像它是一个 Erlang 形式(Erlang 源文件中有效的 Erlang 表达式之一),直到达到最后一个点 (.)。

该函数返回

  • {ok, AbsForm, EndLocation} - 解析成功。

  • {eof, EndLocation} - 标记器遇到文件结尾。

  • eof - I/O 服务器遇到文件结尾。

  • {error, ErrorInfo, ErrorLocation} - 标记化或解析时发生错误。

  • {error, ErrorDescription} - 其他(罕见)错误情况,例如,如果从 NFS 文件系统读取,则为 {error, estale}

链接到此函数

printable_range()

查看源代码 (自 OTP R16B 起)
-spec printable_range() -> unicode | latin1.

返回用户请求的可打印 Unicode 字符范围。

用户可以请求一系列字符,这些字符将在 shell 和格式化函数通过启发式方法检测字符串时被视为可打印的。这可以通过在启动 Erlang 时提供 +pc <range> 来完成。

<range> 的唯一有效值是 latin1unicodelatin1 表示仅代码点 < 256(控制字符等除外)被视为可打印的。unicode 表示所有 Unicode 字符范围中的所有可打印字符都被 I/O 函数视为可打印的。

默认情况下,启动 Erlang 时,仅 latin1 范围的字符表示整数列表是一个字符串。

使用该设置的最简单方法是调用 io_lib:printable_list/1,它使用此函数的返回值来确定列表是否为可打印字符的字符串。

注意

在未来的版本中,此函数可能会返回更多值和范围。为避免兼容性问题,建议使用函数 io_lib:printable_list/1

-spec put_chars(CharData) -> ok when CharData :: unicode:chardata().

等效于 put_chars(standard_io, CharData)

链接到此函数

put_chars(IoDevice, CharData)

查看源代码
-spec put_chars(IoDevice, CharData) -> ok when IoDevice :: device(), CharData :: unicode:chardata().

CharData 的字符写入 IoDevice

如果要将 latin1 编码的字节写入 IoDevice,则应改用 file:write/2

-spec read(Prompt) -> Result
              when
                  Prompt :: prompt(),
                  Result :: {ok, Term :: term()} | server_no_data() | {error, ErrorInfo},
                  ErrorInfo :: erl_scan:error_info() | erl_parse:error_info().

等效于 read(standard_io, Prompt)

链接到此函数

read(IoDevice, Prompt)

查看源代码
-spec read(IoDevice, Prompt) -> Result
              when
                  IoDevice :: device(),
                  Prompt :: prompt(),
                  Result :: {ok, Term :: term()} | server_no_data() | {error, ErrorInfo},
                  ErrorInfo :: erl_scan:error_info() | erl_parse:error_info().

从标准输入 (IoDevice) 读取一个项 Term,使用 Prompt 提示。

该函数返回

  • {ok, Term} - 解析成功。

  • eof - 遇到文件结尾。

  • {error, ErrorInfo} - 解析失败。

  • {error, ErrorDescription} - 其他(罕见)错误情况,例如,如果从 NFS 文件系统读取,则为 {error, estale}

链接到此函数

read(IoDevice, Prompt, StartLocation)

查看源代码
-spec read(IoDevice, Prompt, StartLocation) -> Result
              when
                  IoDevice :: device(),
                  Prompt :: prompt(),
                  StartLocation :: erl_anno:location(),
                  Result ::
                      {ok, Term :: term(), EndLocation :: erl_anno:location()} |
                      {eof, EndLocation :: erl_anno:location()} |
                      server_no_data() |
                      {error, ErrorInfo, ErrorLocation :: erl_anno:location()},
                  ErrorInfo :: erl_scan:error_info() | erl_parse:error_info().

等效于 read(IoDevice, Prompt, StartLocation, [])

链接到此函数

read(IoDevice, Prompt, StartLocation, Options)

查看源代码 (自 OTP R16B 起)
-spec read(IoDevice, Prompt, StartLocation, Options) -> Result
              when
                  IoDevice :: device(),
                  Prompt :: prompt(),
                  StartLocation :: erl_anno:location(),
                  Options :: erl_scan:options(),
                  Result ::
                      {ok, Term :: term(), EndLocation :: erl_anno:location()} |
                      {eof, EndLocation :: erl_anno:location()} |
                      server_no_data() |
                      {error, ErrorInfo, ErrorLocation :: erl_anno:location()},
                  ErrorInfo :: erl_scan:error_info() | erl_parse:error_info().

IoDevice 读取一个项 Term,使用 Prompt 提示。

读取从位置 StartLocation 开始。参数 Options 作为函数 erl_scan:tokens/4 的参数 Options 传递。

该函数返回

  • {ok, Term, EndLocation} - 解析成功。

  • {eof, EndLocation} - 遇到文件结尾。

  • {error, ErrorInfo, ErrorLocation} - 解析失败。

  • {error, ErrorDescription} - 其他(罕见)错误情况,例如,如果从 NFS 文件系统读取,则为 {error, estale}

-spec rows() -> {ok, pos_integer()} | {error, enotsup}.

等效于 rows(standard_io)

-spec rows(IoDevice) -> {ok, pos_integer()} | {error, enotsup} when IoDevice :: device().

检索 IoDevice 的行数(即终端的高度)。

该函数仅对终端设备成功,对于所有其他 I/O 设备,该函数返回 {error, enotsup}

链接到此函数

scan_erl_exprs(Prompt)

查看源代码
-spec scan_erl_exprs(Prompt) -> Result
                        when Prompt :: prompt(), Result :: erl_scan:tokens_result() | server_no_data().

等效于 scan_erl_exprs(standard_io, Prompt)

链接到此函数

scan_erl_exprs(Device, Prompt)

查看源代码
-spec scan_erl_exprs(Device, Prompt) -> Result
                        when
                            Device :: device(),
                            Prompt :: prompt(),
                            Result :: erl_scan:tokens_result() | server_no_data().

等效于 scan_erl_exprs(Device, Prompt, 1)

链接到此函数

scan_erl_exprs(Device, Prompt, StartLocation)

查看源代码
-spec scan_erl_exprs(Device, Prompt, StartLocation) -> Result
                        when
                            Device :: device(),
                            Prompt :: prompt(),
                            StartLocation :: erl_anno:location(),
                            Result :: erl_scan:tokens_result() | server_no_data().

等效于 scan_erl_exprs(Device, Prompt, StartLocation, [])

链接到此函数

scan_erl_exprs(Device, Prompt, StartLocation, Options)

查看源代码 (自 OTP R16B 起)
-spec scan_erl_exprs(Device, Prompt, StartLocation, Options) -> Result
                        when
                            Device :: device(),
                            Prompt :: prompt(),
                            StartLocation :: erl_anno:location(),
                            Options :: erl_scan:options(),
                            Result :: erl_scan:tokens_result() | server_no_data().

IoDevice 读取数据,使用 Prompt 提示。

读取从位置 StartLocation 开始。参数 Options 作为函数 erl_scan:tokens/4 的参数 Options 传递。数据被标记化,就像它是一系列 Erlang 表达式一样,直到达到最后一个点 (.)。此标记也会返回。

该函数返回

  • {ok, Tokens, EndLocation} - 标记化成功。

  • {eof, EndLocation} - 标记器遇到文件结尾。

  • eof - I/O 服务器遇到文件结尾。

  • {error, ErrorInfo, ErrorLocation} - 标记化时发生错误。

  • {error, ErrorDescription} - 其他(罕见)错误情况,例如,如果从 NFS 文件系统读取,则为 {error, estale}

示例

23> io:scan_erl_exprs('enter>').
enter>abc(), "hey".
{ok,[{atom,1,abc},{'(',1},{')',1},{',',1},{string,1,"hey"},{dot,1}],2}
24> io:scan_erl_exprs('enter>').
enter>1.0er.
{error,{1,erl_scan,{illegal,float}},2}
-spec scan_erl_form(Prompt) -> Result
                       when Prompt :: prompt(), Result :: erl_scan:tokens_result() | server_no_data().

等效于 scan_erl_form(standard_io, Prompt)

链接到此函数

scan_erl_form(IoDevice, Prompt)

查看源代码
-spec scan_erl_form(IoDevice, Prompt) -> Result
                       when
                           IoDevice :: device(),
                           Prompt :: prompt(),
                           Result :: erl_scan:tokens_result() | server_no_data().

等效于 scan_erl_form(IoDevice, Prompt, 1)

链接到此函数

scan_erl_form(IoDevice, Prompt, StartLocation)

查看源代码
-spec scan_erl_form(IoDevice, Prompt, StartLocation) -> Result
                       when
                           IoDevice :: device(),
                           Prompt :: prompt(),
                           StartLocation :: erl_anno:location(),
                           Result :: erl_scan:tokens_result() | server_no_data().

等效于 scan_erl_form(IoDevice, Prompt, StartLocation, [])

链接到此函数

scan_erl_form(IoDevice, Prompt, StartLocation, Options)

查看源代码 (自 OTP R16B 起)
-spec scan_erl_form(IoDevice, Prompt, StartLocation, Options) -> Result
                       when
                           IoDevice :: device(),
                           Prompt :: prompt(),
                           StartLocation :: erl_anno:location(),
                           Options :: erl_scan:options(),
                           Result :: erl_scan:tokens_result() | server_no_data().

IoDevice 读取数据,使用 Prompt 提示。

从位置 StartLocation (1) 开始读取。参数 Options 作为函数 erl_scan:tokens/4 的参数 Options 传递。数据被标记化,就像它是一个 Erlang 形式(Erlang 源文件中有效的 Erlang 表达式之一),直到达到最后一个点 (.)。也会返回最后一个标记。

返回值与 scan_erl_exprs/4 的返回值相同。

-spec setopts(Opts) -> ok | {error, Reason} when Opts :: [setopt()], Reason :: term().

等效于 setopts(standard_io, Opts)

链接到此函数

setopts(IoDevice, Opts)

查看源代码
-spec setopts(IoDevice, Opts) -> ok | {error, Reason}
                 when IoDevice :: device(), Opts :: [setopt()], Reason :: term().

IoDevice 设置选项。可能的选项和值因 I/O 设备而异。

有关特定 I/O 设备上支持的选项及其当前值的列表,请使用函数 getopts/1

OTP I/O 设备支持的选项和值如下

  • binarylist{binary, boolean()} - 如果设置为二进制模式(binary{binary, true}),则 I/O 服务器会向 get_lineget_chars 和(如果可能)get_until 请求发送二进制数据(以 UTF-8 编码)作为答案(有关详细信息,请参阅用户指南中的“Erlang I/O 协议”部分)。直接效果是,get_chars/2,3get_line/1,2 为受影响的 I/O 设备返回 UTF-8 二进制文件,而不是字符列表。

    默认情况下,OTP 中的所有 I/O 设备都设置为 list 模式。但是,I/O 函数可以处理任何这些模式,因此其他用户编写的模块也应该像 I/O 服务器的客户端一样工作。

    此选项受 standard_io/0user/0file:io_server/0 I/O 服务器支持。

  • {echo, boolean()} - 表示终端是否回显输入。仅标准 shell I/O 服务器(group.erl)支持此选项。

  • {expand_fun, expand_fun()} - 提供一个类似于 Erlang shell 的 tab 补全(扩展)函数。当用户按下 Tab 键时,会调用此函数。当调用诸如 get_line/1,2 等行读取函数时,扩展功能处于激活状态。

    该函数被调用时,会将当前行(直到光标处)作为反转的字符串传入。它需要返回一个三元组:{yes|no, string(), list()}。如果第一个元素为 no,则发出蜂鸣声,否则扩展是静默的;第二个元素是一个将在光标位置输入的字符串;第三个元素是可能的扩展列表。如果此列表不为空,则会将其打印在当前输入行的下方。可能的扩展列表可以以不同的方式格式化,以便让更高级的扩展建议对用户来说更易读,请参阅 edlin_expand:expand/2 文档以了解更多信息。

    简单示例(除空行外,任何其他输入都会发出蜂鸣声,空行会被扩展为 "quit"

    fun("") -> {yes, "quit", []};
       (_) -> {no, "", ["quit"]} end

    此选项仅由标准 shell(group.erl)支持。

  • {log, none | output | input | all} - 告知 I/O 服务器应该记录 I/O 请求。请求将以 info 级别记录到 [otp, kernel, io, input | output | ctrl] 域,并带有以下报告

    #{ request := IoRequest, server := pid(), server_name => term() }.

    需要特别注意的是,应格外小心,以确保这些日志报告不会被记录到 standard_io/0,因为这可能导致系统进入无限循环。

    示例

    1> logger:set_primary_config(level, info).
    ok
    2> logger:add_handler(stdout, logger_std_h, #{ config => #{ file => "stdout.log" }}).
    ok
    3> io:setopts(user, [{log, output}]).
    ok
    4> io:format(user, "Hello~n", []).
    Hello
    ok
    5> file:read_file("stdout.log").
    {ok,<<"2024-11-14T09:53:49.275085+01:00 info: <0.89.0> wrote to user, Hello\n">>}

    并非所有 I/O 服务器都支持此选项。请使用 io:getopts/1 来检查它是否可用。

    注意

    Erlang/OTP 中的 I/O 服务器会将 logger 域设置为 [otp, kernel, io, input | output]。默认的 logger 处理程序不会打印此域,因此您需要启用它。这可以通过添加类似这样的新过滤器来完成

    logger:add_handler_filter(default, io_domain,
       {fun logger_filters:domain/2, {log,sub,[otp,kernel,io]}}).
  • {encoding, latin1 | unicode} - 指定字符从 I/O 设备输入或输出的方式,这意味着,例如,终端设置为处理 Unicode 输入和输出,或者文件设置为处理 UTF-8 数据编码。

    此选项影响从 I/O 函数返回数据的方式,也不影响在 I/O 协议中发送数据的方式,它仅影响 I/O 设备如何处理到“物理”设备的 Unicode 字符。

    系统启动时,标准 shell 设置为 unicodelatin1 编码。编码通过类 Unix 系统上的 LANGLC_CTYPE 环境变量或在其他系统上通过其他方式设置。因此,如果 I/O 设备支持,用户可以输入 Unicode 字符,并且 I/O 设备处于 {encoding, unicode} 模式。如果运行时系统的假设错误,可以通过设置此选项来更改模式。

    注意

    在 OTP 26.0 之前,当 Erlang 使用 -oldshell-noshell 标志启动时(例如,在 escript 中),standard_io 的默认编码设置为 latin1,这意味着任何大于代码点 255 的字符都会被转义,并且输入应为纯 8 位 ISO Latin-1。从 OTP 26.0 开始,如果 standard_io 支持 Unicode,则始终默认为 unicode,否则为 latin1

    如果您想在 standard_io 上发送原始字节,您现在始终需要显式地将编码设置为 latin1;否则,代码点 128-255 将被转换为 UTF-8。最好通过将内核配置参数 standard_io_encoding 设置为 latin1 来完成此操作。

    文件也可以设置为 {encoding, unicode},这意味着数据以 UTF-8 格式写入和读取。文件可以有更多的编码,请参阅下文。

    标准 shell(group.erl,包括 Windows 上的 werl)、“oldshell”(user.erl)和文件 I/O 服务器都支持 {encoding, unicode | latin1}

  • {encoding, utf8 | utf16 | utf32 | {utf16,big} | {utf16,little} | {utf32,big} | {utf32,little}} - 对于磁盘文件,编码可以设置为各种 UTF 变体。这将导致数据被期望以指定编码从文件中读取,并且数据以指定编码写入到磁盘文件。

    {encoding, utf8} 在文件上具有与 {encoding, unicode} 相同的效果。

    扩展编码仅在磁盘文件(通过函数 file:open/2 打开的文件)上受支持。

-spec write(Term) -> ok when Term :: term().

等效于 write(standard_io, Term)

-spec write(IoDevice, Term) -> ok when IoDevice :: device(), Term :: term().

将项 Term 写入 IoDevice