io — stdlib v6.2.2 (original) (raw)

Standard I/O server interface functions.

This module provides an interface to standard Erlang I/O servers. The output functions all return ok if they are successful, or exit if they are not.

All functions in this module have an optional parameterIoDevice. If included, it must be the pid of a process that handles the I/O protocols. Normally, it is an IoDevice returned byfile:open/2. If no IoDevice is given,standard_io is used.

For a description of the I/O protocols, see sectionThe Erlang I/O Protocol in the User's Guide.

Warning

The data supplied to function put_chars/2 is to be in the unicode:chardata/0 format. This means that programs supplying binaries to this function must convert them to UTF-8 before trying to output the data on an I/O device.

If an I/O device is set in binary mode, functionsget_chars/2,3 and get_line/1,2 can return binaries instead of lists. The binaries are encoded in UTF-8.

To work with binaries in ISO Latin-1 encoding, use the file module instead.

For conversion functions between character encodings, see the unicodemodule.

Error Information

The ErrorInfo mentioned in this module is the standard ErrorInfo structure that is returned from all I/O modules. It has the following format:

{ErrorLocation, Module, ErrorDescriptor}

A string that describes the error is obtained with the following call:

Module:format_error(ErrorDescriptor)

Summary

Types

An I/O device, either standard_io/0, standard_error/0, user/0, a file:io_server/0, a registered name, or any pid handling I/O protocols.

What the I/O server sends when there is no data.

The I/O device standard_error can be used to direct output to whatever the current operating system considers a suitable I/O device for error output. This can be useful when standard output is redirected.

The default standard I/O device assigned to a process. This device is used when no IoDevice argument is specified in the function calls in this module.

An I/O device that can be used to interact with the node local stdout andstdin. This can be either a terminal, a pipe, a file, or a combination.

Functions

Equivalent to columns(standard_io).

Retrieves the number of columns of the IoDevice (that is, the width of a terminal).

Equivalent to format(Format, []).

Equivalent to fwrite(IoDevice, Format, Data).

Reads characters from IoDevice, prompting it with Prompt. Interprets the characters in accordance with Format.

Equivalent to fwrite(Format, []).

Writes the items in Data on the IoDevice in accordance with Format.

Reads Count characters from IoDevice, prompting it with Prompt.

Equivalent to get_line(standard_io, Prompt).

Reads a line from IoDevice, prompting it with Prompt.

Equivalent to getopts(standard_io).

Requests all available options and their current values for a IoDevice.

Equivalent to nl(standard_io).

Writes new line to the standard output (IoDevice).

Reads data from IoDevice, prompting it with Prompt.

Reads data from IoDevice, prompting it with Prompt.

Returns the user-requested range of printable Unicode characters.

Writes the characters of CharData to the IoDevice.

Equivalent to read(standard_io, Prompt).

Reads a term Term from the standard input (IoDevice), prompting it withPrompt.

Reads a term Term from IoDevice, prompting it with Prompt.

Equivalent to rows(standard_io).

Retrieves the number of rows of IoDevice (that is, the height of a terminal).

Reads data from IoDevice, prompting it with Prompt.

Reads data from IoDevice, prompting it with Prompt.

Equivalent to setopts(standard_io, Opts).

Set options for IoDevice. Possible options and values vary depending on the I/O device.

Equivalent to write(standard_io, Term).

Writes term Term to IoDevice.

Types

An I/O device, either standard_io/0, standard_error/0, user/0, a file:io_server/0, a registered name, or any pid handling I/O protocols.

-type encoding() :: latin1 | unicode | utf8 | utf16 | utf32 | {utf16, big | little} | {utf32, big | little}.

-type getopt() :: {terminal | stdin | stdout | stderr, boolean()} | option().

-type server_no_data() :: {error, ErrorDescription :: term()} | eof.

What the I/O server sends when there is no data.

-type setopt() :: binary | list | option().

-type standard_error() :: standard_error.

The I/O device standard_error can be used to direct output to whatever the current operating system considers a suitable I/O device for error output. This can be useful when standard output is redirected.

Example on a Unix-like operating system:

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

-type standard_io() :: standard_io.

