我有一个包含文件名和类文件数据的类:
public class FileMeta
{
public string FileName { get; set; }
public byte[] FileData { get; set; }
}
我有一个通过异步下载操作填充此类集合的方法(文件不是来自本地文件系统):
async Task<List<FileMeta>> ReturnFileData(IEnumerable<string> urls)
{
using (var client = new HttpClient())
{
var results = await Task.WhenAll(urls.Select(async url => new
{
FileName = Path.GetFileName(url),
FileData = await client.GetByteArrayAsync(url),
}));
return results.Select(result =>
new FileMeta
{
FileName = result.FileName,
FileData = result.FileData
}).ToList();
}
}
我将这个List<FileMeta>
提供给ZipFile创建者,ZipFile就像所有文件容器一样需要唯一的文件名。
可读性很重要,我希望能够做到以下几点:
file.txt => file.txt
file.txt => file(1).txt
file.txt => file(2).txt
有很多关于如何在文件系统中执行此操作的示例,但不包含简单的对象集合。 (例如,使用System.IO.File.Exists
)
循环访问此对象集合并返回一组唯一文件名的最佳方法是什么?
我已经走了多远
private List<FileMeta> EnsureUniqueFileNames(IEnumerable<FileMeta> fileMetas)
{
var returnList = new List<FileMeta>();
foreach (var file in fileMetas)
{
while (DoesFileNameExist(file.FileName, returnList))
{
//Append (n) in sequence until match is not found?
}
}
return returnList;
}
private bool DoesFileNameExist(string fileName, IEnumerable<FileMeta> fileMeta)
{
var fileNames = fileMeta.Select(file => file.FileName).ToList();
return fileNames.Contains(fileName);
}
答案 0 :(得分:1)
您可以尝试以下方法来增加文件名:
private List<FileMeta> EnsureUniqueFileNames(IEnumerable<FileMeta> fileMetas)
{
var returnedList = new List<FileMeta>();
foreach (var file in fileMetas)
{
int count = 0;
string originalFileName = file.FileName;
while (returnedList.Any(fileMeta => fileMeta.FileName.Equals(file.FileName,
StringComparison.OrdinalIgnoreCase))
{
string fileNameOnly = Path.GetFileNameWithoutExtension(originalFileName);
string extension = Path.GetExtension(file.FileName);
file.FileName = string.Format("{0}({1}){2}", fileNameOnly, count, extension);
count++;
}
returnList.Add(file);
}
return returnList;
}
作为附注,在ReturnFileData
中,您生成了两个列表,一个是匿名类型,另一个是实际的FileMeta
类型。您可以减少中间列表的创建。实际上,根本不需要await
方法内部:
private Task<FileMeta[]> ReturnFileDataAsync(IEnumerable<string> urls)
{
var client = new HttpClient();
return Task.WhenAll(urls.Select(async url => new FileMeta
{
FileName = Path.GetFileName(url),
FileData = await client.GetByteArrayAsync(url),
}));
}
我将返回类型设为FileMeta[]
而不是List<FileMeta>
,因为它无论如何都是固定大小的返回,并且减少了在返回的数组上调用ToList
的需要。我还添加了Async
后缀,以遵循TAP指南。