Pregunta

En mi aplicación Java, estoy cambiando el nombre de los archivos a un nombre de archivo proporcionado en un parámetro de cadena.Hay un método

boolean OKtoRename(String oldName, String newName)

que básicamente comprueba si el nuevo nombre no está ya en uso en algún otro archivo, ya que no me gustaría enterrar los existentes.

Ahora se me ocurrió que quizás la cadena newName no indique un nombre de archivo válido.Entonces pensé en agregar esta verificación al método:

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

Lo cual obviamente no es la manera correcta de hacerlo, ya que en la mayoría de los casos el newFile aún no existe y por lo tanto aunque es OKtoRename, la función devuelve falso.

Me preguntaba si existe algún método (sé que no existe para los objetos java.io.File) como canExist()?¿O tendría que recurrir a expresiones regulares para asegurarme de que la cadena newFile no contenga caracteres no válidos (p. ej.?, *, ", :)?Me pregunto si tal vez haya una función oculta en algún lugar del JDK que me diga si una cadena podría indicar un nombre de archivo válido.

¿Fue útil?

Solución

createNewFile() , que atómicamente crear el archivo sólo si no existe todavía.

Si se crea el archivo, el nombre es válido y no se clobbering un archivo existente. A continuación, puede abrir los archivos y copiar de manera eficiente los datos de una a la otra con las operaciones FileChannel.transferXXX.

Una cosa importante a tener en cuenta que, en general, la comprobación y la creación deben ser atómicas. Si primero se comprueba si una operación es segura, a continuación, realizar la operación como un paso separado, las condiciones pueden haber cambiado desde entonces, por lo que la operación insegura.

alimento para el pensamiento adicional está disponible en este post relacionado: "operaciones Mover / Copiar en java. "


Actualización:

Desde esta respuesta, se han introducido las API NIO.2, que añaden una mayor interacción con el sistema de archivos.

Suponga que tiene un programa interactivo, y desea validar después de cada golpe de teclado si el archivo es potencialmente válido. Por ejemplo, es posible que desee habilitar un botón "Guardar" sólo cuando la entrada es válida en lugar de aparecer un diálogo de error después de pulsar "Guardar". Crear y asegurar la eliminación de una gran cantidad de archivos innecesarios que mi sugerencia anterior requeriría parece un lío.

Con NIO.2, no se puede crear una instancia de Path que contiene caracteres que son ilegales para el sistema de archivos. Un InvalidPathException se eleva tan pronto como se intenta crear la Path.

Sin embargo, no hay una API para validar nombres ilegales compuestos por caracteres válidos, como "PRN" en Windows. Como solución, la experimentación mostró que el uso de un nombre de archivo sería ilegal provocará una excepción distinta cuando se trata de atributos de acceso (usando Files.getLastModifiedTime(), por ejemplo).

Si especifica un nombre válido para un archivo que no existe, se obtiene no es una excepción.

Si especifica un nombre válido para un archivo que no existe, se plantea NoSuchFileException.

Si especifica un nombre ilegal, se eleva FileSystemException.

Sin embargo, esto parece muy kludgey y podría no ser fiable en otros sistemas operativos.

Otros consejos

Reuní una lista de caracteres de nombres de archivos ilegales (considerando los sistemas UNIX, Mac OS X y Windows) basada en una investigación en línea hace un par de meses.Si el nuevo nombre de archivo contiene alguno de estos, existe el riesgo de que no sea válido en todas las plataformas.

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

EDITAR:Me gustaría recalcar que esto es no es una solución completa:como señaló un comentarista, aunque pase esta prueba, el nombre de su archivo aún podría ser una palabra clave específica de Windows como COM, PRN, etc.Sin embargo, si el nombre de su archivo contiene alguno de estos caracteres, seguramente causará problemas en un entorno multiplataforma.

Aquí sistema de manera específica se sugiere.

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

Si el desarrollo para Eclipse, echa un vistazo a 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;
   }
}

Esta es la forma en que he implementado esto:

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 mi me parece que hay un problema depende del sistema operativo. Simplemente puede desear para comprobar si hay algún carácter no válido en el nombre del archivo. Ventanas hace esto cuando intenta cambiar el nombre del archivo, aparece un mensaje que indica que un archivo no puede contener ninguno de los siguientes caracteres: \ /: *? <> | No estoy seguro de si su pregunta es "¿hay una biblioteca hacer el trabajo para mí?" en ese caso, yo no conozco a ninguna.

Sólo es algo que he encontrado, en Java 7 y versiones posteriores, hay una clase llamada Paths que tiene un llamado get método que toma uno o más Strings y lanza

  

InvalidPathException - si el cadena de ruta no se puede convertir en un camino

Uso

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

File newFile = new File( validName );

¿Funciona.

Me acabo de encontrar hoy en día. No estoy seguro de si funciona el 100% del tiempo, pero hasta ahora, he sido capaz de crear nombres de archivo válidos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top