在Windows上检查Java中文件是否为空的最有效方法

问题描述 投票:24回答:11

我试图在Windows上用Java检查日志文件是否为空(意味着没有错误)。到目前为止,我尝试过使用2种方法。

方法1(失败)

FileInputStream fis = new FileInputStream(new File(sLogFilename));  
int iByteCount = fis.read();  
if (iByteCount == -1)  
    System.out.println("NO ERRORS!");
else
    System.out.println("SOME ERRORS!");

方法2(失败)

File logFile = new File(sLogFilename);
if(logFile.length() == 0)
    System.out.println("NO ERRORS!");
else
    System.out.println("SOME ERRORS!");

现在,当日志文件为空(没有内容)时,这些方法都会失败,但文件大小不为零(2个字节)。

检查文件是否为空的最有效和最准确的方法是什么?我要求效率,因为我必须循环检查文件大小数千次。

注意:文件大小只会徘徊在几到10 KB左右!

方法3(失败)

按照@ Cygnusx1的建议,我也尝试过使用FileReader,但没有成功。这是片段,如果有人感兴趣的话。

Reader reader = new FileReader(sLogFilename);
int readSize = reader.read();
if (readSize == -1)
    System.out.println("NO ERRORS!");
else
    System.out.println("SOME ERRORS!");
java file logging file-io filesystems
11个回答
41
投票

检查第一行文件是否为空:

BufferedReader br = new BufferedReader(new FileReader("path_to_some_file"));     
if (br.readLine() == null) {
    System.out.println("No errors, and file empty");
}

0
投票

现在,当日志文件为空(没有内容)时,这些方法都会失败,但文件大小不为零(2个字节)。

实际上,我认为你会发现该文件不是空的。相反,我认为你会发现这两个字符是CR和NL;即文件由一行为空。

如果你想测试一个文件是空的还是只有一个空行,那么一个简单,相对有效的方法是:

try (BufferedReader br = new BufferedReader(FileReader(fileName))) {
    String line = br.readLine();
    if (line == null || 
        (line.length() == 0 && br.readLine() == null)) {
        System.out.println("NO ERRORS!");
    } else {
        System.out.println("SOME ERRORS!");
    }
}

我们能更有效地做到这一点吗?有可能。这取决于您处理三种不同情况的频率:

  • 一个完全空的文件
  • 由单个空行组成的文件
  • 具有非空行或多行的文件。

你可以通过使用Files.length()和/或只读取前两个字节来做得更好。但问题包括:

  • 如果你们都测试文件大小并读取前几个字节,那么你正在进行2次系统调用。
  • 实际的线路终止序列可以是CR,NL或CR NL,具体取决于平台。 (我知道你说这是针对Windows的,但是如果你需要移植你的应用程序会怎么样?或者如果有人发给你一个非Windows文件?)
  • 避免设置流/读取器堆栈会很好,但文件的字符编码可以将CR和NL映射到字节0x0d0x0a之外的其他内容。 (例如...... UTF-16)
  • 然后有一些令人讨厌的习惯,一些Windows实用程序已将BOM标记放入UTF-8编码文件中。 (这甚至会弄乱上面的简单版本!)

所有这些意味着最有效的解决方案将变得相当复杂。


0
投票

我认为最好的方法是使用file.length == 0

有时可能第一行是空的。


16
投票

为什么不使用:

File file = new File("test.txt");

if (file.length() == 0) {
    // file empty
} else {
    // not empty
}

它有什么问题吗?


2
投票

您可以选择尝试FileReader方法,但现在可能还没有时间放弃。如果BOM字段正在销毁,请尝试在stackoverflow上发布此解决方案。

Byte order mark screws up file reading in Java


2
投票

这是对Saik0的答案的改进,该答案基于Anwar Shaikh的评论,即太大的文件(高于可用内存)将引发异常:

使用Apache Commons FileUtils

private void printEmptyFileName(final File file) throws IOException {
    /*Arbitrary big-ish number that definitely is not an empty file*/
    int limit = 4096;
    if(file.length < limit && FileUtils.readFileToString(file).trim().isEmpty()) {
        System.out.println("File is empty: " + file.getName());
    }        
}

1
投票

另一种方法是(使用Apache Commons FileUtils) -

private void printEmptyFileName(final File file) throws IOException {
    if (FileUtils.readFileToString(file).trim().isEmpty()) {
        System.out.println("File is empty: " + file.getName());
    }        
}

1
投票

试试FileReader,这个阅读器是为了读取字符流,而FileInputStream是为了读取原始数据。

来自Javadoc:

FileReader用于读取字符流。要读取原始字节流,请考虑使用FileInputStream。

由于您想阅读日志文件,FileReader是使用IMO的类。


1
投票
String line = br.readLine();
String[] splitted = line.split("anySplitCharacter");
if(splitted.length == 0)
    //file is empty
else
    //file is not empty

我的文本文件遇到了同样的问题。虽然它是空的,但readLine方法返回的值不为null。因此,我尝试将其值分配给我用于访问数据的分割属性的String数组。它对我有用。试试这个并告诉我它是否适用于你。


0
投票

http://www.coderanch.com/t/279224/Streams/java/Checking-empty-file偷来的

FileInputStream fis = new FileInputStream(new File("file_name"));  
int b = fis.read();  
if (b == -1)  
{  
  System.out.println("!!File " + file_name + " emty!!");  
}  

更新:我的第一个答案为时过早,并且包含一个错误。


0
投票

你的第一个片段的想法是正确的。你可能想检查iByteCount == -1:文件是否至少有一个字节:

if (iByteCount == -1)  
    System.out.println("NO ERRORS!");
else
    System.out.println("SOME ERRORS!");
© www.soinside.com 2019 - 2024. All rights reserved.