Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Get the Size of Files Having Long Path in C#.NET 3.5

3.60/5 (7 votes)
29 Jul 2015CPOL 19K  
Get the size of files having long path in  C#.NET 3.5

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

C#
DirectoryInfo di = newDirectoryInfo(path); // path: It’s the path to the directory
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:

 

Image 1

To fix this issue, include the following namespace:

C#
using System.Reflection;

And use the below code:

C#
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:

C#
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:

C#
DirectoryInfo di = new DirectoryInfo(path); // path: It’s the path to the directory
FileInfo[] fInfos = di.GetFiles();
long fileSize = 0;
if (fi.Exists)
{
fileSize = fi.Length;
}
else
{
// This will handle long paths
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:

C#
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)); 

 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)