developer tip

Java에서 파일을 만들지 않고 경로가 유효한지 확인하는 방법이 있습니까?

copycodes 2020. 11. 15. 11:26
반응형

Java에서 파일을 만들지 않고 경로가 유효한지 확인하는 방법이 있습니까?


사용자가 제공 한 문자열이 유효한 파일 경로인지 (즉, createNewFile()성공하거나 예외가 발생하는 경우) 확인해야하지만 유효성 검사 목적으로 생성 된 쓸모없는 파일로 파일 시스템을 부풀리고 싶지 않습니다.

파일을 만들지 않고 내가 가지고있는 문자열이 유효한 파일 경로인지 확인하는 방법이 있습니까?

"유효한 파일 경로"의 정의는 OS에 따라 다르지만을 수락 C:/foo하거나 /foo거부하는 빠른 방법이 있는지 궁금합니다 banana.

가능한 접근 방식은 파일 생성을 시도하고 생성이 성공하면 결국 삭제하는 것일 수 있지만 동일한 결과를 얻는 더 우아한 방법이 있기를 바랍니다.


이것은 디렉토리의 존재 여부도 확인합니다.

File file = new File("c:\\cygwin\\cygwin.bat");
if (!file.isDirectory())
   file = file.getParentFile();
if (file.exists()){
    ...
}

file.canWrite ()는 디렉토리에 쓸 수있는 권한이있는 경우 명확한 표시를 제공하지 않는 것 같습니다.


Java 7에 도입 된 Path 클래스는 다음과 같은 새로운 대안을 추가합니다.
( Linux에서 제대로 작동하지 않음 -항상 true를 반환 함)

/**
 * <pre>
 * Checks if a string is a valid path.
 * Null safe.
 *  
 * Calling examples:
 *    isValidPath("c:/test");      //returns true
 *    isValidPath("c:/te:t");      //returns false
 *    isValidPath("c:/te?t");      //returns false
 *    isValidPath("c/te*t");       //returns false
 *    isValidPath("good.txt");     //returns true
 *    isValidPath("not|good.txt"); //returns false
 *    isValidPath("not:good.txt"); //returns false
 * </pre>
 */
public static boolean isValidPath(String path) {
    try {
        Paths.get(path);
    } catch (InvalidPathException | NullPointerException ex) {
        return false;
    }
    return true;
}

File.getCanonicalPath()이 목적에 매우 유용합니다. IO 예외는 유효하지 않은 파일 이름의 특정 유형 던져진다 (예를 들면 CON, PRN, *?*Windows의) OS 나 파일 시스템에 대해 확인할 때. 그러나 이것은 예비 점검으로 만 사용됩니다. 실제로 파일을 만들 때 다른 오류를 처리해야합니다 (예 : 권한 부족, 드라이브 공간 부족, 보안 제한).


파일을 만들 때 여러 가지 문제가 발생할 수 있습니다.

  • 필요한 권한이 없습니다.
  • 장치에 공간이 충분하지 않습니다.
  • 장치에 오류가 발생했습니다.
  • 사용자 정의 보안의 일부 정책은 특정 유형의 파일을 생성하는 것을 금지합니다.
  • 기타

요컨대, 가능 여부를 확인하기 위해 시도하고 쿼리 할 때와 실제로 가능할 때 사이에 변경 될 수 있습니다. 다중 스레드 환경에서 이것은 경쟁 조건의 주요 원인 중 하나이며 일부 프로그램의 실제 취약점이 될 수 있습니다.

기본적으로 시도하고 생성하고 작동하는지 확인해야합니다. 이것이 올바른 방법입니다. 일을 좋아하는 이유입니다 ConcurrentHashMapputIfAbsent()체크 및 삽입 원자 작업입니다 및 경쟁 조건으로 고생하지 않도록. 정확히 동일한 원칙이 여기에 적용됩니다.

이것이 진단 또는 설치 프로세스의 일부인 경우 수행하고 작동하는지 확인하십시오. 그러나 나중에 작동한다는 보장은 없습니다.

