Spring源码深度解析(郝佳)-学习-路径解析-cleanPath

20 篇文章 1 订阅
18 篇文章 0 订阅
public class SpringTest1_3 {

    private static final String FOLDER_SEPARATOR = "/";

    private static final String WINDOWS_FOLDER_SEPARATOR = "\\";

    private static final String TOP_PATH = "..";

    private static final String CURRENT_PATH = ".";

    private static final char EXTENSION_SEPARATOR = '.';

    public static void main(String[] args) {
        String a = "f/../../a/b/c/../../spring_test3.xml";
        System.out.println(cleanPath(a));
    }

    public static String cleanPath(String path) {
        if (path == null) {
            return null;
        }
        // 将所有的 \\ 替换成 / ,window 中的路径可能以 \\ 分隔 ,mac 或者 linux 路径分隔一般以 / 来分隔
        String pathToUse = replace(path, "\\", "/");
        // 如果有 classpath: 或 file: 等,将前缀保留下来
        int prefixIndex = pathToUse.indexOf(":");
        String prefix = "";
        if (prefixIndex != -1) {
            // 如果字符串中包含 :
            prefix = pathToUse.substring(0, prefixIndex + 1);
            if (prefix.contains("/")) {
                // 如果前缀中包含 /
                prefix = "";
            }
            else {
                // 如果前缀中不包含 / ,则截取前缀保留 ,不做计算
                pathToUse = pathToUse.substring(prefixIndex + 1);
            }
        }

        if (pathToUse.startsWith("/")) {
            // 如果去除前缀classpath: 的pathToUse 以 / 开头 ,classpath:/spring_1_100\config_1_10/spring_test1/./a/b/c/../../spring_test3.xml
            prefix = prefix + "/";
            pathToUse = pathToUse.substring(1);
        }

        // 以 / 分隔得到字符串数组
        String[] pathArray = delimitedListToStringArray(pathToUse, "/");
        List pathElements = new LinkedList();
        int tops = 0;
        // 反序遍历
        for (int i = pathArray.length - 1; i >= 0; i--) {
            String element = pathArray[i];
            // 如果 pathArray[i] 是 . 则直接略过
            if (".".equals(element)) {

            }
            else if ("..".equals(element)) {
                // 如果pathArray[i] 是 .. 则 top ++
                tops++;
            }
            else {
                if (tops > 0) {
                    // 抵消掉路径 , 比如 config_1_10/spring_test1/./a/b/c/../../spring_test3.xml 当找到第一个 .. ,top = 1
                    // 第二个 .. 时,top =2 ,当循环到 c 时,top = 2 ,让 top -- ,top = 1 ,抵消掉 c,
                    // 从后面向前查找,查找到第二个 .. 抵消掉 c ,第一个 .. 则抵消掉 b .
                    tops--;
                }
                else {
                    // 如果没有 .. 抵消,直接保存到集合中
                    pathElements.add(0, element);
                }
            }
        }
        // 如果 .. 没有被抵消完全,在集合开头加上 ..
        // f/../../a/b/c/../../spring_test3.xml 解析成 ../a/spring_test3.xml
        for (int i = 0; i < tops; i++) {
            pathElements.add(0, "..");
        }
        // 将之前保留的前缀加到开头,同时对集合中的每个元素以 / 分隔
        return prefix + collectionToDelimitedString(pathElements, "/");
    }
    public static String collectionToDelimitedString(Collection<?> coll, String delim) {
        return collectionToDelimitedString(coll, delim, "", "");
    }


    public static String collectionToDelimitedString(Collection<?> coll, String delim, String prefix, String suffix) {
        if (CollectionUtils.isEmpty(coll)) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        Iterator<?> it = coll.iterator();
        while (it.hasNext()) {
            sb.append(prefix).append(it.next()).append(suffix);
            if (it.hasNext()) {
                sb.append(delim);
            }
        }
        return sb.toString();
    }

    public static String[] delimitedListToStringArray(String str, String delimiter) {
        return delimitedListToStringArray(str, delimiter, null);
    }

    public static String[] delimitedListToStringArray(String str, String delimiter, String charsToDelete) {
        if (str == null) {
            return new String[0];
        }
        if (delimiter == null) {
            return new String[] {str};
        }
        List result = new ArrayList();
        if ("".equals(delimiter)) {
            for (int i = 0; i < str.length(); i++) {
                result.add(deleteAny(str.substring(i, i + 1), charsToDelete));
            }
        }
        else {
            int pos = 0;
            int delPos;
            while ((delPos = str.indexOf(delimiter, pos)) != -1) {
                result.add(deleteAny(str.substring(pos, delPos), charsToDelete));
                pos = delPos + delimiter.length();
            }
            if (str.length() > 0 && pos <= str.length()) {

                result.add(deleteAny(str.substring(pos), charsToDelete));
            }
        }
        return toStringArray(result);
    }
    public static String[] toStringArray(Collection collection) {
        if (collection == null) {
            return null;
        }
        return collection.toArray(new String[collection.size()]);
    }

    public static String deleteAny(String inString, String charsToDelete) {
        if (!hasLength(inString) || !hasLength(charsToDelete)) {
            return inString;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < inString.length(); i++) {
            char c = inString.charAt(i);
            if (charsToDelete.indexOf(c) == -1) {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    public static String replace(String inString, String oldPattern, String newPattern) {
        if (!hasLength(inString) || !hasLength(oldPattern) || newPattern == null) {
            return inString;
        }
        StringBuilder sb = new StringBuilder();
        int pos = 0;
        int index = inString.indexOf(oldPattern);

        int patLen = oldPattern.length();
        while (index >= 0) {
            sb.append(inString.substring(pos, index));
            sb.append(newPattern);
            pos = index + patLen;
            index = inString.indexOf(oldPattern, pos);
        }
        sb.append(inString.substring(pos));
        return sb.toString();
    }

    public static boolean hasLength(CharSequence str) {
        return (str != null && str.length() > 0);
    }
}

结果输出:
…/a/spring_test3.xml

网上有人总结【因为是在循环体内,按照tokens的数量,逐个发现并试图逐个抵消“. ./”,这可能会存在的一个问题是,tokens不够“抵消”。比如"/a/. ./. ./b.xml",需要抵消两次,但最多允许抵消一次(“a/”),但上述循环体内的处理对此无能为力,最终处理成为只剩下b.xml了,这肯定不是想要的结果。但有一点可以肯定的是,如果是绝对路径并且正确,就一定不会存在这个问题;但如果是相对路径,用此就需要格外小心了!或许想方设法将相对路径转为绝对路径不失为上策。】

本文的 github 地址
https://github.com/quyixiao/spring_tiny/blob/master/src/main/java/com/spring_1_100/test_1_10/test/SpringTest1_3.java

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值