Determinar el tipo de archivo binario/de texto en Java?


Es decir, cómo le diría a un archivo (jar/rar / etc.) archivo de un texto (xml / txt, independiente de la codificación) uno?

Author: Ondra Žižka, 2009-03-07

10 answers

No hay manera garantizada, pero aquí hay un par de posibilidades:

1) Busque un encabezado en el archivo. Desafortunadamente, los encabezados son específicos del archivo, por lo que si bien es posible que pueda descubrir que es un archivo RAR, no obtendrá la respuesta más genérica de si es texto o binario.

2) Cuente el número de caracteres frente a los tipos que no son caracteres. Los archivos de texto serán en su mayoría caracteres alfabéticos, mientras que los archivos binarios, especialmente los comprimidos como rar, zip y otros, tenderán para tener bytes representados de manera más uniforme.

3) Busque un patrón de nuevas líneas que se repita regularmente.

 16
Author: Aric TenEyck,
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
2009-03-07 00:35:27

Ejecutar file -bi {filename}. Si lo que sea que devuelve comienza con ' text/', entonces no es binario, de lo contrario lo es. ;-)

 10
Author: Wilfred Springer,
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
2009-10-21 06:39:18

Hice este. Un poco más simple, pero para los idiomas basados en latín, debería funcionar bien, con el ajuste de la proporción.

/**
 *  Guess whether given file is binary. Just checks for anything under 0x09.
 */
public static boolean isBinaryFile(File f) throws FileNotFoundException, IOException {
    FileInputStream in = new FileInputStream(f);
    int size = in.available();
    if(size > 1024) size = 1024;
    byte[] data = new byte[size];
    in.read(data);
    in.close();

    int ascii = 0;
    int other = 0;

    for(int i = 0; i < data.length; i++) {
        byte b = data[i];
        if( b < 0x09 ) return true;

        if( b == 0x09 || b == 0x0A || b == 0x0C || b == 0x0D ) ascii++;
        else if( b >= 0x20  &&  b <= 0x7E ) ascii++;
        else other++;
    }

    if( other == 0 ) return false;

    return 100 * other / (ascii + other) > 95;
}
 9
Author: Ondra Žižka,
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
2015-07-09 09:21:15

Echa un vistazo a la biblioteca JMimeMagic.

JMimeMagic es una biblioteca Java para determinar el tipo MIME de archivos o flujo.

 9
Author: Daniel Hiller,
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-06-27 12:33:07

Usando la clase Java 7 Files http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#probeContentType(java.nio.file.Path)

boolean isBinaryFile(File f) throws IOException {
        String type = Files.probeContentType(f.toPath());
        if (type == null) {
            //type couldn't be determined, assume binary
            return true;
        } else if (type.startsWith("text")) {
            return false;
        } else {
            //type isn't text
            return true;
        }
    }
 7
Author: rince,
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-10-06 19:02:53

Usé este código y funciona bastante bien para texto en inglés y alemán:

private boolean isTextFile(String filePath) throws Exception {
    File f = new File(filePath);
    if(!f.exists())
        return false;
    FileInputStream in = new FileInputStream(f);
    int size = in.available();
    if(size > 1000)
        size = 1000;
    byte[] data = new byte[size];
    in.read(data);
    in.close();
    String s = new String(data, "ISO-8859-1");
    String s2 = s.replaceAll(
            "[a-zA-Z0-9ßöäü\\.\\*!\"§\\$\\%&/()=\\?@~'#:,;\\"+
            "+><\\|\\[\\]\\{\\}\\^°²³\\\\ \\n\\r\\t_\\-`´âêîô"+
            "ÂÊÔÎáéíóàèìòÁÉÍÓÀÈÌÒ©‰¢£¥€±¿»«¼½¾™ª]", "");
    // will delete all text signs

    double d = (double)(s.length() - s2.length()) / (double)(s.length());
    // percentage of text signs in the text
    return d > 0.95;
}
 5
Author: Michael von Wenckstern,
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-01-01 17:36:11

Si el archivo consta de los bytes 0x09 (tab), 0x0A (line feed), 0x0C (form feed), 0x0D (carriage return), o 0x20 hasta 0x7E, entonces probablemente es texto ASCII.

Si el archivo contiene cualquier otro carácter de control ASCII, de 0x00 a 0x1F excluyendo los tres anteriores, entonces probablemente son datos binarios.

El texto UTF-8 sigue un patrón muy específico para cualquier byte con el bit de orden alto, pero las codificaciones de longitud fija como ISO-8859-1 no lo hacen. UTF-16 puede contener frecuentemente el byte nulo (0x00), pero solo en cualquier otra posición.

Necesitarías una heurística más débil para cualquier otra cosa.

 3
Author: Matthew,
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
2009-03-07 01:29:22

Solo para que sepas, he elegido un camino bastante diferente. En mi caso, solo hay 2 tipos de archivos, las posibilidades de que cualquier archivo sea binario son altas. So

  1. suponga que el archivo es binario, intente hacer lo que se supone que debe hacerse (por ejemplo, deserializar)
  2. excepción de captura
  3. tratar el archivo como textual
  4. si eso falla, algo está mal con el propio archivo
 3
Author: yanchenko,
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
2009-03-15 02:12:53
 2
Author: MarkusQ,
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
2009-03-10 23:32:14

Puedes probar la herramienta DROID.

 1
Author: Fabian Steeg,
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
2009-03-07 00:43:54