java路径 url_如何从两个绝对路径(或URL)构造Java中的相对路径?

在编写本报告时(2010年6月),这是通过我的测试用例的唯一解决方案。我不能保证这个解决方案是没有错误的,但是它确实通过了包含的测试用例。我编写的方法和测试依赖于FilenameUtils来自ApacheCommonsIO.

该解决方案在Java1.4中进行了测试。如果使用Java1.5(或更高版本),则应考虑替换StringBuffer带着StringBuilder(如果您仍然在使用Java1.4,则应该考虑更换雇主)。import java.io.File;import java.util.regex.Pattern;import org.apache.commons.io.FilenameUtils;public class ResourceUtils {

/**

* Get the relative path from one file to another, specifying the directory separator.

* If one of the provided resources does not exist, it is assumed to be a file unless it ends with '/' or

* '\'.

*

* @param targetPath targetPath is calculated to this file

* @param basePath basePath is calculated from this file

* @param pathSeparator directory separator. The platform default is not assumed so that we can test Unix behaviour

when running on Windows (for example)

* @return

*/

public static String getRelativePath(String targetPath, String basePath, String pathSeparator) {

// Normalize the paths

String normalizedTargetPath = FilenameUtils.normalizeNoEndSeparator(targetPath);

String normalizedBasePath = FilenameUtils.normalizeNoEndSeparator(basePath);

// Undo the changes to the separators made by normalization

if (pathSeparator.equals("/")) {

normalizedTargetPath = FilenameUtils.separatorsToUnix(normalizedTargetPath);

normalizedBasePath = FilenameUtils.separatorsToUnix(normalizedBasePath);

} else if (pathSeparator.equals("\\")) {

normalizedTargetPath = FilenameUtils.separatorsToWindows(normalizedTargetPath);

normalizedBasePath = FilenameUtils.separatorsToWindows(normalizedBasePath);

} else {

throw new IllegalArgumentException("Unrecognised dir separator '" + pathSeparator + "'");

}

String[] base = normalizedBasePath.split(Pattern.quote(pathSeparator));

String[] target = normalizedTargetPath.split(Pattern.quote(pathSeparator));

// First get all the common elements. Store them as a string,

// and also count how many of them there are.

StringBuffer common = new StringBuffer();

int commonIndex = 0;

while (commonIndex 

&& target[commonIndex].equals(base[commonIndex])) {

common.append(target[commonIndex] + pathSeparator);

commonIndex++;

}

if (commonIndex == 0) {

// No single common path element. This most

// likely indicates differing drive letters, like C: and D:.

// These paths cannot be relativized.

throw new PathResolutionException("No common path element found for '" + normalizedTargetPath + "' and '" +

normalizedBasePath                    + "'");

}

// The number of directories we have to backtrack depends on whether the base is a file or a dir

// For example, the relative path from

//

// /foo/bar/baz/gg/ff to /foo/bar/baz

//

// ".." if ff is a file

// "../.." if ff is a directory

//

// The following is a heuristic to figure out if the base refers to a file or dir. It's not perfect, because

// the resource referred to by this path may not actually exist, but it's the best I can do

boolean baseIsFile = true;

File baseResource = new File(normalizedBasePath);

if (baseResource.exists()) {

baseIsFile = baseResource.isFile();

} else if (basePath.endsWith(pathSeparator)) {

baseIsFile = false;

}

StringBuffer relative = new StringBuffer();

if (base.length != commonIndex) {

int numDirsUp = baseIsFile ? base.length - commonIndex - 1 : base.length - commonIndex;

for (int i = 0; i 

relative.append(".." + pathSeparator);

}

}

relative.append(normalizedTargetPath.substring(common.length()));

return relative.toString();

}

static class PathResolutionException extends RuntimeException {

PathResolutionException(String msg) {

super(msg);

}

}    }

通过的测试用例是public void testGetRelativePathsUnix() {

assertEquals("stuff/xyz.dat", ResourceUtils.getRelativePath("/var/data/stuff/xyz.dat", "/var/data/", "/"));

assertEquals("../../b/c", ResourceUtils.getRelativePath("/a/b/c", "/a/x/y/", "/"));

assertEquals("../../b/c", ResourceUtils.getRelativePath("/m/n/o/a/b/c", "/m/n/o/a/x/y/", "/"));

}public void testGetRelativePathFileToFile() {

String target = "C:\\Windows\\Boot\\Fonts\\chs_boot.ttf";

String base = "C:\\Windows\\Speech\\Common\\sapisvr.exe";

String relPath = ResourceUtils.getRelativePath(target, base, "\\");

assertEquals("..\\..\\Boot\\Fonts\\chs_boot.ttf", relPath);}public void testGetRelativePathDirectoryToFile() {

String target = "C:\\Windows\\Boot\\Fonts\\chs_boot.ttf";

String base = "C:\\Windows\\Speech\\Common\\";

String relPath = ResourceUtils.getRelativePath(target, base, "\\");

assertEquals("..\\..\\Boot\\Fonts\\chs_boot.ttf", relPath);}public void testGetRelativePathFileToDirectory() {

String target = "C:\\Windows\\Boot\\Fonts";

String base = "C:\\Windows\\Speech\\Common\\foo.txt";

String relPath = ResourceUtils.getRelativePath(target, base, "\\");

assertEquals("..\\..\\Boot\\Fonts", relPath);}public void testGetRelativePathDirectoryToDirectory() {

String target = "C:\\Windows\\Boot\\";

String base = "C:\\Windows\\Speech\\Common\\";

String expected = "..\\..\\Boot";

String relPath = ResourceUtils.getRelativePath(target, base, "\\");

assertEquals(expected, relPath);}public void testGetRelativePathDifferentDriveLetters() {

String target = "D:\\sources\\recovery\\RecEnv.exe";

String base = "C:\\Java\\workspace\\AcceptanceTests\\Standard test data\\geo\\";

try {

ResourceUtils.getRelativePath(target, base, "\\");

fail();

} catch (PathResolutionException ex) {

// expected exception

}}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值