使用 FileInputStream 和 FileOutputStream 读取和写入同一文件

Reading and writing into the same file with FileInputStream and FileOutputStream

提问人:Jee 提问时间:4/11/2022 最后编辑:Alexander IvanchenkoJee 更新时间:4/13/2022 访问量:1577

问:

我的代码的问题是读取和写入的无限循环

我找不到这个问题的解决方案或概念。

FileInputStream in = new FileInputStream("toto.txt");
FileOutputStream out = new FileOutputStream("toto.txt",false);

int m;
while ((m = in.read()) != 0) {
    System.out.print(m);
    out.write(m);
}
        
in.close();
out.close();
Java EOF java-IO 输入 文件输出流

评论

0赞 user207421 4/12/2022
问题是返回 -1 和流的结尾,而不是零。使用二进制数据,您的循环可以随时终止:对于文本数据,它永远不会终止,因为不应有空字符。但是,无论如何,读取和写入相同的文件将永远无法正常工作。在 Windows 上,您将无法打开 .read()FileOutputStream

答:

-1赞 Vamsi 4/11/2022 #1

它进入无限循环,因为读取将看到过去写入的结果。

无法使用 FileInputStream 和 FileOutputStream 读取和写入同一文件。如果要读取/写入同一文件,请使用 RandomAccessFile。如果要在文件中的特定位置写入,也可以指定位置。

如果要写入文件末尾,然后读取文件上的所有行,则此处为该示例:

RandomAccessFile file = new RandomAccessFile("toto.txt", "rw");
file.seek(file.length());
file.writeBytes("This is a temp file");
file.seek(0); //sets the pointer to the first byte
String line;
while((line = file.readLine()) != null) {
    System.out.println(line);
}

评论

0赞 user207421 4/12/2022
这不会读取文件中的所有行。它不会读取任何内容,因为文件已经位于其末尾。
0赞 user207421 4/12/2022
但毕竟,这仍然不是OP想要做的事情。
1赞 DogEgg 4/11/2022 #2

将循环条件更改为以下内容:

while ((m = in.read()) != -1)

评论

0赞 user207421 4/12/2022
正确,但您应该提供解释。
0赞 DogEgg 4/12/2022
好的,你可以看到 FileInputStream#read() 的 JavaDoc。从此输入流中读取一个字节的数据。如果尚无可用的输入,则此方法会阻止。返回:数据的下一个字节,如果到达文件末尾,则返回 -1。
0赞 Alexander Ivanchenko 4/13/2022 #3

我的代码在无限循环的读取和写入中存在问题。我 找不到此问题的解决方案或概念。

代码存在许多问题:

  • 在实例化后,该文件将被视为空文件,因为您已将 flag 设置为 。End 方法将始终返回,因为没有要读取的内容。FileOutputStreamappendfalseread()-1

  • 条件不正确,方法和方法,仅因为该控件进入循环,EOF () 被重复写入文件。如果将条件固定为 ,则循环将被忽略,因为文件从一开始就为空。read()-1(m = in.read()) != -1

  • 如果你两者都做:修复条件并将标志更改为,那么你会得到另一种无限循环的味道。文件的所有内容都将被成功读取并重复追加到文件中。appendtrue

因此,在任何情况下,同时读取和写入同一文件都不是一个好主意。

关于异常处理的一个重要说明。

因为你的代码片段中没有块,我假设你已经在 main() 中添加了一个 - 这不是一个好主意。代码中的方法只有在成功执行时才会被调用,但如果发生异常,资源将永远不会被释放。catchthrowsclose()

相反,我建议您利用资源进行尝试。这将为您提供一个隐式的最终块,无论是否发生异常,它都会关闭资源(现在,如果发生异常,您的调用将不会被执行)。另一种选择是显式声明 block,并关闭其中的资源。close()finally

尝试使用资源是更简洁、更干净的方式,以确保资源得到释放。

此外,请考虑使用缓冲的高级流包装这两个流以提高性能。这将大大减少应用程序访问文件系统所需的时间。

    try (var in = new BufferedInputStream(new FileInputStream("source.txt"));
         var out = new BufferedOutputStream(new FileOutputStream("destination.txt", false))) {

        int next; // a subsequent byte that has been read from the source
        while ((next = in.read()) != -1) {
            out.write(next);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }