FileUtil.java

net.minecraft.util.FileUtil

信息

  • 全限定名:net.minecraft.util.FileUtil
  • 类型:public class
  • 包:net.minecraft.util
  • 源码路径:src/main/java/net/minecraft/util/FileUtil.java
  • 起始行号:L17
  • 职责:

    TODO

字段/常量

  • COPY_COUNTER_PATTERN

    • 类型: Pattern
    • 修饰符: private static final
    • 源码定位: L18
    • 说明:

      TODO

  • MAX_FILE_NAME

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L19
    • 说明:

      TODO

  • RESERVED_WINDOWS_FILENAMES

    • 类型: Pattern
    • 修饰符: private static final
    • 源码定位: L20
    • 说明:

      TODO

  • STRICT_PATH_SEGMENT_CHECK

    • 类型: Pattern
    • 修饰符: private static final
    • 源码定位: L21
    • 说明:

      TODO

内部类/嵌套类型

构造器

方法

下面的方法块按源码顺序生成。

public static String sanitizeName(String baseName) @ L23

  • 方法名:sanitizeName
  • 源码定位:L23
  • 返回类型:String
  • 修饰符:public static

参数:

  • baseName: String

说明:

TODO

public static String findAvailableName(Path baseDir, String baseName, String suffix) @ L31

  • 方法名:findAvailableName
  • 源码定位:L31
  • 返回类型:String
  • 修饰符:public static

参数:

  • baseDir: Path
  • baseName: String
  • suffix: String

说明:

TODO

public static boolean isPathPortable(Path path) @ L73

  • 方法名:isPathPortable
  • 源码定位:L73
  • 返回类型:boolean
  • 修饰符:public static

参数:

  • path: Path

说明:

TODO

public static boolean isPathPartPortable(String name) @ L83

  • 方法名:isPathPartPortable
  • 源码定位:L83
  • 返回类型:boolean
  • 修饰符:public static

参数:

  • name: String

说明:

TODO

public static String getFullResourcePath(String filename) @ L87

  • 方法名:getFullResourcePath
  • 源码定位:L87
  • 返回类型:String
  • 修饰符:public static

参数:

  • filename: String

说明:

TODO

public static String normalizeResourcePath(String filename) @ L91

  • 方法名:normalizeResourcePath
  • 源码定位:L91
  • 返回类型:String
  • 修饰符:public static

参数:

  • filename: String

说明:

TODO

public static DataResult<List<String>> decomposePath(String path) @ L95

  • 方法名:decomposePath
  • 源码定位:L95
  • 返回类型:DataResult<List>
  • 修饰符:public static

参数:

  • path: String

说明:

TODO

public static Path resolvePath(Path root, List<String> segments) @ L135

  • 方法名:resolvePath
  • 源码定位:L135
  • 返回类型:Path
  • 修饰符:public static

参数:

  • root: Path
  • segments: List

说明:

TODO

private static boolean containsAllowedCharactersOnly(String segment) @ L153

  • 方法名:containsAllowedCharactersOnly
  • 源码定位:L153
  • 返回类型:boolean
  • 修饰符:private static

参数:

  • segment: String

说明:

TODO

public static boolean isValidPathSegment(String segment) @ L157

  • 方法名:isValidPathSegment
  • 源码定位:L157
  • 返回类型:boolean
  • 修饰符:public static

参数:

  • segment: String

说明:

TODO

public static void validatePath(String... path) @ L161

  • 方法名:validatePath
  • 源码定位:L161
  • 返回类型:void
  • 修饰符:public static

参数:

  • path: String…

说明:

TODO

public static void createDirectoriesSafe(Path dir) @ L173

  • 方法名:createDirectoriesSafe
  • 源码定位:L173
  • 返回类型:void
  • 修饰符:public static

参数:

  • dir: Path

说明:

TODO

static boolean isEmptyPath(Path path) @ L177

  • 方法名:isEmptyPath
  • 源码定位:L177
  • 返回类型:boolean
  • 修饰符:static

参数:

  • path: Path

说明:

TODO

代码

public class FileUtil {
    private static final Pattern COPY_COUNTER_PATTERN = Pattern.compile("(<name>.*) \\((<count>\\d*)\\)", 66);
    private static final int MAX_FILE_NAME = 255;
    private static final Pattern RESERVED_WINDOWS_FILENAMES = Pattern.compile(".*\\.|(?:COM|CLOCK\\$|CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(?:\\..*)?", 2);
    private static final Pattern STRICT_PATH_SEGMENT_CHECK = Pattern.compile("[-._a-z0-9]+");
 
    public static String sanitizeName(String baseName) {
        for (char replacer : SharedConstants.ILLEGAL_FILE_CHARACTERS) {
            baseName = baseName.replace(replacer, '_');
        }
 
        return baseName.replaceAll("[./\"]", "_");
    }
 
    public static String findAvailableName(Path baseDir, String baseName, String suffix) throws IOException {
        baseName = sanitizeName(baseName);
        if (!isPathPartPortable(baseName)) {
            baseName = "_" + baseName + "_";
        }
 
        Matcher matcher = COPY_COUNTER_PATTERN.matcher(baseName);
        int count = 0;
        if (matcher.matches()) {
            baseName = matcher.group("name");
            count = Integer.parseInt(matcher.group("count"));
        }
 
        if (baseName.length() > 255 - suffix.length()) {
            baseName = baseName.substring(0, 255 - suffix.length());
        }
 
        while (true) {
            String nameToTest = baseName;
            if (count != 0) {
                String countSuffix = " (" + count + ")";
                int length = 255 - countSuffix.length();
                if (baseName.length() > length) {
                    nameToTest = baseName.substring(0, length);
                }
 
                nameToTest = nameToTest + countSuffix;
            }
 
            nameToTest = nameToTest + suffix;
            Path fullPath = baseDir.resolve(nameToTest);
 
            try {
                Path created = Files.createDirectory(fullPath);
                Files.deleteIfExists(created);
                return baseDir.relativize(created).toString();
            } catch (FileAlreadyExistsException var8) {
                count++;
            }
        }
    }
 
    public static boolean isPathPortable(Path path) {
        for (Path part : path) {
            if (!isPathPartPortable(part.toString())) {
                return false;
            }
        }
 
        return true;
    }
 
    public static boolean isPathPartPortable(String name) {
        return !RESERVED_WINDOWS_FILENAMES.matcher(name).matches();
    }
 
    public static String getFullResourcePath(String filename) {
        return FilenameUtils.getFullPath(filename).replace(File.separator, "/");
    }
 
    public static String normalizeResourcePath(String filename) {
        return FilenameUtils.normalize(filename).replace(File.separator, "/");
    }
 
    public static DataResult<List<String>> decomposePath(String path) {
        int segmentEnd = path.indexOf(47);
        if (segmentEnd == -1) {
            return switch (path) {
                case "", ".", ".." -> DataResult.error(() -> "Invalid path '" + path + "'");
                default -> !containsAllowedCharactersOnly(path) ? DataResult.error(() -> "Invalid path '" + path + "'") : DataResult.success(List.of(path));
            };
        } else {
            List<String> result = new ArrayList<>();
            int segmentStart = 0;
            boolean lastSegment = false;
 
            while (true) {
                String segment = path.substring(segmentStart, segmentEnd);
                switch (segment) {
                    case "":
                    case ".":
                    case "..":
                        return DataResult.error(() -> "Invalid segment '" + segment + "' in path '" + path + "'");
                }
 
                if (!containsAllowedCharactersOnly(segment)) {
                    return DataResult.error(() -> "Invalid segment '" + segment + "' in path '" + path + "'");
                }
 
                result.add(segment);
                if (lastSegment) {
                    return DataResult.success(result);
                }
 
                segmentStart = segmentEnd + 1;
                segmentEnd = path.indexOf(47, segmentStart);
                if (segmentEnd == -1) {
                    segmentEnd = path.length();
                    lastSegment = true;
                }
            }
        }
    }
 
    public static Path resolvePath(Path root, List<String> segments) {
        int size = segments.size();
 
        return switch (size) {
            case 0 -> root;
            case 1 -> root.resolve(segments.get(0));
            default -> {
                String[] rest = new String[size - 1];
 
                for (int i = 1; i < size; i++) {
                    rest[i - 1] = segments.get(i);
                }
 
                yield root.resolve(root.getFileSystem().getPath(segments.get(0), rest));
            }
        };
    }
 
    private static boolean containsAllowedCharactersOnly(String segment) {
        return STRICT_PATH_SEGMENT_CHECK.matcher(segment).matches();
    }
 
    public static boolean isValidPathSegment(String segment) {
        return !segment.equals("..") && !segment.equals(".") && containsAllowedCharactersOnly(segment);
    }
 
    public static void validatePath(String... path) {
        if (path.length == 0) {
            throw new IllegalArgumentException("Path must have at least one element");
        } else {
            for (String segment : path) {
                if (!isValidPathSegment(segment)) {
                    throw new IllegalArgumentException("Illegal segment " + segment + " in path " + Arrays.toString((Object[])path));
                }
            }
        }
    }
 
    public static void createDirectoriesSafe(Path dir) throws IOException {
        Files.createDirectories(Files.exists(dir) ? dir.toRealPath() : dir);
    }
 
    static boolean isEmptyPath(Path path) {
        return path.getNameCount() == 1 && path.getFileName().toString().isEmpty();
    }
}

引用的其他类

  • TropicalFish
    • 引用位置: 字段/方法调用
    • 关联成员: Pattern.compile()