기본적으로 프로그램은 관련 파일을 작성할 수없는 경우 정상적으로 종료 될 수있을만큼 견고해야합니다.


boolean canWrite(File file) {
  if (file.exists()) {
    return file.canWrite();
  }
  else {
    try {
      file.createNewFile();
      file.delete();
      return true;
    }
    catch (Exception e) {
      return false;
    }
  }
}

운영 체제에서 작동하는 작업을 수행 할 수 있습니다.

정규식 일치를 사용하여 기존의 알려진 잘못된 문자를 확인합니다.

if (newName.matches(".*[/\n\r\t\0\f`?*\\<>|\":].*")) {
    System.out.println("Invalid!");
} else {
    System.out.println("Valid!");
}

장점

  • 이것은 운영 체제에서 작동합니다.
  • 해당 정규식을 편집하여 원하는 방식으로 사용자 정의 할 수 있습니다.

단점

  • 이것은 완전한 목록이 아닐 수 있으며 더 잘못된 패턴이나 문자를 채우기 위해 더 많은 연구가 필요합니다.

그냥하세요 (그리고 스스로 청소하세요)

가능한 접근 방식은 파일 생성을 시도하고 생성이 성공하면 결국 삭제하는 것일 수 있지만 동일한 결과를 얻는 더 우아한 방법이 있기를 바랍니다.

아마도 가장 강력한 방법 일 것입니다.

Below is canCreateOrIsWritable that determines whether your program is able to create a file and its parent directories at a given path, or, if there's already a file there, write to it.

It does so by actually creating the necessary parent directories as well as an empty file at the path. Afterwards, it deletes them (if there existed a file at the path, it's left alone).

Here's how you might use it:

var myFile = new File("/home/me/maybe/write/here.log")

if (canCreateOrIsWritable(myFile)) {
    // We're good. Create the file or append to it
    createParents(myFile);
    appendOrCreate(myFile, "new content");
} else {
    // Let's pick another destination. Maybe the OS's temporary directory:
    var tempDir = System.getProperty("java.io.tmpdir");
    var alternative = Paths.get(tempDir, "second_choice.log");
    appendOrCreate(alternative, "new content in temporary directory");
}

The essential method with a few helper methods:

static boolean canCreateOrIsWritable(File file) {
    boolean canCreateOrIsWritable;

    // The non-existent ancestor directories of the file.
    // The file's parent directory is first
    List<File> parentDirsToCreate = getParentDirsToCreate(file);

    // Create the parent directories that don't exist, starting with the one
    // highest up in the file system hierarchy (closest to root, farthest
    // away from the file)
    reverse(parentDirsToCreate).forEach(File::mkdir);

    try {
        boolean wasCreated = file.createNewFile();
        if (wasCreated) {
            canCreateOrIsWritable = true;
            // Remove the file and its parent dirs that didn't exist before
            file.delete();
            parentDirsToCreate.forEach(File::delete);
        } else {
            // There was already a file at the path → Let's see if we can
            // write to it
            canCreateOrIsWritable = java.nio.file.Files.isWritable(file.toPath());
        }
    } catch (IOException e) {
        // File creation failed
        canCreateOrIsWritable = false;
    }
    return canCreateOrIsWritable;
}

static List<File> getParentDirsToCreate(File file) {
    var parentsToCreate = new ArrayList<File>();
    File parent = file.getParentFile();
    while (parent != null && !parent.exists()) {
        parentsToCreate.add(parent);

        parent = parent.getParentFile();
    }
    return parentsToCreate;
}

static <T> List<T> reverse(List<T> input) {
    var reversed = new ArrayList<T>();
    for (int i = input.size() - 1; i >= 0; i--) {
        reversed.add(input.get(i));
    }
    return reversed;
}

static void createParents(File file) {
    File parent = file.getParentFile();
    if (parent != null) {
        parent.mkdirs();
    }
}

Keep in mind that between calling canCreateOrIsWritable and creating the actual file, the contents and permissions of your file system might have changed.

참고URL : https://stackoverflow.com/questions/468789/is-there-a-way-in-java-to-determine-if-a-path-is-valid-without-attempting-to-cre

반응형