是否有可能获得在C#中的文件的大小 ,而无需使用System.IO.FileInfo
呢?
我知道,你可以通过使用得到其他的东西像名和扩展名Path.GetFileName(yourFilePath)
和Path.GetExtension(yourFilePath)
分别,但显然不是文件的大小? 有另一种方式,我可以得到文件的大小 ,而无需使用System.IO.FileInfo
?
这样做的唯一原因是,如果我是正确的,FileInfo的抓住更多信息比我真正需要的,因此它需要更长的时间来收集所有这些FileInfo中,如果我唯一需要的是文件的大小。 是否有一个更快的方法?
我执行使用这两种方法的基准:
public static uint GetFileSizeA(string filename)
{
WIN32_FIND_DATA findData;
FindFirstFile(filename, out findData);
return findData.nFileSizeLow;
}
public static uint GetFileSizeB(string filename)
{
IntPtr handle = CreateFile(
filename,
FileAccess.Read,
FileShare.Read,
IntPtr.Zero,
FileMode.Open,
FileAttributes.ReadOnly,
IntPtr.Zero);
long fileSize;
GetFileSizeEx(handle, out fileSize);
CloseHandle(handle);
return (uint) fileSize;
}
运行针对有点过2300文件,GetFileSizeA了62-63ms运行。 GetFileSizeB接管了18秒。
除非有人看到什么我做错了,我想答案是清楚哪种方法更快。
有没有一种方法,我可以从实际打开文件不要?
更新
改变FileAttributes.ReadOnly到FileAttributes.Normal降低的定时,使得两个方法是在性能上是相同的。
此外,如果你跳过CloseHandle的()调用,GetFileSizeEx方法变为约20-30%的速度,虽然我不知道,我建议。
从简短的测试我没有,我已经发现,使用一个FileStream平均为比使用皮特的GetFileSizeB仅1毫秒慢(我花了大约21毫秒在网络共享上......)。 我个人更喜欢的BCL限度内停留时,我可以。
代码很简单:
using (var file = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return file.Length;
}
按照此评论 :
我有一个小的应用程序,收集大小信息,并将其保存到一个数组...但我经常有百万个文件的一半,或采取和需要一段时间去通过所有这些文件(我使用的FileInfo) 。 我只是想知道如果有一个更快的方法...
既然你发现这么多的文件长度你更可能从并行化中获益比试图通过另一种方法来获取文件的大小。 该FileInfo
类应该是足够好的 ,任何改进都可能是小的。
并行文件大小的要求,而另一方面,有速度显著改进的潜力。 (请注意,改善的程度将在很大程度上基于磁盘驱动器,而不是你的处理器,所以结果可以相差很大。)
没有一个直接的答案...因为我不知道有使用.NET Framework更快的方法。
下面是我使用的代码:
List<long> list = new List<long>();
DirectoryInfo di = new DirectoryInfo("C:\\Program Files");
FileInfo[] fiArray = di.GetFiles("*", SearchOption.AllDirectories);
foreach (FileInfo f in fiArray)
list.Add(f.Length);
运行,花了2709ms对我的“程序文件”目录,这大约是22720的文件运行。 这是通过任何手段没有懈怠。 此外,当我把*.txt
作为第一个参数的过滤器GetFiles
方法,切断时间大幅下降至461ms。
很多的,这将取决于你的硬盘有多快,但我真的不认为是的FileInfo查杀性能。
注:我thikn这仅适用于.NET 4+
你可以试试这个:
[DllImport("kernel32.dll")]
static extern bool GetFileSizeEx(IntPtr hFile, out long lpFileSize);
但是,这不是多大的改善?
下面是从pinvoke.net采取的示例代码:
IntPtr handle = CreateFile(
PathString,
GENERIC_READ,
FILE_SHARE_READ,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_READONLY,
0); //PInvoked too
if (handle.ToInt32() == -1)
{
return;
}
long fileSize;
bool result = GetFileSizeEx(handle, out fileSize);
if (!result)
{
return;
}