Domanda

Nella mia applicazione Java sto rinominando i file con un nome file fornito in un parametro String.C'è un metodo

boolean OKtoRename(String oldName, String newName)

che fondamentalmente controlla se newName non è già preso da qualche altro file, poiché non vorrei seppellire quelli esistenti.

Ora mi è venuto in mente che forse la stringa newName non indicherà un nome di file valido.Quindi ho pensato di aggiungere questo controllo al metodo:

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

Il che ovviamente non è il modo giusto, poiché nella maggior parte dei casi il newFile non esiste ancora e quindi pur essendo È OKtoRename, la funzione restituisce false.

Mi chiedevo, esiste un metodo (so che non esiste per gli oggetti java.io.File) come canExist()?Oppure dovrei ricorrere alla regex per assicurarmi che la newFile String non contenga caratteri non validi (ad es.?, *, ", :)?Mi chiedo se ci sia forse una funzione nascosta da qualche parte nel JDK che mi direbbe se una stringa potrebbe denotare un nome di file valido.

È stato utile?

Soluzione

createNewFile() , che atomicamente creare il file solo se non esiste ancora.

Se il file viene creato, il nome è valido e non è clobbering un file esistente. È quindi possibile aprire i file in modo efficiente e copiare i dati da uno all'altro con le operazioni FileChannel.transferXXX.

Una cosa importante da tenere a mente che, in generale, il controllo e la creazione dovrebbe essere atomica. Se si seleziona prima se un'operazione è sicuro, quindi eseguire l'operazione in una fase successiva, le condizioni possono essere cambiate nel frattempo, rendendo l'operazione non sicuro.

cibo supplementare di riflessione è disponibile a questo post correlati: "operazioni Sposta / Copia in Java. "


Aggiornamento:

Da questa risposta, sono state introdotte le API NIO.2, che aggiungono una maggiore interazione con il file system.

Supponiamo di avere un programma interattivo, e desidera convalidare dopo ogni pressione del tasto se il file è potenzialmente valido. Ad esempio, si potrebbe desiderare di attivare un pulsante "Salva" solo quando la voce è valida piuttosto che spuntando una finestra di errore dopo aver premuto "Salva". Creazione e garantire l'eliminazione di un sacco di file inutili che il mio suggerimento sopra richiederebbe sembra un pasticcio.

Con NIO.2, non è possibile creare un'istanza Path contenente caratteri non validi per il file system. Un InvalidPathException è sollevata, non appena si tenta di creare il Path.

Tuttavia, non v'è un'API per convalidare i nomi illegali composti da caratteri validi, come "PRN" su Windows. Per risolvere il problema, la sperimentazione ha dimostrato che l'utilizzo di un nome di file illegale avrebbe sollevato un'eccezione distinta quando si cerca di attributi di accesso (usando Files.getLastModifiedTime(), per esempio).

Se si specifica un nome legale per un file che non esiste, si ottiene non fa eccezione.

Se si specifica un nome legale per un file che non esiste, che solleva NoSuchFileException.

Se si specifica un nome illegale, FileSystemException è sollevata.

Tuttavia, questo sembra molto kludgey e potrebbe non essere attendibile su altri sistemi operativi.

Altri suggerimenti

Ho messo insieme un elenco di caratteri illegali nei nomi di file (considerando i sistemi UNIX, Mac OS X e Windows) sulla base di alcune ricerche online un paio di mesi fa.Se il nuovo nome file contiene uno di questi elementi, c'è il rischio che non sia valido su tutte le piattaforme.

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

MODIFICARE:Vorrei sottolineare che è così non una soluzione completa:come ha sottolineato un commentatore, anche se supera questo test, il nome del tuo file potrebbe comunque essere una parola chiave specifica di Windows come COM, PRN, ecc.Tuttavia, se il nome del tuo file contiene uno di questi caratteri, causerà sicuramente problemi in un ambiente multipiattaforma.

Qui sistema modo specifico è suggerito.

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

Se in via di sviluppo per Eclipse, il check out 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;
   }
}

Questo è come ho implementato questo:

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

A me sembra che vi sia un problema di dipendenza del sistema operativo. Si può semplicemente voler controllare per qualche carattere non valido nel nome del file. Di Windows fa questo quando si tenta di rinominare il file, si apre un messaggio che dice che un file non può contenere i seguenti caratteri: \ /: *? <> | Io non sono sicuro se la tua domanda è "c'è una biblioteca a fare il lavoro per me?" in quel caso io non conosco nessuna.

Solo qualcosa che ho trovato, in Java 7 e versioni successive, c'è una classe chiamata Paths che ha un metodo chiamato get ne servono uno o più Stringse lancia

InvalidPathException - se la stringa del percorso non può essere convertita in un percorso

con

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

File newFile = new File( validName );

fa il lavoro.

Ho appena trovato oggi. Non sono sicuro se funziona al 100% del tempo, ma finora, sono stato in grado di creare i nomi di file validi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top