我需要从文件的绝对路径获取文件名(我知道file.getName()
方法,但我不能在这里使用它)。
编辑:我不能使用file.getName(),因为我不需要文件名;我也需要文件路径的一部分(但同样,不是整个absoulte路径)。在提供某个路径之后,我需要文件路径的一部分。
假设该文件位于文件夹中:
C:\Users\someUser
在Windows机器上,如果我按如下方式创建一个模式字符串:
String patternStr = "C:\\Users\\someUser\\(.*+)";
我得到一个例外:java.util.regex.PatternSyntaxException: Illegal/unsupported escape sequence
反斜杠。
如果我使用Pattern.quote(File.pathSeparator):
String patternStr = "C:" + Pattern.quote(File.separator) + "Users" + Pattern.quote(File.separator) + "someUser" + Pattern.quote(File.separator) + "(.*+)";
生成的模式字符串是:C:\Q;\EUsers\Q;\EsomeUser\Q;\E(.*+)
当然与实际fileName“C:\ Users \ someUser \ myFile.txt”不匹配。
我在这里缺少什么?解析文件名的正确方法是什么?
答案 0 :(得分:7)
解析文件名的正确方法是什么?
解析文件名的正确方法是使用File(String)
。使用正则表达式可以将平台依赖项硬连接到代码中。这是一个坏主意。
我知道你说你不能使用File.getName()
......但那是正确的解决方案。如果你想说明为什么你不能使用File.getName()
或许我可以提出另一种解决方案。
答案 1 :(得分:4)
如果您确实想使用正则表达式,则应使用
String patternStr = "C:\\\\Users\\\\someUser\\\\(.*+)";
^^ ^^ ^^
代替。
为什么呢?你的字符串文字
"C:\\Users\\someUser\\(.*+)"
编译为
C:\Users\someUser\(.*+)
由于\
也用于在正则表达式中进行转义,因此您必须“两次”转义它们。
关于您的修改:
您可能想查看URI.relativize()
。例如:
File base = new File("C:/Users/someUser");
File file = new File("C:/Users/someUser/someDir/someFile.txt");
String relativePath = base.toURI().relativize(file.toURI()).getPath();
System.out.println(relativePath); // prints "someDir/someFile.txt"
(请注意,/
在Windows计算机上也可用作文件分隔符。)
顺便说一下,我不知道你的系统上File.separator
有什么,但是如果它设置为\
,那么
"C:" + Pattern.quote(File.separator) + "Users" + Pattern.quote(File.separator) +
"someUser" + Pattern.quote(File.separator) + "(.*+)";
应该产生
C:\Q\\EUsers\Q\\EsomeUser\Q\\E(.*+)
答案 2 :(得分:2)
String patternStr = "C:\\Users\\someUser\\(.*+)";
反斜杠(\
)是Java语言中的转义字符。编译后,您的字符串包含以下内容:
C:\Users\someUser\(.*+)
然后将此字符串解析为正则表达式,它也使用反斜杠作为转义字符。正则表达式解析器尝试了解转义的\U
,\s
和\(
。其中一个关于正则表达式语法是错误的(因此你的例外),并且它们都不是你想要实现的。
尝试
String patternStr = "C:\\\\Users\\\\someUser\\\\(.*+)";
答案 3 :(得分:1)
如果你想通过模式解决它,你需要正确地逃避你的模式
String patternStr = "C:\\\\Users\\\\someUser\\\\(.*+)";
答案 4 :(得分:0)
尝试在模式中加入双倍反斜杠。你需要第二个反斜杠来逃避模式中的一个,而且你需要加倍每一个以在字符串中逃避它们。因此,你最终会得到类似的东西:
String patternStr = "C:\\\\Users\\\\someUser\\\\(.*+)";
答案 5 :(得分:0)
从字符串的结尾移动到第一次出现的文件路径分隔符*或开始。
文件路径分隔符可以是/
或\
。
public static final char ALTERNATIVE_DIRECTORY_SEPARATOR_CHAR = '/';
public static final char DIRECTORY_SEPARATOR_CHAR = '\\';
public static final char VOLUME_SEPARATOR_CHAR = ':';
public static String getFileName(String path) {
if(path == null || path.isEmpty()) {
return path;
}
int length = path.length();
int index = length;
while(--index >= 0) {
char c = path.charAt(index);
if(c == ALTERNATIVE_DIRECTORY_SEPARATOR_CHAR || c == DIRECTORY_SEPARATOR_CHAR || c == VOLUME_SEPARATOR_CHAR) {
return path.substring(index + 1, length);
}
}
return path;
}
尽量保持简单; - )。
答案 6 :(得分:0)
试试这个:
String ResultString = null;
try {
Pattern regex = Pattern.compile("([^\\\\/:*?\"<>|\r\n]+$)");
Matcher regexMatcher = regex.matcher(subjectString);
if (regexMatcher.find()) {
ResultString = regexMatcher.group(1);
}
} catch (PatternSyntaxException ex) {
// Syntax error in the regular expression
}
输出:
myFile.txt
也适用于输入:C:/Users/someUser/myFile.txt
输出:myFile.txt
答案 7 :(得分:0)
我在这里缺少什么?解析文件名的正确方法是什么?
解析文件名的正确方法是使用已为此目的提供的API。您已声明无法使用File.getName(),无需解释。你几乎肯定是错的。
答案 8 :(得分:0)
我不能使用file.getName()因为我不需要文件名;我也需要文件路径的一部分(但同样,不是整个absoulte路径)。
行。所以你想要的是这样的。
// Canonicalize paths to deal with ".", "..", symlinks,
// relative files and case sensitivity issues.
String directory = new File(someDirectory).canonicalPath();
String test = new File(somePathname).canonicalPath();
if (!directory.endsWith(File.separator)) {
directory += File.separator;
}
if (test.startsWith(directory)) {
String pathInDirectory = test.substring(directory.length()):
...
}
优点:
\
。答案 9 :(得分:0)
假设文件名具有特殊字符,特别是在支持特殊字符允许的文件名的MAC时,服务器端Path.GetFileName(fileName)失败并因路径中的非法字符而引发错误。以下使用正则表达式的代码来救援。
以下正则表达式处理2件事
在IE中,上传文件时,文件路径也包含文件夹(即c:\ samplefolder \ subfolder \ sample.xls)。下面的表达式将用空字符串替换所有文件夹并保留文件名
在Mac中使用时,文件名是唯一提供的Safari浏览器并允许文件名中的特殊字符
var regExpDir = @"(^[\w]:\\)([\w].+\w\\)";
var fileName = Regex.Replace(fileName, regExpDir, string.Empty);