web-dev-qa-db-fra.com

Déterminer le type de fichier binaire / texte en Java?

À savoir, comment diriez-vous un fichier d'archive (jar/rar/etc.) À partir d'un fichier textuel (xml/txt, indépendant de l'encodage)?

42
yanchenko

Il n'y a pas de moyen garanti, mais voici quelques possibilités:

1) Recherchez un en-tête dans le fichier. Malheureusement, les en-têtes sont spécifiques au fichier, donc bien que vous puissiez découvrir qu'il s'agit d'un fichier RAR, vous n'obtiendrez pas la réponse plus générique qu'il s'agisse de texte ou de binaire.

2) Comptez le nombre de types de caractères par rapport aux types sans caractère. Les fichiers texte seront principalement des caractères alphabétiques tandis que les fichiers binaires - en particulier ceux compressés comme rar, Zip, etc. - auront tendance à être représentés de manière plus uniforme.

3) Recherchez une répétition régulière de nouvelles lignes.

18
Aric TenEyck

Utilisation de Java 7 classe 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;
        }
    }
10
rince

Courir file -bi {filename}. Si tout ce qu'il retourne commence par 'text /', alors ce n'est pas binaire, sinon c'est le cas. ;-)

10
Wilfred Springer

J'ai fait celui-ci. Un peu plus simple, mais pour les langues à base latine, cela devrait fonctionner correctement, avec l'ajustement du rapport.

/**
 *  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;
}
10
Ondra Žižka

Jetez un œil à la bibliothèque JMimeMagic .

jMimeMagic est une bibliothèque Java pour déterminer le type MIME de fichiers ou de flux.

9
Daniel Hiller

J'ai utilisé ce code et cela fonctionne plutôt bien pour le texte anglais et allemand:

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;
}
6

Si le fichier se compose des octets 0x09 (tabulation), 0x0A (saut de ligne), 0x0C (saut de page), 0x0D (retour chariot) ou 0x20 à 0x7E, il s'agit probablement du texte ASCII.

Si le fichier contient tout autre caractère de contrôle ASCII, 0x00 à 0x1F à l'exclusion des trois ci-dessus, il s'agit probablement de données binaires.

Le texte UTF-8 suit un modèle très spécifique pour tous les octets avec le bit de poids fort, mais pas les codages de longueur fixe comme ISO-8859-1. UTF-16 peut fréquemment contenir l'octet nul (0x00), mais uniquement dans toutes les autres positions.

Vous auriez besoin d'une heuristique plus faible pour autre chose.

3
Matthew

Juste pour vous faire savoir, j'ai choisi une voie assez différente. Dans mon cas, il n'y a que 2 types de fichiers, les chances qu'un fichier donné soit binaire sont élevées. Alors

  1. présumer que le fichier est binaire, essayez de faire ce qui est censé être fait (par exemple, désérialiser)
  2. attraper l'exception
  3. traiter le fichier comme textuel
  4. si cela échoue, quelque chose ne va pas avec le fichier lui-même
3
yanchenko
2
MarkusQ

Vous pouvez essayer l'outil DROÏDE .

1
Fabian Steeg