Java中如何从URL/路径中删除文件名

31

如何从URL或字符串中删除文件名?

String os = System.getProperty("os.name").toLowerCase();
        String nativeDir = Game.class.getProtectionDomain().getCodeSource().getLocation().getFile().toString();

        //Remove the <name>.jar from the string
        if(nativeDir.endsWith(".jar"))
            nativeDir = nativeDir.substring(0, nativeDir.lastIndexOf("/"));

        //Load the right native files
        for(File f : (new File(nativeDir + File.separator + "lib" + File.separator + "native")).listFiles()){
            if(f.isDirectory() && os.contains(f.getName().toLowerCase())){
                System.setProperty("org.lwjgl.librarypath", f.getAbsolutePath()); break;
            }
        }

这就是我现在拥有的,并且它能够工作。根据我的了解,因为我使用了“/”,所以这只能在 Windows 上运行。我想使它具有跨平台性。


https://dev59.com/7Gsz5IYBdhLWcg3wLEq9 - selalerer
这个 / 不是 Windows,\ 才是! - bobbel
9个回答

26

可以考虑使用org.apache.commons.io.FilenameUtils

您可以使用任何文件分隔符提取基本路径、文件名、扩展名等。

String url = "C:\\windows\\system32\\cmd.exe";

String baseUrl = FilenameUtils.getPath(url);
String myFile = FilenameUtils.getBaseName(url)
                + "." + FilenameUtils.getExtension(url);

System.out.println(baseUrl);
System.out.println(myFile);

给予,

windows\system32\
cmd.exe

有 url; String url = "C:/windows/system32/cmd.exe";

将会得到;

windows/system32/
cmd.exe

我没有FilenameUtils,无法导入org.apache.commons.io.FilenameUtils。 - Yemto
@yemto 无法导入可能是“不应该”的意思,或者是“不知道哪个库有它”的意思? - StoopidDonut
@PopoFido 哦,我不喜欢使用库,尤其是对于应该如此简单的事情。 - Yemto
驱动器字母呢? - ed22

22

通过使用 java.nio.file 文件处理包(据我所知自 J2SE 1.7 后引入),这个问题得以简单解决:

Path path = Paths.get(fileNameWithFullPath);
String directory = path.getParent().toString();

2
在问题中没有特别提到,但对于浏览这些答案的一些人可能会感兴趣的是,它对HTTP URL的支持效果不佳。 - Nate

15

你在另一行中使用了File.separator。为什么不在lastIndexOf()中也使用它呢?

nativeDir = nativeDir.substring(0, nativeDir.lastIndexOf(File.separator));

因为它返回了错误的内容,不过似乎并不在意是否变成了C:\something\something\something/something。 - Yemto
File.separator 会返回与您的系统相关的文件分隔符。因此在Windows上,你会得到 "",而在Unix上你会得到“/”。这就是为什么你应该使用 File.separator 的原因。 - Dirk Fauth
Game.class.getProtectionDomain().getCodeSource().getLocation().getFile().toString() 返回 **D:/Dropbox/NetBeansProjects/**,而 System.out.println(File.separator) 返回 \,这是错误的。我使用的是 Windows 7 64 位操作系统。 - Yemto
如果该方法始终返回“/”,您可能需要先执行替换以确保任何情况下都处于相同的状态。String.replace() 可能会有所帮助。 - Dirk Fauth
请注意,为了获取文件名,表达式应该类似于 nativeDir.substring(nativeDir.lastIndexOf(File.separator) + 1)(因此子字符串是从分隔符开始到结尾)。 - rsenna

8
File file = new File(path);
String pathWithoutFileName = file.getParent();

其中 path 可以是 "C:\Users\userName\Desktop\file.txt"。


这应该被标记为答案。 - undefined

3
标准库自Java 7版本起可以处理此问题。
Path pathOnly;

if (file.getNameCount() > 0) {
  pathOnly = file.subpath(0, file.getNameCount() - 1);
} else {
  pathOnly = file;
}

fileFunction.accept(pathOnly, file.getFileName());

1
path.getNameCount() 的文档说明为:“路径中的元素数量,如果此路径仅表示根组件,则为0”。这可能会导致问题... - Andrew

1
Kotlin解决方案:
val file = File( "/folder1/folder2/folder3/readme.txt")
val pathOnly = file.absolutePath.substringBeforeLast( File.separator )
println( pathOnly )

产生以下结果:

/folder1/folder2/folder3


0

使用File.separator替代“/”。它可能是/\,具体取决于平台。如果这不能解决您的问题,那么使用 FileSystem.getSeparator():您可以传递不同的文件系统而不是默认值。


1
我想这样做。但是File.separator返回“\”,而nativeDir使用“/”。 - Yemto
那么像这样的东西不应该可以工作吗?if(nativeDir.endsWith(".jar")){ int index = Math.max(nativeDir.lastIndexOf("/"), nativeDir.lastIndexOf("\\")); nativeDir = nativeDir.substring(0, index); } - Yemto
添加了更多信息。这应该解决与本地目录的差异。 - Chthonic Project

0
我使用正则表达式解决了这个问题。
对于Windows系统:
String path = "";
String filename = "d:\\folder1\\subfolder11\\file.ext";
String regEx4Win = "\\\\(?=[^\\\\]+$)";
String[] tokens = filename.split(regEx4Win);
if (tokens.length > 0)
   path = tokens[0]; // path -> d:\folder1\subfolder11

-1
请尝试以下代码:
file.getPath().replace(file.getName(), "");

1
如果任何目录与目标文件同名,则会中断。由于从操作系统的角度来看,没有扩展名的文件是可以的,这可能会导致像C:\ A \ B \ C \ B被更改为C:\ A \\ C,因此您无意中丢失了一个目录。 - Koenigsberg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接