webentwicklung-frage-antwort-db.com.de

Java - Wie finde ich heraus, ob ein Dateiname gültig ist?

In meiner Java-Anwendung benenne ich Dateien in einen Dateinamen um, der in einem String-Parameter angegeben ist. Es gibt eine Methode

boolean OKtoRename(String oldName, String newName)

im Grunde wird geprüft, ob der newName nicht bereits von einer anderen Datei übernommen wurde, da ich die vorhandenen nicht begraben möchte.

Nun kam mir der Gedanke, dass der newName-String möglicherweise keinen gültigen Dateinamen angibt. Also dachte ich mir, diese Prüfung der Methode hinzuzufügen:

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

Was natürlich nicht der richtige Weg ist, da das newFile in den meisten Fällen noch nicht existiert, und obwohl OKtoRename ist, liefert die Funktion false.

Ich habe mich gefragt, gibt es eine Methode (ich weiß, dass es keine Java.io.File-Objekte gibt) wie canExist()? Oder müsste ich auf Regex zurückgreifen, um sicherzustellen, dass der newFile-String keine ungültigen Zeichen enthält (z. B.?, *, ", :)? Ich frage mich, ob in der JDK möglicherweise eine Funktion versteckt ist, die mir sagt, ob ein String vorhanden ist könnte möglicherweise einen gültigen Dateinamen angeben.

48
Peter Perháč

Verwenden Sie createNewFile() , um die Datei nur dann atomar zu erstellen, wenn sie noch nicht vorhanden ist. 

Wenn die Datei erstellt wird, ist der Name gültig und blockiert keine vorhandene Datei. Sie können dann die Dateien öffnen und Daten effizient mit FileChannel.transferXXX-Vorgängen von einem zum anderen kopieren.

Es ist wichtig zu wissen, dass Check und Schöpfung generell atomar sein sollten. Wenn Sie zuerst prüfen, ob eine Operation sicher ist, führen Sie die Operation als separaten Schritt durch. Möglicherweise haben sich die Bedingungen inzwischen geändert, was die Operation unsicher macht.

Weitere Denkanstöße finden Sie in diesem zugehörigen Beitrag: "Verschieben/Kopieren von Vorgängen in Java".


Update:

Seit dieser Antwort wurden die NIO.2-APIs eingeführt, die mehr Interaktion mit dem Dateisystem hinzufügen.

Angenommen, Sie haben ein interaktives Programm und möchten nach jedem Tastendruck prüfen, ob die Datei möglicherweise gültig ist. Beispielsweise möchten Sie die Schaltfläche "Speichern" nur aktivieren, wenn der Eintrag gültig ist, anstatt nach dem Klicken auf "Speichern" einen Fehlerdialogfeld aufzurufen. Das Erstellen und das Löschen vieler unnötiger Dateien, die mein Vorschlag oben erfordern würde, scheint ein Durcheinander zu sein.

Mit NIO.2 können Sie keine Path-Instanz erstellen, die Zeichen enthält, die für das Dateisystem nicht zulässig sind. Eine InvalidPathException wird ausgelöst, sobald Sie versuchen, die Path zu erstellen.

Es gibt jedoch keine API zum Überprüfen ungültiger Namen, die aus gültigen Zeichen bestehen, wie "PRN" unter Windows. Experimentelle Versuche haben gezeigt, dass die Verwendung eines ungültigen Dateinamens beim Zugriff auf Attribute (z. B. mit Files.getLastModifiedTime()) eine eindeutige Ausnahme auslöst. 

Wenn Sie einen gültigen Namen für eine vorhandene Datei angeben, erhalten Sie keine Ausnahme. 

Wenn Sie einen rechtmäßigen Namen für eine Datei angeben, die nicht vorhanden ist, wird NoSuchFileException ausgelöst. 

Wenn Sie einen ungültigen Namen angeben, wird FileSystemException ausgelöst. 

Dies scheint jedoch sehr kludgey zu sein und ist unter anderen Betriebssystemen möglicherweise nicht zuverlässig. 

23
erickson

Ich habe eine Liste illegaler Dateinamen (unter Berücksichtigung von UNIX-, Mac OS X- und Windows-Systemen) auf der Grundlage einiger Online-Recherchen vor ein paar Monaten zusammengestellt. Wenn der neue Dateiname einen dieser Werte enthält, besteht das Risiko, dass er möglicherweise nicht auf allen Plattformen gültig ist.

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

EDIT: Ich möchte betonen, dass dies keine vollständige Lösung ist : Wie ein Kommentator darauf hinweist, könnte Ihr Dateiname, obwohl er diesen Test besteht, ein Windows-spezifisches Schlüsselwort sein COM, PRN usw. Wenn Ihr Dateiname jedoch eines dieser Zeichen enthält, führt dies in einer plattformübergreifenden Umgebung zu Problemen.

58
Zsolt Török

Hier wird systemspezifische Art vorgeschlagen.

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

Wenn Sie für Eclipse entwickeln, überprüfen Sie 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;
   }
}
6
Nick J. R. T.

So habe ich das umgesetzt:

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
Mosty Mostacho

Für mich scheint es ein vom Betriebssystem abhängiges Problem zu sein. Möglicherweise möchten Sie einfach nach ungültigen Zeichen im Dateinamen suchen. Wenn Sie versuchen, die Datei umzubenennen, öffnet Windows eine Meldung, dass eine Datei keine der folgenden Zeichen enthalten darf:\/: *? <> | Ich bin nicht sicher, ob Ihre Frage lautet: "Gibt es eine Bibliothek, die die Arbeit für mich erledigt?" In diesem Fall kenne ich keine.

3
svachon

Nur etwas, was ich in Java 7 und später gefunden habe, gibt es eine Klasse namens Paths , die eine Methode namens get hat, die eine oder mehrere Strings braucht und löst

InvalidPathException - wenn die Pfadzeichenfolge nicht in einen Pfad konvertiert werden kann

3
BrainStorm.exe

Verwenden 

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

File newFile = new File( validName );

Macht die Arbeit 

Ich habe es gerade heute gefunden. Ich bin nicht sicher, ob es 100% der Zeit funktioniert, aber bisher konnte ich gültige Dateinamen erstellen. 

0
OscarRyz