使用 BufferedInputStream 读取大文件时 Java 文件 IO 被截断

Posted

技术标签:

【中文标题】使用 BufferedInputStream 读取大文件时 Java 文件 IO 被截断【英文标题】:Java file IO truncated while reading large files using BufferedInputStream 【发布时间】:2013-05-01 01:31:24 【问题描述】:

我有一个函数,其中我只得到一个 BufferedInputStream 而没有关于要读取的文件的其他信息。不幸的是,我无法更改方法定义,因为它是由我无权访问的代码调用的。我一直在使用下面的代码来读取文件并将其内容放在一个字符串中:

public String[] doImport(BufferedInputStream stream) throws IOException, PersistenceException 
    int bytesAvail = stream.available();
    byte[] bytesRead = new byte[bytesAvail];
    stream.read(bytesRead);
    stream.close();
    String fileContents = new String(bytesRead);
    //more code here working with fileContents

我的问题是,对于大文件 (>2Gb),此代码会导致程序运行速度极慢或截断数据,具体取决于执行程序的计算机。有人对在这种情况下如何处理大文件有建议吗?

【问题讨论】:

【参考方案1】:

您假设available() 返回文件的大小;它不是。它返回可供读取的字节数,可以是小于或等于文件大小的任何数字。

不幸的是,如果没有关于文件数据长度的其他信息来源(即通过调用java.io.File.length()),就无法一次性完成您想要的操作。相反,您可能必须从多次读取中累积。一种方法是使用ByteArrayOutputStream。读入一个固定的、有限大小的数组,然后将读入的数据写入ByteArrayOutputStream。最后,拉出字节数组。您需要使用read()write() 的三参数形式,并查看read() 的返回值,以便准确了解每次调用时将多少字节读入缓冲区。

【讨论】:

【参考方案2】:

我不知道你为什么不认为你可以逐行阅读。 BufferedInputStream 仅描述了如何访问底层流,它不会对您最终从中读取数据的方式施加任何限制。您可以像使用其他任何InputStream 一样使用它。

也就是说,你可以逐行阅读它

InputStreamReader streamReader = new InputStreamReader(stream);
BufferedInputReader lineReader = new BufferedInputReader(streamReader);
String line = lineReader.readLine();
...

[编辑]此回复是对问题的原始措辞,该措辞专门要求一种逐行读取输入文件的方法。

【讨论】:

“不知道你为什么这么想”每个文件都有行。他们没有。也很难理解为什么您认为每个文件都有字符。他们没有。并且从可能有也可能没有一个或多个文件的文件中读取一行并不能解决实际问题。 -1. 原问题已修改。最初,发布者表示他们更愿意逐行读取文件,因此我假设输入是带有换行符的字符流。 ***.com/posts/16311485/revisions

以上是关于使用 BufferedInputStream 读取大文件时 Java 文件 IO 被截断的主要内容,如果未能解决你的问题,请参考以下文章

bufferedinputstream的使用

为啥使用 BufferedInputStream 逐字节读取文件比使用 FileInputStream 快?

使用 BufferedInputStream 读取大文件时 Java 文件 IO 被截断

BufferedInputStream读取流正常,但是BufferedInputStream转化为BufferedReader后 就读取不到数据了?求解

如何从 BufferedInputStream 中读取 id3 标签?

java 比较InputStream,BufferedInputStream,RandomAccessFile,FileChannel的读取速度。