Introduction
This posst discusses how to get the size of files having long path in C#.NET 3.5.
Suppose you want to get the size of all the files present in a directory. You would do something like this:
Method 1
DirectoryInfo di = newDirectoryInfo(path);
FileInfo[] fInfos = di.GetFiles();
long fileSize = 0;
foreach (FileInfo fi in fInfos)
{
fileSize = fi.Length;
}
But if you have files having full path (including directory name) more than 260 characters, “fi.Length
” will throw FileNotFoundException
. Even if the file exists, you will get this error, as shown in the screenshot below:
To fix this issue, include the following namespace:
using System.Reflection;
And use the below code:
public const int MAX_PATH = 260;
public const int MAX_ALTERNATE = 14;
[StructLayout(LayoutKind.Sequential)]
public struct FILETIME
{
public uint dwLowDateTime;
public uint dwHighDateTime;
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WIN32_FIND_DATA
{
public FileAttributes dwFileAttributes;
public FILETIME ftCreationTime;
public FILETIME ftLastAccessTime;
public FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ALTERNATE)]
public string cAlternate;
}
[DllImport("kernel32", CharSet = CharSet.Unicode)]
public static extern IntPtrFindFirstFile(string lpFileName, out WIN32_FIND_DATAlpFindFileData);
Define the below function that will return the size of files having long path:
private long getFileSize(string fileName, out WIN32_FIND_DATA findData)
{
long size = 0;
IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
IntPtr findHandle;
findHandle = FindFirstFile(@"\\?\"+ fileName , out findData);
if (findHandle != INVALID_HANDLE_VALUE)
{
if ((findData.dwFileAttributes & FileAttributes.Directory) == 0)
{
size = (long)findData.nFileSizeLow + (long)findData.nFileSizeHigh * 4294967296;
}
}
return size;
}
Update Method 1 with the below code:
DirectoryInfo di = new DirectoryInfo(path);
FileInfo[] fInfos = di.GetFiles();
long fileSize = 0;
if (fi.Exists)
{
fileSize = fi.Length;
}
else
{
FieldInfo fld = typeof(FileSystemInfo).GetField( "FullPath", BindingFlags.Instance |
BindingFlags.NonPublic);
string fullPath = fld.GetValue(fi).ToString();
WIN32_FIND_DATA findData;
fileSize = getFileSize(fullPath, out findData);
}
The function getFileSize
outputs “findData
” of type WIN32_FIND_DATA
. It can be used to get the attribute, created date, last access date and other properties of file having long path as below:
string attribute = findData.dwFileAttributes.ToString();
DateTime CreationTime = DateTime.FromFileTimeUtc
((((long)findData.ftCreationTime.dwHighDateTime) << 32) | ((uint)findData.ftCreationTime.dwLowDateTime));
DateTime LastAccessTime = DateTime.FromFileTimeUtc((((long)findData.ftLastAccessTime.dwHighDateTime)
<< 32) | ((uint)findData.ftLastAccessTime.dwLowDateTime));
DateTime LastWriteTime = DateTime.FromFileTimeUtc((((long)findData.ftLastWriteTime.dwHighDateTime) << 32) |
((uint)findData.ftLastWriteTime.dwLowDateTime));
CodeProject