gpt4 book ai didi

elixir - 为什么文件读取会因 STDIO 或 File.open 而异?

转载 作者:行者123 更新时间:2023-12-03 12:17:14 26 4
gpt4 key购买 nike

问题

根据我是否从 :stdio 拉取文件,读取文件的行为似乎有所不同。或打开文件。为什么?我希望能够从 STDIN 或通过打开文件 ( File.open ) 读取二进制文件并使用相同的代码来提取字节。

简而言之:

  • 为什么我在下面概述的行为在 stdio 和
    文件?
  • 我怎样才能实现我的目标?

  • 测试用例

    作为一个简单的测试用例,我有一个包含三个字节的二进制文件:
    06 8C 7D

    我想要的结果是,从任一来源读取此文件都应生成以下形式的二进制文件:
    <<6, 140, 125>>

    但是,根据我是从 STDIO 读取还是打开文件,情况似乎有所不同。

    以下是展示该行为的一系列测试用例。

    示例 1

    stdio 的 IO.binread 产生此错误
    IO.inspect IO.binread(:stdio, 3)
    $ elixir repro.exs < repro.bin
    {:error, :collect_chars}

    示例 2

    stdio 的 IO.read 产生所需的结果
    IO.inspect IO.read(:stdio, 3)
    $ elixir repro.exs < repro.bin
    <<6, 140, 125>>

    示例 3

    文件的 IO.binread 产生所需的结果
    {:ok, file} = File.open("repro.bin")
    IO.inspect IO.binread(file, 3)
    $ elixir repro.exs
    <<6, 140, 125>>

    示例 4

    文件的 IO.read 添加了一个额外的字节(194),我不明白 - 我最好的猜测是这与 utf8 有关吗?
    {:ok, file} = File.open("repro.bin")
    IO.inspect IO.read(file, 3)
    $ elixir repro.exs
    <<6, 194, 140, 125>>

    我想要什么:

    一种接受文件或标准输入输出并处理的方法
    任一设备相同。现在看来,我做不到。尽管我最好的谷歌搜索,我发现自己卡住了。

    有什么见解吗?

    最佳答案

    José Valim 在 elixir google 小组中的回答:

    The answer to your question is in which encoding the source is. STDIO is by default in unicode, which means it is not suitable for binread. This is documented in the binread function and is currently an Erlang bug/limitation. To find out the encoding, use getopts:

    iex> :io.getopts :standard_io
    [expand_fun: &IEx.Autocomplete.expand/1, echo: true, binary: true,
    encoding: :unicode]

    On the other hand, File is in latin, which means read will attempt to convert and binread will return the raw bytes. You can try to use :io.setopts and see if you get the desired result:

    iex> io.setopts :standard_io, encoding: :latin1

    I am aware the situation is not ideal. It would be nice if binread could always read bytes regardless of the encoding of the file. I have written a report here: http://erlang.org/pipermail/erlang-bugs/2014-July/004498.html

    To sum up:

    • read will always attempt to do a conversion to the device encoding
    • binread should always return raw binaries but there is a bug when it comes to unicode (which is the default for IO devices)


    我看到的额外字节(194)的奇怪“注入(inject)”似乎是elixir/erlang试图将bin解释为utf8。

    根据他的建议,直接设置 stdio 的编码似乎可以解决问题:

    test_read = fn(device) ->
    IO.binread(device, 3)
    end

    #set stdio's encoding to latin1
    :io.setopts(:standard_io, encoding: :latin1)

    # Test the read against stdio
    IO.inspect test_read.(:stdio)

    #grab a file descriptor
    {:ok, fd} = File.open("repro.bin")

    # Test the same read against a file
    IO.inspect test_read.(fd)

    输出:
    $ elixir repro.exs < repro.bin
    <<6, 140, 125>>
    <<6, 140, 125>>

    关于elixir - 为什么文件读取会因 STDIO 或 File.open 而异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34458855/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com