Java - Comment savoir si un nom de Fichier est valide? [dupliquer]

cette question a déjà une réponse ici:

  • Est-il un moyen en Java pour déterminer si un chemin est valide sans essayer de créer un fichier? 5 réponses

dans mon application Java, je renomme des fichiers à un nom de fichier fourni dans un paramètre String. Il existe une méthode

boolean OKtoRename(String oldName, String newName)

qui vérifie si le nouveau nom n'est pas déjà pris par un autre fichier, car je ne voudrais pas enterrer ceux qui existent déjà.

il m'est apparu maintenant que peut-être la chaîne de caractères newName ne désignera pas un nom de fichier valide. J'ai donc pensé à ajouter cette vérification à la méthode:

if (new File(newName).isFile()) { 
    return false; 
}

qui n'est évidemment pas la bonne façon de le faire, puisque dans la plupart des cas le nouveau n'existe pas encore et donc bien qu'il est OKtoRename, la fonction retourne false.

je me demandais, y a-t-il une méthode (je sais qu'il n'y en a pas pour le java.io.File objects) like canExist() ? Ou devrais-je recourir à regex pour m'assurer que la chaîne de caractères newFile ne contient pas de caractères invalides (par exemple ?, *,",:)? Je me demande s'il y a peut-être une fonction cachée quelque part dans le JDK qui me dirait si une chaîne de caractères pourrait éventuellement dénoter un nom de fichier valide.

48
demandé sur OscarRyz 2009-05-21 21:04:46

8 réponses

Use createNewFile() , qui ne créera le fichier que s'il n'existe pas encore.

Si le fichier est créé, le nom est valide et il n'est pas casser un fichier existant. Vous pouvez ensuite ouvrir les fichiers et copier efficacement les données de l'un à l'autre avec les opérations FileChannel.transferXXX .

Une chose importante à garder à l'esprit que, en général, la vérification et la création doit être atomique. Si vous vérifiez d'abord si une opération est sûr, puis effectuer l'opération comme une étape distincte, les conditions ont changé dans le temps, ce qui rend l'opération dangereuse.

des éléments supplémentaires pour alimenter la réflexion sont disponibles sur ce post connexe: "opérations de copie/déplacement en Java."


mise à jour:

depuis cette réponse, le NIO.2 IPA ont été introduits, qui ajoutent plus l'interaction avec le système de fichiers.

supposons que vous avez un programme interactif, et que vous voulez valider après chaque frappe si le fichier est potentiellement valide. Par exemple, vous pourriez vouloir activer un bouton "Enregistrer" seulement quand l'entrée est valide plutôt que de faire apparaître une boîte de dialogue d'erreur après avoir appuyé sur "Enregistrer". Créer et assurer la suppression d'un grand nombre de fichiers inutiles que ma suggestion ci-dessus exigerait semble comme un gâchis.

avec NIO.2, vous impossible de créer une instance Path contenant des caractères illégaux pour le système de fichiers. Un InvalidPathException est soulevé dès que vous essayez de créer le Path .

cependant, il n'y a pas D'API pour valider les noms illégaux composés de caractères valides, comme "PRN" sur Windows. Comme solution de contournement , l'expérimentation a montré que l'utilisation d'un nom de fichier illégal soulèverait une exception distincte lors de l'accès aux attributs (en utilisant Files.getLastModifiedTime() , par exemple).

si vous spécifiez un nom légal pour un fichier qui existe, vous n'avez aucune exception.

Si vous spécifiez un nom légal pour un fichier qui n'existe pas, elle soulève NoSuchFileException .

si vous spécifiez un nom illégal, FileSystemException est augmenté.

cependant, cela semble très kludgey et pourrait ne pas être fiable sur d'autres systèmes d'exploitation.

22
répondu erickson 2017-05-23 11:46:54

j'ai assemblé une liste de noms de fichiers illégaux (concernant les systèmes UNIX, Mac OS X et Windows) basée sur une recherche en ligne il y a quelques mois. Si le nouveau nom de fichier contient l'un de ceux-ci, il y a un risque qu'il ne soit pas valide sur toutes les plateformes.

