Подтвердить что ты не робот

Java - Как узнать, действительно ли имя файла?

В моем приложении Java я переименовываю файлы в имя файла, представленное в параметре String. Существует метод

boolean OKtoRename(String oldName, String newName)

который в основном проверяет, не является ли newName еще не каким-то другим файлом, так как я бы не захотел похоронить существующие.

Теперь мне пришло в голову, что, возможно, newName String не будет обозначать допустимое имя файла. Поэтому я решил добавить эту проверку к методу:

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

Очевидно, что это неправильный способ сделать это, так как в большинстве случаев newFile еще не существует и поэтому, хотя это OKtoRename, функция возвращает false.

Мне было интересно, есть ли метод (я знаю, что нет для объектов java.io.File), например canExist()? Или мне придется прибегать к регулярному выражению, чтобы убедиться, что newFile String не содержит недопустимых символов (например?, *, ",:)? Интересно, есть ли какая-то функция, скрытая где-то в JDK, которая скажет мне, если строка может означать действительное имя файла.

4b9b3361

Ответ 1

Используйте createNewFile(), который будет атомизировать файл, только если он еще не существует.

Если файл создан, имя является допустимым и не сбивает существующий файл. Затем вы можете открывать файлы и эффективно копировать данные из одного в другое с помощью операций FileChannel.transferXXX.

Важно помнить, что в общем случае проверка и создание должны быть атомарными. Если вы сначала проверите, безопасна ли операция, затем выполните операцию как отдельный шаг, условия могут быть изменены в то же время, что делает операцию небезопасной.

Дополнительную информацию о пищу можно найти в этой связанной записи: "Операции перемещения/копирования на Java" .


Update:

После этого ответа были введены API NIO.2, которые добавляют больше взаимодействия с файловой системой.

Предположим, что у вас есть интерактивная программа и вы хотите проверить после каждого нажатия клавиши, является ли файл потенциально допустимым. Например, вы можете включить кнопку "Сохранить" только тогда, когда запись будет действительной, а не появится диалоговое окно с сообщением об ошибке после нажатия "Сохранить". Создание и обеспечение удаления большого количества ненужных файлов, которые потребуются моему предложению выше, похоже на беспорядок.

С NIO.2 вы не можете создать экземпляр Path, содержащий символы, которые являются незаконными для файловой системы. InvalidPathException создается, как только вы пытаетесь создать Path.

Однако API не проверяет незаконные имена, состоящие из допустимых символов, таких как "PRN" в Windows. В качестве обходного пути экспериментирование показало, что использование недопустимого имени файла приведет к возникновению отдельного исключения при попытке доступа к атрибутам (например, с помощью Files.getLastModifiedTime()).

Если вы укажете юридическое имя для файла, который существует, вы не получите никакого исключения.

Если вы укажете юридическое имя файла, который не существует, он вызывает NoSuchFileException.

Если вы укажете незаконное имя, FileSystemException будет поднят.

Однако это кажется очень kludgey и может быть ненадежным в других операционных системах.

Ответ 2

Я собрал список незаконных имен файлов (с учетом UNIX, Mac OS X и систем Windows) на основе некоторых онлайн-исследований пару месяцев назад. Если новое имя файла содержит какие-либо из них, существует риск, что он может быть недействительным на всех платформах.

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

EDIT: Я хотел бы подчеркнуть, что это не полное решение: как отметил комментатор, даже несмотря на то, что он прошел этот тест, ваше имя файла все равно может быть ключевым для Windows, например COM, PRN и т.д. Однако, если ваше имя файла содержит любой из этих символов, это, безусловно, вызовет проблемы в межплатформенной среде.

Ответ 4

Вот как я это сделал:

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

Ответ 5

Если вы разрабатываете для Eclipse, проверьте 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

Мне кажется, что это проблема, зависящая от ОС. Вы можете просто захотеть проверить наличие недопустимого символа в имени файла. Windows делает это при попытке переименования файла, появляется сообщение о том, что файл не может содержать ни один из следующих символов: \/: *? < > | Я не уверен, что ваш вопрос: "Есть ли библиотека для меня?" в этом случае я не знаю.

Ответ 7

Просто что-то я нашел, в java 7 и более поздних версиях существует класс под названием Paths, у которого есть метод под названием get, который принимает один или несколько String и бросает

InvalidPathException - если строка пути не может быть преобразована в Path

Ответ 8

Используя

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

File newFile = new File( validName );

Работает ли.

Я только что нашел сегодня. Я не уверен, работает ли он в 100% случаев, но до сих пор мне удалось создать правильные имена файлов.