La forma más eficiente de comprobar si un archivo está vacío en Java en Windows


Estoy tratando de comprobar si un archivo de registro está vacío (lo que significa que no hay errores) o no, en Java, en Windows. He intentado usar 2 métodos hasta ahora.

Método 1 (Fallo)

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

Método 2 (Fallo)

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

Ahora ambos métodos fallan cuando el archivo de registro está vacío (no tiene contenido), pero el tamaño del archivo no es cero (2 bytes).

¿Cuál es el método más eficiente y para comprobar si el archivo está vacío? Pedí eficiencia, ya que tengo que seguir comprobando el tamaño del archivo miles de veces, en un bucle.

Nota: ¡El tamaño del archivo oscilaría entre unos pocos y 10 KB solamente!

Método 3 (Fallo)

Siguiendo la sugerencia de @Cygnusx1, también había intentado usar un FileReader, sin éxito. Aquí está el fragmento, si alguien está interesado.

Reader reader = new FileReader(sLogFilename);
int readSize = reader.read();
if (readSize == -1)
    System.out.println("NO ERRORS!");
else
    System.out.println("SOME ERRORS!");
Author: GPX, 2011-08-25

11 answers

Compruebe si la primera línea del archivo está vacía:

BufferedReader br = new BufferedReader(new FileReader("path_to_some_file"));     
if (br.readLine() == null) {
    System.out.println("No errors, and file empty");
}
 40
Author: Victor Carmouze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-20 17:37:26

¿Por qué no usar:

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

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

¿Hay algo malo en ello?

 17
Author: SneakyMummin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-25 02:38:08

Puede elegir probar el enfoque FileReader, pero puede que no sea el momento de darse por vencido todavía. Si es el campo de la lista de materiales de destrucción para que pruebe esta solución publicada aquí en stackoverflow.

La marca de orden de bytes arruina la lectura de archivos en Java

 2
Author: Farmor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:09:44

Otra forma de hacer esto es (usando 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
Author: Saikat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-30 11:31:02

Esta es una mejora de la respuesta de Saik0 basada en el comentario de Anwar Shaikh de que los archivos demasiado grandes (por encima de la memoria disponible) lanzarán una excepción:

Usando 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
Author: Manuel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-29 08:36:25

Intente FileReader, este lector está destinado a leer el flujo de caracteres, mientras que FileInputStream está destinado a leer datos sin procesar.

Del Javadoc:

FileReader está diseñado para leer flujos de caracteres. Para leer flujos de bytes sin procesar, considere usar un FileInputStream.

Dado que desea leer un archivo de registro, FileReader es la clase para usar IMO.

 1
Author: Cygnusx1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-14 10:25:22
String line = br.readLine();
String[] splitted = line.split("anySplitCharacter");
if(splitted.length == 0)
    //file is empty
else
    //file is not empty

Tuve el mismo problema con mi archivo de texto. Aunque estaba vacío, el valor devuelto por el método readLine no era null. Por lo tanto, traté de asignar su valor a la matriz de cadenas que estaba utilizando para acceder a los atributos divididos de mis datos. Funcionó para mí. Prueba esto y dime si funciona para ti también.

 1
Author: crazyDeveloper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-26 22:22:25

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

Actualizado: Mi primera respuesta fue prematura y contenía un error.

 0
Author: Farmor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-25 12:51:08

La idea de tu primer fragmento es correcta. Usted probablemente significaba para comprobar iByteCount == -1: si el archivo tiene al menos un byte:

if (iByteCount == -1)  
    System.out.println("NO ERRORS!");
else
    System.out.println("SOME ERRORS!");
 0
Author: Nivas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-25 12:52:23

Ahora ambos métodos fallan cuando el archivo de registro está vacío (no tiene contenido), pero el tamaño del archivo no es cero (2 bytes).

En realidad, creo que encontrará que el archivo NO está vacío. Más bien creo que encontrará que esos dos caracteres son un CR y un NL; es decir, el archivo consta de una línea que está vacía.

Si desea probar si un archivo está vacío o tiene una sola línea vacía, entonces una forma simple y relativamente eficiente es:

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

Podemos hacer esto de manera más eficiente? Posiblemente. Depende de la frecuencia con la que tenga que lidiar con los tres casos diferentes:

  • un archivo completamente vacío
  • un archivo que consiste en una sola línea vacía
  • un archivo con una línea no vacía, o varias líneas.

Probablemente puedas hacerlo mejor usando Files.length() y / o leyendo solo los dos primeros bytes. Sin embargo, los problemas incluyen:

  • Si ambos prueban el tamaño del archivo Y leen los primeros bytes, entonces están haciendo 2 syscalls.
  • La secuencia real de terminación de línea podría ser CR, NL o CR NL, dependiendo de la plataforma. (Sé que dices que esto es para Windows, pero ¿qué pasa si necesitas portar tu aplicación? ¿O si alguien te envía un archivo que no es de Windows?)
  • Sería bueno evitar configurar stream / reader stack, pero la codificación de caracteres del archivo podría mapear CR y NL a algo que no sea los bytes 0x0d y 0x0a. (Por ejemplo ... UTF-16)
  • Entonces existe el molesto hábito de algunas utilidades de Windows han poner marcadores de BOM en archivos codificados UTF-8. (Esto incluso estropear la versión simple de arriba!)

Todo esto significa que la solución más eficiente posible va a ser bastante complicada.

 0
Author: Stephen C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-28 12:47:48

Creo que la mejor manera es usar file.length == 0.

A veces es posible que la primera línea esté vacía.

 0
Author: user3744089,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-28 15:02:52