private static final char[] ILLEGAL_CHARACTERS = { '/', '\n', '\r', '\t', '"151900920"', '\f', '`', '?', '*', '\', '<', '>', '|', '\"', ':' };

EDIT: Je voudrais souligner, qu'il s'agit de pas une solution complète : comme un commentateur a souligné, même si elle passe ce test votre nom de fichier peut encore être un mot-clé spécifique de Windows COMME COM, PRN, etc. Cependant, si votre nom de fichier contient l'un de ces caractères, il causera certainement des problèmes dans un environnement multiplateforme.

57
répondu Zsolt Török 2010-08-30 15:04:28

Ici système de manière spécifique est proposé.

public static boolean isFilenameValid(String file) {
  File f = new File(file);
  try {
    f.getCanonicalPath();
    return true;
  } catch (IOException e) {
    return false;
  }
}
17
répondu Maxim Mazin 2011-11-04 15:24:39

si vous développez pour L'éclipse, cochez org.eclipse.core.internal.resources.OS

public abstract class OS {
   private static final String INSTALLED_PLATFORM;

   public static final char[] INVALID_RESOURCE_CHARACTERS;
   private static final String[] INVALID_RESOURCE_BASENAMES;
   private static final String[] INVALID_RESOURCE_FULLNAMES;

   static {
      //find out the OS being used
      //setup the invalid names
      INSTALLED_PLATFORM = Platform.getOS();
      if (INSTALLED_PLATFORM.equals(Platform.OS_WIN32)) {
         //valid names and characters taken from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp
         INVALID_RESOURCE_CHARACTERS = new char[] {'\', '/', ':', '*', '?', '"', '<', '>', '|'};
         INVALID_RESOURCE_BASENAMES = new String[] {"aux", "com1", "com2", "com3", "com4", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ 
               "com5", "com6", "com7", "com8", "com9", "con", "lpt1", "lpt2", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
               "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", "nul", "prn"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$
         Arrays.sort(INVALID_RESOURCE_BASENAMES);
         //CLOCK$ may be used if an extension is provided
         INVALID_RESOURCE_FULLNAMES = new String[] {"clock$"}; //$NON-NLS-1$
      } else {
         //only front slash and null char are invalid on UNIXes
         //taken from http://www.faqs.org/faqs/unix-faq/faq/part2/section-2.html
         INVALID_RESOURCE_CHARACTERS = new char[] {'/', '"151900920"',};
         INVALID_RESOURCE_BASENAMES = null;
         INVALID_RESOURCE_FULLNAMES = null;
      }
   }

   /**
    * Returns true if the given name is a valid resource name on this operating system,
    * and false otherwise.
    */
   public static boolean isNameValid(String name) {
      //. and .. have special meaning on all platforms
      if (name.equals(".") || name.equals("..")) //$NON-NLS-1$ //$NON-NLS-2$
         return false;
      if (INSTALLED_PLATFORM.equals(Platform.OS_WIN32)) {
         //empty names are not valid
         final int length = name.length();
         if (length == 0)
            return false;
         final char lastChar = name.charAt(length-1);
         // filenames ending in dot are not valid
         if (lastChar == '.')
            return false;
         // file names ending with whitespace are truncated (bug 118997)
         if (Character.isWhitespace(lastChar))
            return false;
         int dot = name.indexOf('.');
         //on windows, filename suffixes are not relevant to name validity
         String basename = dot == -1 ? name : name.substring(0, dot);
         if (Arrays.binarySearch(INVALID_RESOURCE_BASENAMES, basename.toLowerCase()) >= 0)
            return false;
         return Arrays.binarySearch(INVALID_RESOURCE_FULLNAMES, name.toLowerCase()) < 0;
      }
      return true;
   }
}
5
répondu Nick J. R. T. 2015-03-11 21:10:42

C'est comme ça que j'ai mis en œuvre ceci:

public boolean isValidFileName(final String aFileName) {
    final File aFile = new File(aFileName);
    boolean isValid = true;
    try {
        if (aFile.createNewFile()) {
            aFile.delete();
        }
    } catch (IOException e) {
        isValid = false;
    }
    return isValid;
}
4
répondu Mosty Mostacho 2011-07-27 00:27:52

pour moi, il semble qu'il s'agisse d'un problème dépendant de L'OS. Vous pouvez simplement vérifier certains de caractère non valide dans le nom de fichier. Windows ne ce lorsque vous essayez de renommer le fichier, il affiche un message indiquant qu'un fichier ne peut contenir aucun des caractères suivants: \ / : * ? < > | Je ne suis pas sûr que votre question soit "y a-t-il une bibliothèque qui fait le travail pour moi?"dans ce cas, je ne sais pas tout.

3
répondu svachon 2009-05-21 18:00:53

juste quelque chose que j'ai trouvé, en java 7 et plus tard, il ya une classe appelée Paths qui a une méthode appelée get qui prend un ou plusieurs String s et jette

InvalidPathException - si la chaîne de chemin ne peut pas être convertie en chemin

3
répondu BrainStorm.exe 2015-05-06 20:35:44

utilisant

String validName = URLEncoder.encode( fileName , "UTF-8");

File newFile = new File( validName );

fait le travail.

je viens de trouver aujourd'hui. Je ne suis pas sûr que cela fonctionne 100% du temps, mais jusqu'à présent, j'ai pu créer des noms de fichiers valides.

0
répondu OscarRyz 2009-05-26 17:46:03