The default standard I/O device assigned to a process. This device is used when no IoDevice argument is specified in the function calls in this module.

It is sometimes desirable to use an explicit IoDevice argument that refers to the default I/O device. This is the case with functions that can access either a file or the default I/O device. The atom standard_io has this special meaning. The following example illustrates this:

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

By default all I/O sent to standard_io will end up in the userI/O device of the node that spawned the calling process.

standard_io is an alias for group_leader/0, so in order to change where the default input/output requests are sent you can change the group leader of the current process usinggroup_leader(NewGroupLeader, self()).

An I/O device that can be used to interact with the node local stdout andstdin. This can be either a terminal, a pipe, a file, or a combination.

Use getopts/1 to get more information about the I/O device.

See The Interactive Shell andEscripts and non-interactive I/Oin the Using Unicode In Erlang User's Guide for details on how Unicode is handled by user.

Functions

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

Equivalent to columns(standard_io).

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

Retrieves the number of columns of the IoDevice (that is, the width of a terminal).

The function succeeds for terminal devices and returns {error, enotsup} for all other I/O devices.

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

Equivalent to format(Format, []).

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

Equivalent to format(standard_io, Format, Data).

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

Equivalent to fwrite(IoDevice, Format, Data).

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

Equivalent to fread(standard_io, 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().

Reads characters from IoDevice, prompting it with Prompt. Interprets the characters in accordance with Format.

Format can contain the following:

Examples:

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().

Equivalent to fwrite(Format, []).

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

Equivalent to fwrite(standard_io, Format, Data).

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

Writes the items in Data on the IoDevice in accordance with Format.

Format contains plain characters that are copied to the output device, and control sequences for formatting, see below. If Formatis an atom or a binary, it is first converted to a list with the aid ofatom_to_list/1 orbinary_to_list/1. Example:

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

The general format of a control sequence is ~F.P.PadModC.

The character C determines the type of control sequence to be used. It is the only required field. All of F, P, Pad, and Mod are optional. For example, to use a # for Pad but use the default values for F and P, you can write ~..#C.

If F, P, or Pad is a * character, the next argument in Data is used as the value. For example:

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

To use a literal * character as Pad, it must be passed as an argument:

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

Available control sequences:

1> io:fwrite("|~10.5c|~-10.5c|~5c|~n", [$a, <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>b</mi><mo separator="true">,</mo></mrow><annotation encoding="application/x-tex">b, </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">b</span><span class="mpunct">,</span></span></span></span>c]).  
|     aaaaa|bbbbb     |ccccc|  
ok  

If the Unicode translation modifier (t) is in effect, the integer argument can be any number representing a valid Unicode codepoint, otherwise it is to be an integer less than or equal to 255, otherwise it is masked with 16#FF:

2> io:fwrite("~tc~n",[1024]).  
\x{400}  
ok  
3> io:fwrite("~c~n",[1024]).  
^@  
ok  
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  

A list with integers > 255 is considered an error if the Unicode translation modifier is not specified:

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]])  
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  

The field width specifies the maximum line length. It defaults to 80. The precision specifies the initial indentation of the term. It defaults to the number of characters printed on this line in the same call to write/1 orformat/1,2,3. For example, using T above:

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  

As from Erlang/OTP 21.0, a field width of value 0 can be used for specifying that a line is infinitely long, which means that no line breaks are inserted. For example:

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  

When the modifier l is specified, no detection of printable character lists takes place, for example:

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  

The Unicode translation modifier t specifies how to treat characters outside the Latin-1 range of codepoints, in atoms, strings, and binaries. For example, printing an atom containing a character > 255:

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

By default, Erlang only detects lists of characters in the Latin-1 range as strings, but the +pc unicode flag can be used to change this (seeprintable_range/0 for details). For example:

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

but if Erlang was started with +pc unicode:

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

Similarly, binaries that look like UTF-8 encoded strings are output with the binary string syntax if the t modifier is specified:

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  
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  

If the maximum depth is reached, it cannot be read in the resultant output. Also, the ,... form in a tuple denotes that there are more elements in the tuple but these are below the print depth.

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  
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  
1> io:fwrite("~X~n", [31,"10#"]).  
10#31  
ok  
2> io:fwrite("~.16X~n", [-31,"0x"]).  
-0x1F  
ok  
1> io:fwrite("~.10#~n", [31]).  
10#31  
ok  
2> io:fwrite("~.16#~n", [-31]).  
-16#1F  
ok  

The function returns:

If an error occurs, there is no output. Example:

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")

In this example, an attempt was made to output the single character 65 with the aid of the string formatting directive "~s".

Equivalent to get_chars(standard_io, Prompt, Count).

Reads Count characters from IoDevice, prompting it with Prompt.

The function returns:

Equivalent to get_line(standard_io, Prompt).

Reads a line from IoDevice, prompting it with Prompt.

The function returns:

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

Equivalent to getopts(standard_io).

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

Requests all available options and their current values for a IoDevice.

For example:

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

Here the file I/O server returns all available options for a file, which are the expected ones, encoding and binary. However, the standard shell has some more options:

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

This example is, as can be seen, run in an environment where the terminal supports Unicode input and output.

The stdin, stdout and stderr options are read only and indicates whether the stream is a terminal or not. When it is a terminal, most systems that Erlang runs on allows the use of ANSI escape codesto control what the terminal inputs or outputs.

terminal is an alias for stdout.

See setopts/1 for a description of the other options.

Equivalent to nl(standard_io).

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

Writes new line to the standard output (IoDevice).

-spec parse_erl_exprs(Prompt) -> Result when Prompt :: prompt(), Result :: parse_ret().

Equivalent to parse_erl_exprs(standard_io, Prompt).

-spec parse_erl_exprs(IoDevice, Prompt) -> Result when IoDevice :: device(), Prompt :: prompt(), Result :: parse_ret().

Equivalent to parse_erl_exprs(IoDevice, Prompt, 1).

-spec parse_erl_exprs(IoDevice, Prompt, StartLocation) -> Result when IoDevice :: device(), Prompt :: prompt(), StartLocation :: erl_anno:location(), Result :: parse_ret().

Equivalent to parse_erl_exprs(IoDevice, Prompt, StartLocation, []).

-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().

Reads data from IoDevice, prompting it with Prompt.

Starts reading at location StartLocation. Argument Options is passed on as argument Options of function erl_scan:tokens/4. The data is tokenized and parsed as if it was a sequence of Erlang expressions until a final dot (.) is reached.

The function returns:

Example:

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}

-spec parse_erl_form(Prompt) -> Result when Prompt :: prompt(), Result :: parse_form_ret().

Equivalent to parse_erl_form(standard_io, Prompt).

-spec parse_erl_form(IoDevice, Prompt) -> Result when IoDevice :: device(), Prompt :: prompt(), Result :: parse_form_ret().

Equivalent to parse_erl_form(IoDevice, Prompt, 1).

-spec parse_erl_form(IoDevice, Prompt, StartLocation) -> Result when IoDevice :: device(), Prompt :: prompt(), StartLocation :: erl_anno:location(), Result :: parse_form_ret().

Equivalent to parse_erl_form(IoDevice, Prompt, StartLocation, []).

-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().

Reads data from IoDevice, prompting it with Prompt.

Starts reading at location StartLocation. Argument Options is passed on as argument Options of function erl_scan:tokens/4. The data is tokenized and parsed as if it was an Erlang form (one of the valid Erlang expressions in an Erlang source file) until a final dot (.) is reached.

The function returns:

-spec printable_range() -> unicode | latin1.

Returns the user-requested range of printable Unicode characters.

The user can request a range of characters that are to be considered printable in heuristic detection of strings by the shell and by the formatting functions. This is done by supplying +pc <range> when starting Erlang.

The only valid values for <range> are latin1 and unicode. latin1 means that only code points < 256 (except control characters, and so on) are considered printable. unicode means that all printable characters in all Unicode character ranges are considered printable by the I/O functions.

By default, Erlang is started so that only the latin1 range of characters indicate that a list of integers is a string.

The simplest way to use the setting is to call io_lib:printable_list/1, which uses the return value of this function to decide if a list is a string of printable characters.

