如何在Erlang中读取标准输入(STDIN)的全部数据?
在Erlang中读取全部STDIN并解析JSON
要一次性读取管道传入的全部STDIN数据,核心思路是循环读取输入直到遇到EOF,累加所有数据后再进行JSON解析。以下是具体实现方案:
核心读取函数
通过循环调用file:read/2读取标准输入(standard_io)的块数据,直到返回eof,最终拼接出完整的输入二进制:
read_all_stdin() -> read_all_stdin(<<>>). read_all_stdin(Accumulator) -> case file:read(standard_io, 4096) of {ok, Data} -> read_all_stdin(<<Accumulator/binary, Data/binary>>); eof -> Accumulator; {error, Reason} -> error({stdin_read_error, Reason}) end.
- 选择4096字节作为每次读取的块大小是权衡性能和内存使用的常见做法,可根据实际场景调整。
- 使用二进制累加是因为JSON数据通常以UTF-8编码存储,二进制处理既高效又能避免字符编码转换问题。
结合JSON解析的完整示例
以常用的jsx库为例,实现读取全部STDIN并解析JSON的逻辑:
-module(stdin_json_parser). -export([main/0]). main() -> try StdinData = read_all_stdin(), ParsedJson = jsx:decode(StdinData, [return_maps]), % 此处添加你的JSON处理逻辑 io:format("Successfully parsed JSON: ~p~n", [ParsedJson]) catch error:{stdin_read_error, Reason} -> io:format("Failed to read STDIN: ~p~n", [Reason]), halt(1); {error, {json_decode_error, Details}} -> io:format("Failed to parse JSON: ~p~n", [Details]), halt(1) end. read_all_stdin() -> read_all_stdin(<<>>). read_all_stdin(Accumulator) -> case file:read(standard_io, 4096) of {ok, Data} -> read_all_stdin(<<Accumulator/binary, Data/binary>>); eof -> Accumulator; {error, Reason} -> error({stdin_read_error, Reason}) end.
编译与运行
- 确保项目依赖
jsx(可通过rebar3管理,在rebar.config中添加{deps, [{jsx, "~> 3.0"}]}) - 编译代码:
erlc stdin_json_parser.erl - 通过管道传入数据运行:
echo '{"name": "Erlang", "version": "26.0"}' | erl -noshell -s stdin_json_parser main -s init stop
Escript便捷版本
如果需要更易用的可执行文件,可以写成escript格式:
#!/usr/bin/env escript %% -*- erlang -*- %%! -noshell -noinput main(_Args) -> try StdinData = read_all_stdin(<<>>), case jsx:decode(StdinData, [return_maps]) of {error, Err} -> io:format("JSON parse error: ~p~n", [Err]), halt(1); Json -> io:format("Parsed result: ~p~n", [Json]) end catch error:{read_error, Reason} -> io:format("STDIN read error: ~p~n", [Reason]), halt(1) end. read_all_stdin(Acc) -> case file:read(standard_io, 4096) of {ok, Data} -> read_all_stdin(<<Acc/binary, Data/binary>>); eof -> Acc; {error, R} -> error({read_error, R}) end.
赋予执行权限后即可直接运行:
chmod +x json_parser.escript cat sample.json | ./json_parser.escript
内容的提问来源于stack exchange,提问作者Sam Weaver
相关产品推荐
相关产品推荐

