Ignore:
Timestamp:
1/28/2010 3:37:54 AM (5 years ago)
Author:
lowjoel
Message:

Replaced the Eraser.Util.File class with extension methods (based on FileSystemInfo? for the most part) to avoid the name collision with System.IO.File; the File.GetCompactPath? function has been replaced with the FileSize? struct.

File:
1 moved

Legend:

Unmodified
Added
Removed
  • branches/eraser6/CodeReview/Eraser.Util/FileSize.cs

    r1705 r1709  
    1 /*  
     1/*  
    22 * $Id$ 
    33 * Copyright 2008-2010 The Eraser Project 
    44 * Original Author: Joel Low <lowjoel@users.sourceforge.net> 
    5  * Modified By: Kasra Nassiri <cjax@users.sourceforge.net> @10/7/2008 
     5 * Modified By: 
    66 *  
    77 * This file is part of Eraser. 
     
    2424using System.Text; 
    2525 
    26 using System.Runtime.InteropServices; 
    27 using System.ComponentModel; 
    28 using System.Windows.Forms; 
    29 using System.Drawing; 
    30 using System.IO; 
    31 using Microsoft.Win32.SafeHandles; 
    3226using System.Globalization; 
    3327 
    3428namespace Eraser.Util 
    3529{ 
    36     public static class File 
     30    /// <summary> 
     31    /// Gets the human-readable representation of a file size from the byte-wise 
     32    /// length of a file. This returns a KB = 1024 bytes (Windows convention.) 
     33    /// </summary> 
     34    public struct FileSize : IConvertible 
    3735    { 
    3836        /// <summary> 
    39         /// Gets the list of ADSes of the given file.  
     37        /// Constructor. 
    4038        /// </summary> 
    41         /// <param name="info">The FileInfo object with the file path etc.</param> 
    42         /// <returns>A list containing the names of the ADSes of each file. The 
    43         /// list will be empty if no ADSes exist.</returns> 
    44         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] 
    45         public static IList<string> GetADSes(FileInfo info) 
     39        /// <param name="filesize">The size of the file, in bytes.</param> 
     40        public FileSize(long filesize) 
     41            : this() 
    4642        { 
    47             List<string> result = new List<string>(); 
    48             using (FileStream stream = new StreamInfo(info.FullName).Open(FileMode.Open, 
    49                 FileAccess.Read, FileShare.ReadWrite)) 
    50             using (SafeFileHandle streamHandle = stream.SafeFileHandle) 
    51             { 
    52                 //Allocate the structures 
    53                 NativeMethods.FILE_STREAM_INFORMATION[] streams = GetADSes(streamHandle); 
    54  
    55                 foreach (NativeMethods.FILE_STREAM_INFORMATION streamInfo in streams) 
    56                 { 
    57                     //Get the name of the stream. The raw value is :NAME:$DATA 
    58                     string streamName = streamInfo.StreamName.Substring(1, 
    59                         streamInfo.StreamName.LastIndexOf(':') - 1); 
    60                      
    61                     if (streamName.Length != 0) 
    62                         result.Add(streamName); 
    63                 } 
    64             } 
    65  
    66             return result.AsReadOnly(); 
     43            Size = filesize; 
    6744        } 
    6845 
    69         private static NativeMethods.FILE_STREAM_INFORMATION[] GetADSes(SafeFileHandle FileHandle) 
     46        #region IConvertible Members 
     47 
     48        public TypeCode GetTypeCode() 
    7049        { 
    71             NativeMethods.IO_STATUS_BLOCK status = new NativeMethods.IO_STATUS_BLOCK(); 
    72             IntPtr fileInfoPtr = IntPtr.Zero; 
     50            return TypeCode.Int64; 
     51        } 
    7352 
    74             try 
    75             { 
    76                 NativeMethods.FILE_STREAM_INFORMATION streamInfo = 
    77                     new NativeMethods.FILE_STREAM_INFORMATION(); 
    78                 int fileInfoPtrLength = (Marshal.SizeOf(streamInfo) + 32768) / 2; 
    79                 uint ntStatus = 0; 
     53        public bool ToBoolean(IFormatProvider provider) 
     54        { 
     55            throw new InvalidCastException(); 
     56        } 
    8057 
    81                 do 
    82                 { 
    83                     fileInfoPtrLength *= 2; 
    84                     if (fileInfoPtr != IntPtr.Zero) 
    85                         Marshal.FreeHGlobal(fileInfoPtr); 
    86                     fileInfoPtr = Marshal.AllocHGlobal(fileInfoPtrLength); 
     58        public byte ToByte(IFormatProvider provider) 
     59        { 
     60            return Convert.ToByte(Size); 
     61        } 
    8762 
    88                     ntStatus = NativeMethods.NtQueryInformationFile(FileHandle, ref status, 
    89                         fileInfoPtr, (uint)fileInfoPtrLength, 
    90                         NativeMethods.FILE_INFORMATION_CLASS.FileStreamInformation); 
    91                 } 
    92                 while (ntStatus != 0 /*STATUS_SUCCESS*/ && ntStatus == 0x80000005 /*STATUS_BUFFER_OVERFLOW*/); 
     63        public char ToChar(IFormatProvider provider) 
     64        { 
     65            throw new InvalidCastException(); 
     66        } 
    9367 
    94                 //Marshal the structure manually (argh!) 
    95                 List<NativeMethods.FILE_STREAM_INFORMATION> result = 
    96                     new List<NativeMethods.FILE_STREAM_INFORMATION>(); 
    97                 unsafe 
    98                 { 
    99                     for (byte* i = (byte*)fileInfoPtr; streamInfo.NextEntryOffset != 0; 
    100                         i += streamInfo.NextEntryOffset) 
    101                     { 
    102                         byte* currStreamPtr = i; 
    103                         streamInfo.NextEntryOffset = *(uint*)currStreamPtr; 
    104                         currStreamPtr += sizeof(uint); 
     68        public DateTime ToDateTime(IFormatProvider provider) 
     69        { 
     70            throw new InvalidCastException(); 
     71        } 
    10572 
    106                         streamInfo.StreamNameLength = *(uint*)currStreamPtr; 
    107                         currStreamPtr += sizeof(uint); 
     73        public decimal ToDecimal(IFormatProvider provider) 
     74        { 
     75            return Convert.ToDecimal(Size); 
     76        } 
    10877 
    109                         streamInfo.StreamSize = *(long*)currStreamPtr; 
    110                         currStreamPtr += sizeof(long); 
     78        public double ToDouble(IFormatProvider provider) 
     79        { 
     80            return Convert.ToDouble(Size); 
     81        } 
    11182 
    112                         streamInfo.StreamAllocationSize = *(long*)currStreamPtr; 
    113                         currStreamPtr += sizeof(long); 
     83        public short ToInt16(IFormatProvider provider) 
     84        { 
     85            return Convert.ToInt16(Size); 
     86        } 
    11487 
    115                         streamInfo.StreamName = Marshal.PtrToStringUni((IntPtr)currStreamPtr, 
    116                             (int)streamInfo.StreamNameLength / 2); 
    117                         result.Add(streamInfo); 
    118                     } 
    119                 } 
     88        public int ToInt32(IFormatProvider provider) 
     89        { 
     90            return Convert.ToInt32(Size); 
     91        } 
    12092 
    121                 return result.ToArray(); 
    122             } 
    123             finally 
    124             { 
    125                 Marshal.FreeHGlobal(fileInfoPtr); 
    126             } 
     93        public long ToInt64(IFormatProvider provider) 
     94        { 
     95            return Size; 
     96        } 
     97 
     98        public sbyte ToSByte(IFormatProvider provider) 
     99        { 
     100            return Convert.ToSByte(Size); 
     101        } 
     102 
     103        public float ToSingle(IFormatProvider provider) 
     104        { 
     105            return Convert.ToSingle(Size); 
     106        } 
     107 
     108        public string ToString(IFormatProvider provider) 
     109        { 
     110            return ToString(Size); 
     111        } 
     112 
     113        public object ToType(Type conversionType, IFormatProvider provider) 
     114        { 
     115            return Convert.ChangeType(Size, conversionType, provider); 
     116        } 
     117 
     118        public ushort ToUInt16(IFormatProvider provider) 
     119        { 
     120            return Convert.ToUInt16(Size); 
     121        } 
     122 
     123        public uint ToUInt32(IFormatProvider provider) 
     124        { 
     125            return Convert.ToUInt32(Size); 
     126        } 
     127 
     128        public ulong ToUInt64(IFormatProvider provider) 
     129        { 
     130            return Convert.ToUInt64(Size); 
     131        } 
     132 
     133        #endregion 
     134 
     135        /// <summary> 
     136        /// The size of the file, in bytes. 
     137        /// </summary> 
     138        public long Size 
     139        { 
     140            get; 
     141            private set; 
    127142        } 
    128143 
    129144        /// <summary> 
    130         /// Uses SHGetFileInfo to retrieve the description for the given file, 
    131         /// folder or drive. 
     145        /// Converts this file size to the concise equivalent. 
    132146        /// </summary> 
    133         /// <param name="path">A string that contains the path and file name for 
    134         /// the file in question. Both absolute and relative paths are valid. 
    135         /// Directories and volumes must contain the trailing \</param> 
    136         /// <returns>A string containing the description</returns> 
    137         public static string GetFileDescription(string path) 
     147        /// <returns>A string containing the file size and the associated unit. 
     148        /// Files larger than 1MB will be accurate to 2 decimal places.</returns> 
     149        public override string ToString() 
    138150        { 
    139             NativeMethods.SHFILEINFO shfi = new NativeMethods.SHFILEINFO(); 
    140             NativeMethods.SHGetFileInfo(path, 0, ref shfi, Marshal.SizeOf(shfi), 
    141                 NativeMethods.SHGetFileInfoFlags.SHGFI_DISPLAYNAME); 
    142             return shfi.szDisplayName; 
     151            return ToString(CultureInfo.CurrentCulture); 
    143152        } 
    144153 
    145154        /// <summary> 
    146         /// Uses SHGetFileInfo to retrieve the icon for the given file, folder or 
    147         /// drive. 
     155        /// Converts a file size to the concise equivalent. 
    148156        /// </summary> 
    149         /// <param name="path">A string that contains the path and file name for 
    150         /// the file in question. Both absolute and relative paths are valid. 
    151         /// Directories and volumes must contain the trailing \</param> 
    152         /// <returns>An Icon object containing the bitmap</returns> 
    153         public static Icon GetFileIcon(string path) 
    154         { 
    155             NativeMethods.SHFILEINFO shfi = new NativeMethods.SHFILEINFO(); 
    156             NativeMethods.SHGetFileInfo(path, 0, ref shfi, Marshal.SizeOf(shfi), 
    157                 NativeMethods.SHGetFileInfoFlags.SHGFI_SMALLICON | 
    158                 NativeMethods.SHGetFileInfoFlags.SHGFI_ICON); 
    159  
    160             if (shfi.hIcon != IntPtr.Zero) 
    161                 return Icon.FromHandle(shfi.hIcon); 
    162             else 
    163                 throw new IOException(string.Format(CultureInfo.CurrentCulture, 
    164                     "Could not load file icon from {0}", path), 
    165                     Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error())); 
    166         } 
    167  
    168         /// <summary> 
    169         /// Compacts the file path, fitting in the given width. 
    170         /// </summary> 
    171         /// <param name="longPath">The long file path.</param> 
    172         /// <param name="newWidth">The target width of the text.</param> 
    173         /// <param name="drawFont">The font used for drawing the text.</param> 
    174         /// <returns>The compacted file path.</returns> 
    175         public static string GetCompactPath(string longPath, int newWidth, Font drawFont) 
    176         { 
    177             using (Control ctrl = new Control()) 
    178             { 
    179                 //First check if the source string is too long. 
    180                 Graphics g = ctrl.CreateGraphics(); 
    181                 int width = g.MeasureString(longPath, drawFont).ToSize().Width; 
    182                 if (width <= newWidth) 
    183                     return longPath; 
    184  
    185                 //It is, shorten it. 
    186                 int aveCharWidth = width / longPath.Length; 
    187                 int charCount = newWidth / aveCharWidth; 
    188                 StringBuilder builder = new StringBuilder(); 
    189                 builder.Append(longPath); 
    190                 builder.EnsureCapacity(charCount); 
    191  
    192                 while (g.MeasureString(builder.ToString(), drawFont).Width > newWidth) 
    193                 { 
    194                     if (!NativeMethods.PathCompactPathEx(builder, longPath, 
    195                         (uint)charCount--, 0)) 
    196                     { 
    197                         return string.Empty; 
    198                     } 
    199                 } 
    200  
    201                 return builder.ToString(); 
    202             } 
    203         } 
    204  
    205         /// <summary> 
    206         /// Determines if a given file is protected by SFC. 
    207         /// </summary> 
    208         /// <param name="filePath">The path to check</param> 
    209         /// <returns>True if the file is protected.</returns> 
    210         public static bool IsProtectedSystemFile(string filePath) 
    211         { 
    212             return NativeMethods.SfcIsFileProtected(IntPtr.Zero, filePath); 
    213         } 
    214  
    215         /// <summary> 
    216         /// Checks whether the path given is compressed. 
    217         /// </summary> 
    218         /// <param name="path">The path to the file or folder</param> 
    219         /// <returns>True if the file or folder is compressed.</returns> 
    220         public static bool IsCompressed(string path) 
    221         { 
    222             ushort compressionStatus = 0; 
    223             uint bytesReturned = 0; 
    224  
    225             using (SafeFileHandle handle = NativeMethods.CreateFile(path, 
    226                 NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE, 
    227                 0, IntPtr.Zero, NativeMethods.OPEN_EXISTING, 
    228                 NativeMethods.FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero)) 
    229             { 
    230                 if (NativeMethods.DeviceIoControl(handle, NativeMethods.FSCTL_GET_COMPRESSION, 
    231                     IntPtr.Zero, 0, out compressionStatus, sizeof(ushort), out bytesReturned, 
    232                     IntPtr.Zero)) 
    233                 { 
    234                     return compressionStatus != NativeMethods.COMPRESSION_FORMAT_NONE; 
    235                 } 
    236             } 
    237  
    238             return false; 
    239         } 
    240  
    241         /// <summary> 
    242         /// Sets whether the file system object pointed to by path is compressed. 
    243         /// </summary> 
    244         /// <param name="path">The path to the file or folder.</param> 
    245         /// <returns>True if the file or folder has its compression value set.</returns> 
    246         public static bool SetCompression(string path, bool compressed) 
    247         { 
    248             ushort compressionStatus = compressed ? 
    249                 NativeMethods.COMPRESSION_FORMAT_DEFAULT : 
    250                 NativeMethods.COMPRESSION_FORMAT_NONE; 
    251             uint bytesReturned = 0; 
    252  
    253             using (SafeFileHandle handle = NativeMethods.CreateFile(path, 
    254                 NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE, 
    255                 0, IntPtr.Zero, NativeMethods.OPEN_EXISTING, 
    256                 NativeMethods.FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero)) 
    257             { 
    258                 return NativeMethods.DeviceIoControl(handle, NativeMethods.FSCTL_SET_COMPRESSION, 
    259                     ref compressionStatus, sizeof(ushort), IntPtr.Zero, 0, out bytesReturned, 
    260                     IntPtr.Zero); 
    261             } 
    262         } 
    263  
    264         /// <summary> 
    265         /// Gets the human-readable representation of a file size from the byte-wise 
    266         /// length of a file. This returns a KB = 1024 bytes (Windows convention.) 
    267         /// </summary> 
    268         /// <param name="bytes">The file size to scale.</param> 
     157        /// <param name="size">The size of the file to convert.</param> 
    269158        /// <returns>A string containing the file size and the associated unit. 
    270159        /// Files larger than 1MB will be accurate to 2 decimal places.</returns> 
    271         public static string GetHumanReadableFileSize(long bytes) 
     160        public static string ToString(long size) 
    272161        { 
    273162            //List of units, in ascending scale 
     
    282171            }; 
    283172 
    284             double dBytes = (double)bytes; 
     173            double dSize = (double)size; 
    285174            for (int i = 0; i != units.Length; ++i) 
    286175            { 
    287                 if (dBytes < 1000.0) 
     176                if (dSize < 1000.0) 
    288177                    if (i <= 1) 
    289178                        return string.Format(CultureInfo.CurrentCulture, 
    290                             "{0} {1}", (int)dBytes, units[i]); 
     179                            "{0} {1}", (int)dSize, units[i]); 
    291180                    else 
    292181                        return string.Format(CultureInfo.CurrentCulture, 
    293                             "{0:0.00} {1}", dBytes, units[i]); 
    294                 dBytes /= 1024.0; 
     182                            "{0:0.00} {1}", dSize, units[i]); 
     183                dSize /= 1024.0; 
    295184            } 
    296185 
    297186            return string.Format(CultureInfo.CurrentCulture, "{0, 2} {1}", 
    298                 dBytes, units[units.Length - 1]); 
    299         } 
    300  
    301         private static DateTime FileTimeToDateTime(System.Runtime.InteropServices.ComTypes.FILETIME value) 
    302         { 
    303             long time = (long)((((ulong)value.dwHighDateTime) << sizeof(int) * 8) | 
    304                 (uint)value.dwLowDateTime); 
    305             return DateTime.FromFileTime(time); 
    306         } 
    307  
    308         private static System.Runtime.InteropServices.ComTypes.FILETIME DateTimeToFileTime(DateTime value) 
    309         { 
    310             long time = value.ToFileTime(); 
    311  
    312             System.Runtime.InteropServices.ComTypes.FILETIME result = 
    313                 new System.Runtime.InteropServices.ComTypes.FILETIME(); 
    314             result.dwLowDateTime = (int)(time & 0xFFFFFFFFL); 
    315             result.dwHighDateTime = (int)(time >> 32); 
    316  
    317             return result; 
    318         } 
    319  
    320         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#")] 
    321         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#")] 
    322         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "3#")] 
    323         public static void GetFileTime(SafeFileHandle file, out DateTime creationTime, 
    324             out DateTime accessedTime, out DateTime modifiedTime) 
    325         { 
    326             System.Runtime.InteropServices.ComTypes.FILETIME accessedTimeNative = 
    327                 new System.Runtime.InteropServices.ComTypes.FILETIME(); 
    328             System.Runtime.InteropServices.ComTypes.FILETIME modifiedTimeNative = 
    329                 new System.Runtime.InteropServices.ComTypes.FILETIME(); 
    330             System.Runtime.InteropServices.ComTypes.FILETIME createdTimeNative = 
    331                 new System.Runtime.InteropServices.ComTypes.FILETIME(); 
    332  
    333             if (!NativeMethods.GetFileTime(file, out createdTimeNative, out accessedTimeNative, 
    334                 out modifiedTimeNative)) 
    335             { 
    336                 throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); 
    337             } 
    338  
    339             creationTime = FileTimeToDateTime(createdTimeNative); 
    340             accessedTime = FileTimeToDateTime(accessedTimeNative); 
    341             modifiedTime = FileTimeToDateTime(modifiedTimeNative); 
    342         } 
    343  
    344         public static void SetFileTime(SafeFileHandle file, DateTime creationTime, 
    345             DateTime accessedTime, DateTime modifiedTime) 
    346         { 
    347             System.Runtime.InteropServices.ComTypes.FILETIME accessedTimeNative = 
    348                 new System.Runtime.InteropServices.ComTypes.FILETIME(); 
    349             System.Runtime.InteropServices.ComTypes.FILETIME modifiedTimeNative = 
    350                 new System.Runtime.InteropServices.ComTypes.FILETIME(); 
    351             System.Runtime.InteropServices.ComTypes.FILETIME createdTimeNative = 
    352                 new System.Runtime.InteropServices.ComTypes.FILETIME(); 
    353  
    354             if (!NativeMethods.GetFileTime(file, out createdTimeNative, 
    355                 out accessedTimeNative, out modifiedTimeNative)) 
    356             { 
    357                 throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); 
    358             } 
    359  
    360             if (creationTime != DateTime.MinValue) 
    361                 createdTimeNative = DateTimeToFileTime(creationTime); 
    362             if (accessedTime != DateTime.MinValue) 
    363                 accessedTimeNative = DateTimeToFileTime(accessedTime); 
    364             if (modifiedTime != DateTime.MinValue) 
    365                 modifiedTimeNative = DateTimeToFileTime(modifiedTime); 
    366  
    367             if (!NativeMethods.SetFileTime(file, ref createdTimeNative, 
    368                 ref accessedTimeNative, ref modifiedTimeNative)) 
    369             { 
    370                 throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); 
    371             } 
     187                dSize, units[units.Length - 1]); 
    372188        } 
    373189    } 
Note: See TracChangeset for help on using the changeset viewer.