// --------------------------------------------------------------------------------------------------------------------
// <copyright file="File.cs" company="Catel development team">
// Copyright (c) 2008 - 2011 Catel development team. All rights reserved.
// </copyright>
// <summary>
// File class.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using Catel.Properties;
using Microsoft.Win32.SafeHandles;
namespace Catel.IO
{
/// <summary>
/// File class.
/// </summary>
public static class File
{
/// <summary>
/// Copies the specified file to the destination path. Overwriting of the destination file is allowed.
/// </summary>
/// <param name="sourceFileName">Name of the source file.</param>
/// <param name="destinationFileName">Name of the destination file.</param>
/// <returns>
/// <c>true</c> if the file is copied; otherwise <c>false</c>.
/// </returns>
/// <exception cref="ArgumentException">when <paramref name="sourceFileName"/> is <c>null</c> or empty.</exception>
/// <exception cref="ArgumentException">when <paramref name="destinationFileName"/> is <c>null</c> or empty.</exception>
public static bool Copy(string sourceFileName, string destinationFileName)
{
return Copy(sourceFileName, destinationFileName, false);
}
/// <summary>
/// Copies the specified file to the destination path.
/// </summary>
/// <param name="sourceFileName">Name of the source file.</param>
/// <param name="destinationFileName">Name of the destination file.</param>
/// <param name="failIfExist">if set to <c>true</c>, the copy action will fail if the destination file already exists.</param>
/// <returns>
/// <c>true</c> if the file is copied; otherwise <c>false</c>.
/// </returns>
/// <exception cref="ArgumentException">when <paramref name="sourceFileName"/> is <c>null</c> or empty.</exception>
/// <exception cref="ArgumentException">when <paramref name="destinationFileName"/> is <c>null</c> or empty.</exception>
public static bool Copy(string sourceFileName, string destinationFileName, bool failIfExist)
{
if (string.IsNullOrEmpty(sourceFileName))
{
throw new ArgumentException(Exceptions.ArgumentCannotBeNullOrEmpty, "sourceFileName");
}
if (string.IsNullOrEmpty(destinationFileName))
{
throw new ArgumentException(Exceptions.ArgumentCannotBeNullOrEmpty, "destinationFileName");
}
sourceFileName = Path.AddWin32LongFileNamePrefix(sourceFileName);
destinationFileName = Path.AddWin32LongFileNamePrefix(destinationFileName);
return Win32IOApi.CopyFile(sourceFileName, destinationFileName, failIfExist);
}
/// <summary>
/// Creates the specified file.
/// </summary>
/// <param name="filePath">The file path.</param>
/// <returns>
/// <see cref="System.IO.FileStream"/> of the file.
/// </returns>
/// <exception cref="ArgumentException">when <paramref name="filePath"/> is <c>null</c> or empty.</exception>
public static FileStream Create(string filePath)
{
if (string.IsNullOrEmpty(filePath))
{
throw new ArgumentException(Exceptions.ArgumentCannotBeNullOrEmpty, "filePath");
}
return Open(filePath, FileMode.Create, FileAccess.ReadWrite);
}
/// <summary>
/// Deletes the specified file.
/// </summary>
/// <param name="filePath">The file path.</param>
/// <returns>
/// <c>true</c> if the file is deleted; otherwise <c>false</c>.
/// </returns>
/// <exception cref="ArgumentException">when <paramref name="filePath"/> is <c>null</c> or empty.</exception>
public static bool Delete(string filePath)
{
if (string.IsNullOrEmpty(filePath))
{
throw new ArgumentException(Exceptions.ArgumentCannotBeNullOrEmpty, "filePath");
}
filePath = Path.AddWin32LongFileNamePrefix(filePath);
return Win32IOApi.DeleteFile(filePath);
}
/// <summary>
/// Checks whether the specified file exists.
/// </summary>
/// <param name="filePath">The file path.</param>
/// <returns>
/// <c>true</c> if the file exists; otherwise <c>false</c>.
/// </returns>
/// <exception cref="ArgumentNullException">when <paramref name="filePath"/> is <c>null</c>.</exception>
public static bool Exists(string filePath)
{
if (filePath == null)
{
throw new ArgumentNullException("filePath");
}
if (string.IsNullOrEmpty(filePath))
{
return false;
}
Win32IOApi.WIN32_FIND_DATA findData;
filePath = Path.AddWin32LongFileNamePrefix(filePath);
IntPtr findHandle = Win32IOApi.FindFirstFile(filePath, out findData);
if (findHandle != Win32IOApi.INVALID_HANDLE_VALUE)
{
Win32IOApi.FindClose(findHandle);
return true;
}
return false;
}
/// <summary>
/// Gets the size of the file.
/// </summary>
/// <param name="filePath">The file path.</param>
/// <returns>Length of the file or <c>0</c> if file is not found.</returns>
/// <exception cref="ArgumentException">when <paramref name="filePath"/> is <c>null</c> or empty.</exception>
public static long GetFileSize(string filePath)
{
if (string.IsNullOrEmpty(filePath))
{
throw new ArgumentException(Exceptions.ArgumentCannotBeNullOrEmpty, "filePath");
}
filePath = Path.AddWin32LongFileNamePrefix(filePath);
try
{
using (FileStream fileStream = OpenRead(filePath))
{
return fileStream.Length;
}
}
catch (Exception)
{
return 0L;
}
}
/// <summary>
/// Opens the specified filePath as a filestream with read and write access and no share permissions.
/// </summary>
/// <param name="filePath">The filePath.</param>
/// <param name="mode">The file mode.</param>
/// <returns><see cref="System.IO.FileStream"/> of the file.</returns>
/// <exception cref="ArgumentException">when <paramref name="filePath"/> is <c>null</c> or empty.</exception>
public static FileStream Open(string filePath, FileMode mode)
{
return Open(filePath, mode, FileAccess.ReadWrite);
}
/// <summary>
/// Opens the specified filePath as a filestream with the specified access and no share permissions.
/// </summary>
/// <param name="filePath">The filePath.</param>
/// <param name="mode">The file mode.</param>
/// <param name="access">The file access.</param>
/// <returns>
/// <see cref="System.IO.FileStream"/> of the file.
/// </returns>
/// <exception cref="ArgumentException">when <paramref name="filePath"/> is <c>null</c> or empty.</exception>
public static FileStream Open(string filePath, FileMode mode, FileAccess access)
{
return Open(filePath, mode, access, FileShare.None);
}
/// <summary>
/// Opens the specified filePath as a filestream for reading only.
/// </summary>
/// <param name="filePath">The filePath.</param>
/// <returns>
/// <see cref="System.IO.FileStream"/> of the file.
/// </returns>
/// <exception cref="ArgumentException">when <paramref name="filePath"/> is <c>null</c> or empty.</exception>
public static FileStream OpenRead(string filePath)
{
return Open(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
}
/// <summary>
/// Opens the specified filePath as a filestream for writing only.
/// </summary>
/// <param name="filePath">The filePath.</param>
/// <returns>
/// <see cref="System.IO.FileStream"/> of the file.
/// </returns>
public static FileStream OpenWrite(string filePath)
{
return Open(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
}
/// <summary>
/// Opens the specified filePath as a filestream with the specified access and share permissions.
/// </summary>
/// <param name="filePath">The filePath.</param>
/// <param name="mode">The file mode.</param>
/// <param name="access">The file access.</param>
/// <param name="share">The file share.</param>
/// <returns>
/// <see cref="System.IO.FileStream"/> of the file.
/// </returns>
/// <exception cref="ArgumentException">when <paramref name="filePath"/> is <c>null</c> or empty.</exception>
public static FileStream Open(string filePath, FileMode mode, FileAccess access, FileShare share)
{
if (string.IsNullOrEmpty(filePath))
{
throw new ArgumentException(Exceptions.ArgumentCannotBeNullOrEmpty, "filePath");
}
uint umode = GetMode(mode);
uint uaccess = GetAccess(access);
uint ushare = GetShare(share);
if (mode == FileMode.Append)
{
uaccess = Win32IOApi.FILE_APPEND_DATA;
}
filePath = Path.AddWin32LongFileNamePrefix(filePath);
SafeFileHandle sh = Win32IOApi.CreateFileW(filePath, uaccess, ushare, IntPtr.Zero, umode, Win32IOApi.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);
int errorInterface = Marshal.GetLastWin32Error();
if ((errorInterface > 0 && !(mode == FileMode.Append && errorInterface != Win32IOApi.ERROR_ALREADY_EXISTS)) || sh.IsInvalid)
{
throw new FileNotFoundException(string.Format(CultureInfo.CurrentCulture, Exceptions.ErrorOpeningFileViaWin32, errorInterface), filePath);
}
FileStream fs = new FileStream(sh, access);
if (mode == FileMode.Append)
{
if (!sh.IsInvalid)
{
Win32IOApi.SetFilePointer(sh, 0, IntPtr.Zero, Win32IOApi.FILE_END);
}
}
return fs;
}
/// <summary>
/// Gets the mode.
/// </summary>
/// <param name="mode">The file mode.</param>
/// <returns>Win32 mode of the file.</returns>
private static uint GetMode(FileMode mode)
{
uint umode = 0;
switch (mode)
{
case FileMode.CreateNew:
umode = Win32IOApi.CREATE_NEW;
break;
case FileMode.Create:
umode = Win32IOApi.CREATE_ALWAYS;
break;
case FileMode.Append:
umode = Win32IOApi.OPEN_ALWAYS;
break;
case FileMode.Open:
umode = Win32IOApi.OPEN_EXISTING;
break;
case FileMode.OpenOrCreate:
umode = Win32IOApi.OPEN_ALWAYS;
break;
case FileMode.Truncate:
umode = Win32IOApi.TRUNCATE_EXISTING;
break;
}
return umode;
}
/// <summary>
/// Converts the FileAccess constant to win32 constant.
/// </summary>
/// <param name="access">The access.</param>
/// <returns>Win32 access of the file.</returns>
private static uint GetAccess(FileAccess access)
{
uint uaccess = 0;
switch (access)
{
case FileAccess.Read:
uaccess = Win32IOApi.GENERIC_READ;
break;
case FileAccess.ReadWrite:
uaccess = Win32IOApi.GENERIC_READ | Win32IOApi.GENERIC_WRITE;
break;
case FileAccess.Write:
uaccess = Win32IOApi.GENERIC_WRITE;
break;
}
return uaccess;
}
/// <summary>
/// Converts the FileShare constant to win32 constant.
/// </summary>
/// <param name="share">The share.</param>
/// <returns>Win32 share of the file.</returns>
private static uint GetShare(FileShare share)
{
uint ushare = 0;
switch (share)
{
case FileShare.Read:
ushare = Win32IOApi.FILE_SHARE_READ;
break;
case FileShare.ReadWrite:
ushare = Win32IOApi.FILE_SHARE_READ | Win32IOApi.FILE_SHARE_WRITE;
break;
case FileShare.Write:
ushare = Win32IOApi.FILE_SHARE_WRITE;
break;
case FileShare.Delete:
ushare = Win32IOApi.FILE_SHARE_DELETE;
break;
case FileShare.None:
ushare = 0;
break;
}
return ushare;
}
}
}