从同一个FileInputStream中读取字符串和二进制文件

我有一个文件,在开始时包含一些纯文本,最后是二进制内容。 二进制内容的大小由我读过的一条纯文本行确定。

我使用BufferedReader来读取各行,但它没有公开任何方法来引用读取字节数组。 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; } 

如果你真的有一个文件(而不是更难以寻找的东西,例如网络流),那么我建议这样的事情:

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

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

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

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

那是因为你已经将流包装在BufferedReaderBufferedReader在填充缓冲区时可能已经消耗了流中的所有字节。

您需要使用InputStream。 读者是为了角色数据。 查看使用DataInputStream包装输入流,如:

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

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

(这实际上是HTTP服务器必须执行的内容读取请求。)


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

唉, 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"); } 

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

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

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

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

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