愿FileInputStream.available愚蠢吗?

这个FileInputStream.available()javadoc说:

返回可以从此输入流中读取(或跳过)的剩余字节数的估计值,而不会被下一次调用此输入流的方法阻塞。 下一次调用可能是同一个线程或另一个线程。 单个读取或跳过这么多字节不会阻塞,但可以读取或跳过更少的字节。

在某些情况下,非阻塞读取(或跳过)可能在速度很慢时似乎被阻止,例如在通过慢速网络读取大型文件时。

我不确定在这张支票中是否:

if (new FileInputStream(xmlFile).available() == 0) 

我可以依赖那些空文件总是返回零吗?

谢谢@SB,他没有完全回答这个问题,但却是第一个提供最佳选择的人:

如果xmlFile是java.io.File对象,则可以使用length()方法获取其大小。

如果指定的文件为空,则可以依赖new FileInputStream(fileName).available()返回零。

不能依赖new FileInputStream(fileName).available() == 0作为文件为空的权威性测试。 如果fileName是本地文件系统上的常规文件,它可能会起作用。 但是,如果fileName是设备文件或者它是远程文件系统上的文件,则available()可能返回零以报告read()必须阻塞一段时间。 (或者在远程文件系统的情况下,它可能不会。)

测试常规文件长度的更可靠方法是使用new File(fileName).length() == 0 。 但是,对于设备文件或管道, length()调用可能返回零,而不管最终可以读取的字节数。 请记住,如果文件不存在, new File(fileName).length()也会返回零。

编辑如果您想要一个可靠的测试来查看文件是否为空,您必须进行多次调用:

 public static isEmptyFile(String fileName) { File file = new File(fileName); if (!file.exists()) { return false; } else if (file.length() != 0L) { return false; } else if (file.isFile()) { return true; } else if (file.isDirectory()) { return false; } else { // It may be impossible to tell that a device file / named pipe is // "empty" without actually reading it. This is not a failing of // Java: it is a logical consequence of the way that certain // devices, etc work. throw new CannotAnswerException(...); } } 

但是建议您在运行应用程序的所有平台上使用各种“文件”类型仔细测试。 某些文件谓词的行为记录为特定于平台; 看到javadoc 。

我强烈建议不要使用available() – 它可以返回0,因为流被阻塞,即使仍有足够的字节要读取。 它可能不会发生在文件中,但API不保证它不会。

尽管如此,read()也可以使用相同的方法:

 if (new FileInputStream(xmlFile).read() == -1) System.out.println("!!File empty!!"); 

如果xmlFile是java.io.File对象,则可以使用length()方法获取其大小。

我对这个问题的合理回答是“我可以依赖空文件总是返回零吗?” 是“是的,对于空文件, available()将返回0”。

但你可能也想知道“我可以依赖只有空文件会返回零吗?”,答案是“不,不是按规格说明:即使文件不为空, available()也可能返回0”。

此外,您正在打开文件流, 不要再次关闭它 。 这可能会导致意外和不良行为,例如,只要Java程序正在运行,您就可能无法移动或删除该文件。 如果您的程序在通常运行很长时间的应用程序服务器中运行,这使得文件实际上不可变,这尤其令人讨厌。