33

I am trying to check if a log file is empty (meaning no errors) or not, in Java, on Windows. I have tried using 2 methods so far.

Method 1 (Failure)

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!");

Method 2 (Failure)

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

Now both these methods fail at times when the log file is empty (has no content), yet the file size is not zero (2 bytes).

What is the most efficient and accurate method to check if the file is empty? I asked for efficiency, as I have to keep checking the file size thousands of times, in a loop.

Note: The file size would hover around a few to 10 KB only!

Method 3 (Failure)

Following @Cygnusx1's suggestion, I had tried using a FileReader too, without success. Here's the snippet, if anyone's interested.

Reader reader = new FileReader(sLogFilename);
int readSize = reader.read();
if (readSize == -1)
    System.out.println("NO ERRORS!");
else
    System.out.println("SOME ERRORS!");
GPX
  • 3,506
  • 10
  • 52
  • 69
  • I don`t understand how the file can be empty and still have a size of 2 bytes? I have wrote the exact same code as you and with an empty file, i get the expected result NO ERRORS in your case. – Cygnusx1 Aug 25 '11 at 13:20
  • ok forget my comment, just read about BOM and unicode. – Cygnusx1 Aug 25 '11 at 13:23
  • 2
    Unicode encoding often uses a BOM field as an identifier, which takes up 255 bytes. My guess is, your empty file is ANSI encoded. Try with Unicode encoding. – GPX Aug 25 '11 at 13:24
  • yeah i saw, question: do you have control on the creation of this log file? Could you change it's encoding to UTF-8? it would solve your problem. – Cygnusx1 Aug 25 '11 at 13:33
  • I've considered that. But in my specific case, sadly, no. – GPX Aug 25 '11 at 13:46
  • @GPX - A BOM doesn't take up to 255 bytes. It takes just 3 bytes in UTF-8 or 2 bytes in UTF-16. (Source: https://en.wikipedia.org/wiki/Byte_order_mark) – Stephen C Jan 27 '23 at 04:40

12 Answers12

49

Check if the first line of file is empty:

BufferedReader br = new BufferedReader(new FileReader("path_to_some_file"));     
if (br.readLine() == null) {
    System.out.println("No errors, and file empty");
}
Dan J
  • 25,433
  • 17
  • 100
  • 173
Victor Carmouze
  • 947
  • 6
  • 10
  • Well I guess I'll use this method, as this works. Can you say this is the most efficient method? – GPX Aug 26 '11 at 05:24
  • Update: This method doesn't work either. When I use `readLine()`, it returns these junk characters - `ÿþ`. Now I'm confused. – GPX Aug 26 '11 at 08:41
  • 1
    This method *does* work if the input file is ANSI-encoded. Marking this as the answer. – GPX Dec 20 '11 at 04:51
  • Am I missing something or is there no file.readLine() method? – w25r Dec 06 '12 at 17:01
  • 1
    @w25r java.io.File.readLine() doesn't exist, Victor is referring to an example use of a BufferedReader.readLine(). I've updated the answer so that it isn't confusing anymore. – Drupad Panchal Jan 23 '13 at 19:49
  • when I use this, the main class throws an error. Exception in thread "main" java.lang.NullPointerException at java.io.FileInputStream.(FileInputStream.java:134) at java.io.FileReader.(FileReader.java:72) – Arhat Baid Apr 17 '15 at 04:10
  • This method doesn't work if the file encoding is ANSI, for example there are 10 blank-lines and than comes a character, the first line will be null yes, but the others maybe not. – Simon Oct 20 '17 at 11:26
23

Why not just use:

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

if (file.length() == 0) {
    // File empty
} else {
    // Not empty
}
user16217248
  • 3,119
  • 19
  • 19
  • 37
SneakyMummin
  • 683
  • 1
  • 11
  • 30
  • 10
    This doesn't work with Unicode files. Check **Method 2** in my original post. – GPX Jun 18 '12 at 13:21
  • It also returns long the file.length() method – Lefteris Bab May 18 '17 at 14:22
  • @GPX Sorry for being tardy to class. When you say a unicode file can be empty but have bytes, are you referring to [this](https://stackoverflow.com/questions/18516343/why-empty-text-file-contains-3-bytes)? – Jeff Holt Feb 14 '18 at 19:42
3

This is an improvement of Saik0's answer based on Anwar Shaikh's comment that too big files (above available memory) will throw an exception:

Using 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());
    }        
}
Emma
  • 430
  • 8
  • 14
2

Now both these methods fail at times when the log file is empty (has no content), yet the file size is not zero (2 bytes).

Actually, I think you will find that the file is NOT empty. Rather I think that you will find that those two characters are a CR and a NL; i.e. the file consists of one line that is empty. A truly empty file does in fact have a file size of zero.

If you want to test if a file is either empty or has a single empty line then a simple, relatively efficient way is:

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

Can we do this more efficiently? Possibly. It depends on how often you have to deal with the three different cases:

  • a completely empty file
  • a file consisting of a single empty line
  • a file with a non-empty line, or multiple lines.

You can probably do better by using Files.length() and / or reading just the first two bytes. However, the problems include:

  • If you both test the file size AND read the first few bytes then you are making 2 syscalls.
  • The actual line termination sequence could be CR, NL or CR NL, depending on the platform. (I know you say this is for Windows, but what happens if you need to port your application? Or if someone sends you a non-Windows file?)
  • It would be nice to avoid setting up stream / reader stack, but the file's character encoding could map CR and NL to something other than the bytes 0x0d and 0x0a. (For example ... UTF-16)
  • Then there's the annoying habit of some Windows utilities have putting byte order markers into UTF-8 encoded files. (This would even mess up the simple version above!) A BOM is the Unicode code point U+FEFF which will render as 3 bytes in UTF-8 and 2 bytes in UTF-16 and 4 bytes in UTF-32.

All of this means that the most efficient possible solution is going to be rather complicated.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
2

You can choose try the FileReader approach but it may not be time to give up just yet. If is the BOM field destroying for you try this solution posted here at stackoverflow.

Byte order mark screws up file reading in Java

Community
  • 1
  • 1
  • Whilst this may theoretically answer the question, [it would be preferable](//meta.stackoverflow.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – Kalle Richter Jan 08 '17 at 15:10
1

Another way to do this is (using 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());
    }        
}
Saikat
  • 14,222
  • 20
  • 104
  • 125
  • 4
    The method readFileToString(..) method will give exception "Java heap space error" if file is huge and insufficient memory available. – Anwar Shaikh Jun 08 '15 at 08:38
1
String line = br.readLine();
String[] splitted = line.split("anySplitCharacter");
if(splitted.length == 0)
    //file is empty
else
    //file is not empty

I had the same problem with my text file. Although it was empty, the value being returned by the readLine method was not null. Therefore, I tried to assign its value to the String array which I was using to access the splitted attributes of my data. It did work for me. Try this out and tell me if it works for u as well.

  • 1
    Why not check if `line.isEmpty()`? – shmosel Dec 26 '17 at 22:23
  • Its because br.readLine will return a non-null value because when a file is created, although it looks empty, it isn't actually empty. I don't know for sure which characters are already inside it but the file is not empty even though it looks as if it is. – crazyDeveloper Jun 19 '18 at 11:10
  • What's your point? You think `isEmpty()` will return true if it *looks* empty? – shmosel Jun 19 '18 at 16:39
  • No, I did not mean that isEmpty() will return true if it looks empty. We all know that a String is an array of characters and we also know that isEmpty() returns true if the length of the String is zero, but these hidden junk characters that I was talking about are not visible in the file if we open it but they are there and add upto the length of the String thus making isEmpty() an inappropriate method to use here. – crazyDeveloper Jul 18 '18 at 11:08
  • 1
    Why would splitting operate differently? – shmosel Jul 18 '18 at 16:38
1

I combined the two best solutions to cover all the possibilities:

File file = new File(fileName);
BufferedReader br = new BufferedReader(new FileReader(file));     
if (br.readLine() == null && file.length() == 0)
{
    System.out.println("No errors, and file empty");
}                
else
{
    System.out.println("File contains something");
}
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
1

Try FileReader, this reader is meant to read stream of character, while FileInputStream is meant to read raw data.

From the Javadoc:

FileReader is meant for reading streams of characters. For reading streams of raw bytes, consider using a FileInputStream.

Since you wanna read a log file, FileReader is the class to use IMO.

Enigo
  • 3,685
  • 5
  • 29
  • 54
Cygnusx1
  • 5,329
  • 2
  • 27
  • 39
  • Yeah, i did a test with both methods and they work the same way. In the end, my suggestion is still valid, but it does not solve the unicode BOM problem. Look at Farmor answer and the link to another answer about this problem. – Cygnusx1 Aug 25 '11 at 13:26
0

I think the best way is to use file.length == 0.

It is sometimes possible that the first line is empty.

0

Stolen from 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!!");  
}  

Updated: My first answer was premature and contained a bug.

0

The idea of your first snippet is right. You probably meant to check iByteCount == -1: whether the file has at least one byte:

if (iByteCount == -1)  
    System.out.println("NO ERRORS!");
else
    System.out.println("SOME ERRORS!");
Nivas
  • 18,126
  • 4
  • 62
  • 76
  • Well this is embarrassing! But trying this out, I have an empty file (absolutely empty - no spaces, no new lines) - but the byte count is 255 bytes. My guess is, it could because of the BOM field for Unicode. So this method doesn't work for me. – GPX Aug 25 '11 at 13:00