【问题标题】:Reading Strings and Binary from the same FileInputStream从同一个 FileInputStream 中读取字符串和二进制文件
【发布时间】:2010-10-08 18:59:09
【问题描述】:

我有一个文件,开头包含一定数量的纯文本,结尾是二进制内容。二进制内容的大小由我阅读的一些纯文本行决定。

我使用BufferedReader 来读取各个行,但是它没有公开任何方法来引用读取字节数组。 readUTF 的 DataInputStream 不会一直读到行尾,readLine 方法已被弃用。

使用底层FileInputStream 读取返回空字节数组。有什么建议可以解决这个问题吗?


private DOTDataInfo parseFile(InputStream stream) throws IOException{
DOTDataInfo info = new DOTDataInfo();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
int binSize = 0;
String line;
while((line = reader.readLine()) != null){
    if(line.length() == 0)
        break;
    DOTProperty prop = parseProperty(line);
    info.getProperties().add(prop);
    if(prop.getName().equals("ContentSize"))
        binSize = Integer.parseInt(prop.getValue());
}
byte[] content = new byte[binSize];
stream.read(content); //Its all empty now. If I use a DataInputStream instead, its got the values from the file
return info;
}

【问题讨论】:

  • 也许发布给你空数组的代码?它不应该那样做......
  • 我认为问题在于 bufferedReader 也会读取二进制数据,因为它会缓冲数据。这意味着没有任何内容可以从 InputStream 中读取 - 因此是空字节数组结果。

标签: java io stream


【解决方案1】:

正确的方法是使用某种形式的 InputStream,可能是 FileInputStream,除非这会成为性能障碍。

“使用底层 FileInputStream 读取返回空字节数组”是什么意思?这似乎不太可能,并且可能是您的错误所在。您能向我们展示您尝试过的示例代码吗?

【讨论】:

    【解决方案2】:

    您需要使用 InputStream。阅读器用于字符数据。研究用 DataInputStream 包装您的输入流,例如:

    stream=new DataInputStream(new BufferedInputStream(new FileInputStream(...)));
    

    数据输入流将为您提供许多有用的方法来读取各种类型的数据,当然还有用于读取字节的基本 InputStream 方法。

    (这实际上正是 HTTP 服务器在读取带有内容的请求时必须执行的操作。)


    readUTF 不读取一行,它读取以(修改的)UTF8 格式编写的字符串 - 请参阅 JavaDoc。

    【讨论】:

      【解决方案3】:

      您可以使用 BufferedReader 阅读文本。当您知道二进制文件从哪里开始时,您可以关闭文件并使用 RandomAccessFile 打开它并从文件中的任何位置读取二进制文件。 或者您可以将文件读取为二进制文件并将您识别为文本的部分转换为文本。 {使用新字符串(字节,编码)}

      【讨论】:

        【解决方案4】:

        您可以使用RandomAccessFile。使用readLine() 读取开头的纯文本(注意这里的限制,如API 中所述),然后使用readByte() 或readFully() 读取后续二进制数据。

        使用底层FileInputStream 读取返回空字节数组。

        这是因为您已将流包装在 BufferedReader 中,这可能在填充其缓冲区时消耗了流中的所有字节。

        【讨论】:

          【解决方案5】:

          我建议使用DataInputStream。您有以下选择:

          • 使用 DataInputStream 读取文本和二进制内容
          • 打开 BufferedReader,读取文本并关闭流。然后打开一个DataInputStream,跳过文本大小的字节,读取二进制数据。

          【讨论】:

            【解决方案6】:

            如果您确实有一个文件(而不是更难查找的文件,例如网络流),那么我建议您这样做:

            • 将文件作为 FileInputStream 打开
            • 将其包装在 InputStreamReader 和 BufferedReader 中
            • 阅读正文,了解内容有多少
            • 关闭 BufferedReader(这将关闭 InputStreamReader,这将关闭 FileInputStream)
            • 重新打开文件
            • 跳至(文件总长度 - 二进制内容长度)
            • 正常读取其余数据

            如果您想避免重新打开文件,您可以在 FileInputStream 的开头调用mark(),然后调用reset() 和skip() 以到达正确的位置。 (我一直在寻找 InputStream.seek() 但我看不到 - 我不记得以前在 Java 中想要它,但它真的没有吗?哎呀。)

            【讨论】:

            • 好吧,我想这似乎是正确的选择。但是出于好奇,如果它是一个很难找到的流,人们会怎么做呢?对于我认为可能有一个直观(但难以捉摸!)的解决方案,这似乎需要付出很多努力。
            • 嗯,棘手的一点是读取字符数据而不“过度读取”二进制数据。您可以通过从 InputStreamReader 一次读取一个字符来做到这一点——我没有检查它是否缓冲——但这将是低效的。 (您可以将流包装在 [cont]
            • 一个 BufferedInputStream 来避免每次调用都进入操作系统/磁盘,诚然。)基本上混合格式的文件总是有点痛苦。如果格式在每次有文本时都包含一个长度前缀,那还不错:“接下来的 n 个字节是文本”,这样你就知道在哪里停止了。
            • 很好的信息,但我认为不能回答这个问题。这个问题是指一些输入流。它可能无法重新读取,就像在网络流上传递的文件一样。那么如何在不设置文本长度的情况下读取部分文本和部分二进制呢?
            • @AlikElzin-kilaka:问题明确指的是FileInputStream - 并且OP接受了这个答案。所以我认为它确实回答了这个问题。现在,如果您遇到不同的情况,这将变得更加困难,这将取决于编码、文本的结束方式等。我建议您提出一个新问题。
            【解决方案7】:

            唉,DataInputStream 已被弃用并且不处理 UTF。但这应该会有所帮助(它从二进制流中读取一行,没有任何前瞻)。

            public static String lineFrom(InputStream in) throws IOException {
                byte[] buf = new byte[128];
                int pos = 0;
                for (;;) {
                    int ch = in.read();
                    if (ch == '\n' || ch < 0) break;
                    buf[pos++] = (byte) ch;
                    if (pos == buf.length) buf = Arrays.copyOf(buf, pos + 128);
                }
                return new String(Arrays.copyOf(buf, pos), "UTF-8");
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-07-21
              • 2014-06-18
              • 2012-09-05
              • 2012-09-02
              • 2020-10-30
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多