Note

In a future release, this function may return more values and ranges. To avoid compatibility problems, it is recommended to use functionio_lib:printable_list/1.

Equivalent to put_chars(standard_io, CharData).

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

Writes the characters of CharData to the IoDevice.

If you want to write latin1 encoded bytes to the IoDevice you should usefile:write/2 instead.

Equivalent to read(standard_io, Prompt).

Reads a term Term from the standard input (IoDevice), prompting it withPrompt.

The function returns:

-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().

Equivalent to read(IoDevice, Prompt, StartLocation, []).

-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().

Reads a term Term from IoDevice, prompting it with Prompt.

Reading starts at location StartLocation. Argument Options is passed on as argument Options of function erl_scan:tokens/4.

The function returns:

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

Equivalent to rows(standard_io).

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

Retrieves the number of rows of IoDevice (that is, the height of a terminal).

The function only succeeds for terminal devices, for all other I/O devices the function returns {error, enotsup}.

Equivalent to scan_erl_exprs(standard_io, Prompt).

Equivalent to scan_erl_exprs(Device, Prompt, 1).

Equivalent to scan_erl_exprs(Device, Prompt, StartLocation, []).

Reads data from IoDevice, prompting it with Prompt.

Reading starts at location StartLocation. Argument Options is passed on as argument Options of function erl_scan:tokens/4. The data is tokenized as if it were a sequence of Erlang expressions until a final dot (.) is reached. This token is also returned.

The function returns:

Example:

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}

Equivalent to scan_erl_form(standard_io, Prompt).

-spec scan_erl_form(IoDevice, Prompt) -> Result when IoDevice :: device(), Prompt :: prompt(), Result :: erl_scan:tokens_result() | server_no_data().

Equivalent to scan_erl_form(IoDevice, Prompt, 1).

Equivalent to scan_erl_form(IoDevice, Prompt, StartLocation, []).

Reads data from IoDevice, prompting it with Prompt.

Starts reading at location StartLocation (1). Argument Options is passed on as argument Options of function erl_scan:tokens/4. The data is tokenized as if it was an Erlang form (one of the valid Erlang expressions in an Erlang source file) until a final dot (.) is reached. This last token is also returned.

The return values are the same as for scan_erl_exprs/4.

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

Equivalent to setopts(standard_io, Opts).

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

Set options for IoDevice. Possible options and values vary depending on the I/O device.

For a list of supported options and their current values on a specific I/O device, use function getopts/1.

The options and values supported by the OTP I/O devices are as follows:

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

This option is only supported by the standard shell (group.erl).

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

It is important to note that extra care should be taken so that these log reports are not logged to standard_io/0 as that may cause the system to enter an infinite loop.
Example:

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">>}  

Not all I/O servers support this option. Use io:getopts/1 to check if it is available.

Note

The I/O servers in Erlang/OTP will set the logger domainto [otp, kernel, io, input | output]. The default logger handler will not print this domain, so you need to enable it. This can be done by adding a new filter like this:

logger:add_handler_filter(default, io_domain,  
   {fun logger_filters:domain/2, {log,sub,[otp,kernel,io]}}).  

Note

Prior to OTP 26.0, when Erlang was started with the -oldshell or-noshell flags (for example, in an escript), the default encoding forstandard_io was set to latin1, meaning that any characters > codepoint 255 were escaped and that input was expected to be plain 8-bit ISO Latin-1. As of OTP 26.0, standard_ioalways defaults to unicode if its supported, otherwise latin1.
If you want to send raw bytes on standard_io, you now always need to explicitly set the encoding to latin1; otherwise, code points 128-255 will be converted to UTF-8. This is best done by setting the kernel configuration parameterstandard_io_encoding tolatin1.
Files can also be set in {encoding, unicode}, meaning that data is written and read as UTF-8. More encodings are possible for files, see below.
{encoding, unicode | latin1} is supported by both the standard shell (group.erl including werl on Windows), the 'oldshell' (user.erl), and the file I/O servers.

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

Equivalent to write(standard_io, Term).

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

Writes term Term to IoDevice.