2010-06-22 10 views
5

J'ai écrit la méthode suivante pour voir si un fichier particulier contient des caractères de texte ASCII seulement ou des caractères de contrôle en plus de cela. Pourriez-vous jeter un coup d'oeil sur ce code, suggérer des améliorations et souligner les oublis?Comment vérifier si le fichier est binaire?

La logique est la suivante: « Si les 500 premiers octets d'un fichier contiennent 5 ou plusieurs caractères de contrôle - le signaler sous forme de fichier binaire »

merci.

public boolean isAsciiText(String fileName) throws IOException { 

    InputStream in = new FileInputStream(fileName); 
    byte[] bytes = new byte[500]; 

    in.read(bytes, 0, bytes.length); 
    int x = 0; 
    short bin = 0; 

    for (byte thisByte : bytes) { 
     char it = (char) thisByte; 
     if (!Character.isWhitespace(it) && Character.isISOControl(it)) { 

      bin++; 
     } 
     if (bin >= 5) { 
      return false; 
     } 
     x++; 
    } 
    in.close(); 
    return true; 
} 

Répondre

3

Puisque vous appelez cette classe "isASCIIText", vous savez exactement ce que vous cherchez. En d'autres termes, ce n'est pas "isTextInCurrentLocaleEncoding". Ainsi, vous pouvez être plus précis avec:

if (thisByte < 32 || thisByte > 127) bin++; 

modifier, longtemps après — il a fait remarquer dans un commentaire que cette simple vérification serait déclenché par un fichier texte qui a commencé avec beaucoup de nouvelles lignes. Il serait probablement mieux d'utiliser une table de "ok" octets, et inclure des caractères imprimables (y compris le retour chariot, newline et tabulation, et éventuellement former le flux si je ne pense pas que beaucoup de documents modernes utilisent ceux-ci), puis vérifier la table.

+0

Il est une tragédie que cela est marqué comme la bonne réponse, lorsque cet algorithme classerait un fichier qui contient « ce \ r \ nis \ r \ nUne \ r \ ntext » sous forme binaire. – Ingo

+1

@Ingo vrai; il vaudrait mieux vérifier le rapport entre les caractères de contrôle et les non-contrôles, et aussi vérifier les cas spéciaux comme les caractères de contrôle communs dans le texte. J'étais si jeune quand j'ai tapé cette réponse :) – Pointy

3

x ne semble pas faire quoi que ce soit.

Que faire si le fichier est inférieur à 500 octets?

Certains fichiers binaires ont une situation où vous pouvez avoir un en-tête pour les N premiers octets du fichier qui contient des données utiles pour une application, mais que la bibliothèque pour laquelle le binaire est fait ne compte pas. Vous pourriez facilement avoir plus de 500 octets d'ASCII dans un préambule comme celui-ci suivi de données binaires dans le gigaoctet suivant.

doit gérer exception si le fichier ne peut être ouvert ou lu, etc.

1

La première chose que je remarque - sans rapport avec votre question réelle, mais vous devriez fermerons votre flux d'entrée dans un bloc finally pour assurer c'est toujours fait. Habituellement, cela ne gère que les exceptions, mais dans votre cas, vous ne fermez même pas les flux de fichiers lors du retour false.

En dehors de cela, pourquoi la comparaison aux caractères de contrôle ISO? Ce n'est pas un fichier "binaire", c'est un "fichier qui contient 5 caractères de contrôle ou plus". Une meilleure façon d'aborder la situation à mon avis, serait d'inverser la vérification - écrire une fonction isAsciiText à la place qui affirme que tous les caractères dans le fichier (ou dans les 500 premiers octets si vous le souhaitez) sont dans un ensemble d'octets qui sont connu bon. En théorie, ne vérifier que les quelques centaines d'octets d'un fichier pourrait vous causer des ennuis s'il s'agissait d'un fichier composite (par exemple un texte avec des images incorporées), mais en pratique je suspecte que chaque fichier aura des données d'en-tête binaires au début, vous êtes probablement d'accord.

0
  1. Vous ignorez ce que read() renvoie, et si les fichiers sont plus courts que 500 octets?
  2. Lorsque vous renvoyez false, vous ne fermez pas le fichier.
  3. Lors de la conversion d'un octet en caractère char, vous supposez que votre fichier est ASCII 7 bits.
0

Ceci ne fonctionnerait pas avec les paquets d'installation de jdk pour linux ou solaris.ils ont un début shell-script et ensuite un blob de données bi. Pourquoi ne pas vérifier le type mime en utilisant une bibliothèque comme jMimeMagic (http://http://sourceforge.net/projects/jmimemagic/) et désider en fonction du type mime comment gérer le fichier.

3
  1. ne réussit pas mal si la taille du fichier est inférieure à 500 octets

  2. La ligne char it = (char) thisByte; est douteuse sur le plan conceptuel, il mêle les concepts d'octets et de caractères, par exemple. suppose implicitement que l'encodage est un octet = un caractère (eux, il exclut les codages Unicode). En particulier, il échoue si le fichier est codé en UTF-16.

  3. Le retour dans la boucle (pratique un peu mauvaise OMI) oublie de fermer le fichier.

Questions connexes