Question

    

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

         

Dans mon application Java je suis renommage de fichiers à un nom de fichier fourni dans un paramètre de chaîne. Il existe une méthode

boolean OKtoRename(String oldName, String newName)

qui vérifie essentiellement si le newName est pas déjà pris par un autre fichier, comme je ne voudrais pas enterrer ceux qui existent déjà.

Il maintenant me est apparu que peut-être la chaîne newName ne sera pas indiquer un nom de fichier valide. Donc je pensais que d'ajouter ce chèque à la méthode:

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

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

Je me demandais, est-il une méthode (je sais qu'il n'y a pas pour les objets java.io.File) comme canExist()? Ou devrais-je avoir recours à regex pour vous assurer que la chaîne newFile ne contient pas de caractères non valides (par exemple?, *, », :) Je me demande s'il y a peut-être une fonction cachée quelque part dans le JDK qui pourrait me dire si une chaîne pourrait éventuellement indiquer un nom de fichier valide.

Était-ce utile?

La solution

Utilisez createNewFile() , qui atomiquement créer le fichier que si elle n'existe pas encore.

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

Une chose importante à garder à l'esprit que, en général, le contrôle et la création devrait être atomique. Si vous vérifiez d'abord si une opération est en sécurité, puis effectuez l'opération comme une étape distincte, les conditions peuvent avoir changé entre-temps, ce qui rend l'opération dangereuse.

nourriture supplémentaire pour la pensée est disponible à ce poste lié: "opérations Déplacer / Copier dans Java. "


Mise à jour:

Depuis cette réponse, les API NIO.2 ont été introduites, qui ajoutent plus d'interaction avec le système de fichiers.

Supposons que vous ayez un programme interactif, et que vous voulez valider chaque pression de touche si le fichier est potentiellement valide. Par exemple, vous pouvez activer un « Enregistrer » uniquement lorsque l'entrée est valide plutôt que d'apparaître une boîte de dialogue d'erreur après avoir appuyé sur « Enregistrer ». Création et assurer la suppression d'un grand nombre de fichiers inutiles que ma suggestion nécessiterait ci-dessus semble comme un gâchis.

Avec NIO.2, vous ne pouvez pas créer une instance de Path contenant des caractères qui sont illégales pour le système de fichiers. Un InvalidPathException est soulevée dès que vous essayez de créer le Path.

Cependant, il n'y a pas une API pour valider les noms illégaux composées de caractères valides, comme « PRN » sous Windows. Pour contourner ce problème, l'expérimentation a montré que l'utilisation d'un nom de fichier illégal soulèverait une exception distincte lorsque vous essayez d'attributs d'accès (en utilisant Files.getLastModifiedTime(), par exemple).

Si vous spécifiez un nom légal pour un fichier qui existe, vous obtenez pas 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 élevé.

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

Autres conseils

Je dressé une liste de caractères de noms de fichiers illégaux (considérant systèmes UNIX, Mac OS X et Windows) basé sur des recherches en ligne il y a quelques mois. Si le nouveau nom de fichier contient toutes ces choses, il y a un risque que cela pourrait ne pas être valide sur toutes les plateformes.

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

EDIT: Je voudrais souligner que ceci est pas une solution complète : comme commentateur a fait remarquer, 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. Toutefois, si votre nom de fichier contient un de ces caractères, il va certainement causer des problèmes dans un environnement multi-plateforme.

ici de manière spécifique le système est suggéré.

public static boolean isFilenameValid(String file) {
  File f = new File(file);
  try {
    f.getCanonicalPath();
    return true;
  } catch (IOException e) {
    return false;
  }
}

Si le développement d'Eclipse, consultez 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[] {'/', '\0',};
         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;
   }
}

Voici comment je mis en œuvre cette:

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

Pour moi, il semble y avoir un problème dépendant du système d'exploitation. Vous voudrez peut-être simplement de vérifier un certain caractère non valide dans le nom du fichier. Windows fait cela 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 sais pas si votre question est « est-il une bibliothèque faire le travail pour moi? » dans ce cas, je ne sais pas.

Juste quelque chose que je trouve, en Java 7 et plus tard, il y a une classe appelée Paths qui a une méthode appelée get qui prend un ou plusieurs Strings et jette

  

InvalidPathException - si le chaîne de chemin ne peut pas être converti en un chemin

Utilisation

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

File newFile = new File( validName );

Est-ce que le travail.

Je viens d'aujourd'hui. Je ne sais pas si cela fonctionne 100% du temps, mais jusqu'à présent, je suis en mesure de créer des noms de fichiers valides.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top