c#更改相对或绝对uri的文件名
本文关键字:uri 文件名 相对 | 更新日期: 2023-09-27 18:02:18
我正在寻找一种干净的方法来改变绝对或相对uri的文件名,这可能包含多个段。我们事先不知道它是绝对的还是相对的,所以我们需要检测:
下面是测试用例:
[Test]
public void Can_change_path_file_name()
{
Fix("file.txt").ShouldEqual("file_fixed.txt");
Fix("/file.txt").ShouldEqual("/file_fixed.txt");
Fix("directory/file.txt").ShouldEqual("directory/file_fixed.txt");
Fix("/directory/file.txt").ShouldEqual("/directory/file_fixed.txt");
Fix("/directory/subdirectory/file.txt").ShouldEqual("/directory/subdirectory/file_fixed.txt");
Fix("http://www.test.com/directory/subdirectory/file.txt").ShouldEqual("http://www.test.com/directory/subdirectory/file_fixed.txt");
Fix("/directory/file/file.txt").ShouldEqual("/directory/file/file_fixed.txt");
}
private string Fix(string uri)
{
// fill me with goodness
}
我的解决方案有效,但似乎有点复杂。我把它贴在下面,如果你想更好:
private string Fix(string uri)
{
var fileName = Path.GetFileNameWithoutExtension(uri);
var extension = Path.GetExtension(uri);
fileName += "_fixed" + extension;
var path = uri.Contains('/') ? uri.Substring(0, uri.LastIndexOf('/') + 1) : "";
return Combine(path, fileName);
}
private string Combine(string path1, string path2)
{
if (path1 == null)
{
throw new ArgumentNullException("path1");
}
if (path2 == null)
{
throw new ArgumentNullException("path2");
}
if (String.IsNullOrEmpty(path2))
{
return path1;
}
if (String.IsNullOrEmpty(path1))
{
return path2;
}
if (path2.StartsWith("http://") || path2.StartsWith("https://"))
{
return path2;
}
var ch = path1[path1.Length - 1];
if (ch != '/')
{
return (path1.TrimEnd('/') + '/' + path2.TrimStart('/'));
}
return (path1 + path2);
}
无正则表达式,无字符串索引。
只是使用。net Path
方法来检索和重新组装一个新的文件名:
/// <summary>
/// Partner to Path.ChangeExtension. This function changes the base filename portion
/// </summary>
/// <param name="path"></param>
/// <param name="newFilename"></param>
/// <returns></returns>
public static String ChangeFilename(String path, String newFilename)
{
String directoryName = Path.GetDirectoryName(path); //e.g. "C:'Temp'foo.dat" ==> "C:'Temp"
//String oldFilename = Path.GetFileName(path); //e.g. "C:'Temp'foo.dat" ==> "foo.dat"
//String filenameWithoutExtension = Path.GetFileNameWithoutExtension(path); //e.g. "C:'Temp'foo.dat" ==> "foo"
String extension = Path.GetExtension(path); //e.g. "C:'Temp'foo.dat" ==> ".dat"
//Reassemble as
// directoryName ' newFilename dotExtension
return String.Format("{0}{1}{2}{3}",
directoryName,
Path.DirectorySeparatorChar,
newFilename,
extension);
}
注意:任何代码都被发布到公共领域。不需要署名
为什么不简单的字符串替换?
private string Fix(string uri)
{
var fileName = Path.GetFileNameWithoutExtension(uri);
var extension = Path.GetExtension(uri);
return uri.Replace(string.Format("{0}{1}", fileName, extension), string.Format("{0}_fixed{1}", fileName, extension));
}
只有当你的文件名也出现在uri的其他部分时,这才会出错。
另一个没有这个缺点的选项是:
private string Fix(string uri)
{
var fileName = Path.GetFileNameWithoutExtension(uri);
var extension = Path.GetExtension(uri);
var slashIndex = uri.LastIndexOf("/");
return string.Format("{0}{1}_fixed{2}", uri.Substring(0, slashIndex + 1), fileName, extension);
}
像
这样的正则表达式怎么样?'b[a-zA-Z0-9]+'.[a-zA-Z0-9]+$
这应该找到file
后跟扩展名的所有结尾。
接下来,如果捕获file
…
'b([a-zA-Z0-9]+)('.[a-zA-Z0-9]+)$
…然后你可以替换它:
var result = Regex.Replace(
input,
@"'b([a-zA-Z0-9]+)('.[a-zA-Z0-9]+)$",
"$1_fixed$2" );
就完成了。您可以在编写代码之前使用像这样的在线正则表达式测试器进行测试。
我已经将工作解决方案包装到一个实用程序方法中。我应该帮助别人。
/// <summary>
/// Changes the file name of the <paramref name="uri"/> using the given <paramref name="modifier"/>
/// </summary>
/// <param name="uri">A relative or absolute uri</param>
/// <param name="modifier">A function to apply to the filename</param>
/// <returns>The modified uri</returns>
public static string ModifyUriFileName(string uri, Func<string, string> modifier)
{
if (string.IsNullOrEmpty(uri))
{
throw new ArgumentNullException("uri");
}
var fileName = Path.GetFileNameWithoutExtension(uri);
var extension = Path.GetExtension(uri);
var path = uri.Substring(0, uri.LastIndexOf('/') + 1);
return string.Format("{0}{1}{2}", path, modifier(fileName), extension);
}
用法:
return CommonUtils.ModifyUriFileName(uri, s => s + "_fixed");