// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
namespace System.Data.Entity
{
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Threading;
///
/// This class provides utility methods for common I/O tasks not directly supported by .NET Framework BCL,
/// as well as I/O tasks that require elevated privileges.
///
public static class IOHelpers
{
private const int DefaultCopyBufferSize = 65536;
#if !SILVERLIGHT
///
/// Safely determines whether the given path refers to an existing directory on disk.
///
/// The path to test.
/// True if path refers to an existing directory; otherwise, false.
[SecuritySafeCritical]
// Calling Directory.Exists demands FileIOPermission (Read flag) for the specified path.
[PermissionSet(SecurityAction.Assert, Unrestricted = true)]
public static bool DirectoryExists(string path)
{
return Directory.Exists(path);
}
///
/// Creates the specified directory if it doesn't exist or removes all contents of an existing directory.
///
/// Path to directory to create.
[SecuritySafeCritical]
// Calling Directory.Exists demands FileIOPermission (Read flag) for the specified path.
[PermissionSet(SecurityAction.Assert, Unrestricted = true)]
public static void EnsureDirectoryEmpty(string path)
{
if (Directory.Exists(path))
{
SafeDeleteDirectory(path);
}
EnsureDirectoryExists(path);
}
///
/// Creates the specified directory if it doesn't exist.
///
/// Path to directory to create.
[SecuritySafeCritical]
// Calling Directory.Exists and Directory.CreateDirectory demands FileIOPermission (Read | Write) for the specified path.
[PermissionSet(SecurityAction.Assert, Unrestricted = true)]
public static void EnsureDirectoryExists(string path)
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
}
///
/// Safely determines whether the specified file exists.
///
/// The file to check.
/// True if the caller has the required permissions and path contains the name of an existing file; otherwise, false. This method also returns false if path is null, an invalid path, or a zero-length string. If the caller does not have sufficient permissions to read the specified file, no exception is thrown and the method returns false regardless of the existence of path.
[SecuritySafeCritical]
// Calling File.Exists demands FileIOPermission (Read flag) for the specified path.
[PermissionSet(SecurityAction.Assert, Unrestricted = true)]
public static bool FileExists(string path)
{
return File.Exists(path);
}
///
/// Safely returns the absolute path for the specified path string.
///
/// The file or directory for which to obtain absolute path information.
/// A string containing the fully qualified location of path, such as "C:\MyFile.txt".
[SecuritySafeCritical]
// Calling Path.GetFullPath demands FileIOPermission (PathDiscovery flag) for the specified path.
[PermissionSet(SecurityAction.Assert, Unrestricted = true)]
public static string GetFullPath(string path)
{
return Path.GetFullPath(path);
}
///
/// Safely deletes the file and ignores any access violation exceptions.
///
/// The directory to delete.
[SecuritySafeCritical]
// Calling File.Delete demands FileIOPermission (Write flag) for the specified path.
[PermissionSet(SecurityAction.Assert, Unrestricted = true)]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Need to catch everything here.")]
public static void SafeDeleteFile(string path)
{
try
{
File.Delete(path);
}
catch (Exception)
{
// ignore exceptions
}
}
///
/// Safely deletes the directory and ignores any access violation exceptions.
///
/// The directory to delete.
[SecuritySafeCritical]
// Calling Directory.Delete demands FileIOPermission (Write flag) for the specified path.
[PermissionSet(SecurityAction.Assert, Unrestricted = true)]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Need to catch everything here.")]
public static void SafeDeleteDirectory(string path)
{
// try different ways of contents of directory, fail after 3 attempts
for (var i = 0; i < 3; ++i)
{
try
{
Directory.Delete(path, true);
return;
}
catch (Exception)
{
}
Thread.Sleep(500);
try
{
foreach (var file in Directory.GetFiles(path, "*", SearchOption.AllDirectories))
{
SafeDeleteFile(file);
}
return;
}
catch (Exception)
{
}
Thread.Sleep(500);
}
}
///
/// Creates a uniquely named, empty temporary directory on disk and returns the
/// full path of that directory.
///
/// A containing the full path of the temporary directory.
public static string GetTempDirName()
{
var tempDir = Path.GetTempFileName();
File.Delete(tempDir);
Directory.CreateDirectory(tempDir);
return tempDir;
}
///
/// Copies the specified source files to a given directory.
///
/// The destination directory.
/// The source files.
[SecuritySafeCritical]
// Calling File.Copy demands FileIOPermission (Write flag) for the destination file path.
[PermissionSet(SecurityAction.Assert, Unrestricted = true)]
public static void CopyToDirectory(string destinationDirectory, params string[] sourceFiles)
{
foreach (var sourceFile in sourceFiles)
{
var baseName = Path.GetFileName(sourceFile);
var destinationFile = Path.Combine(destinationDirectory, baseName);
if (new FileInfo(sourceFile).FullName
!= new FileInfo(destinationFile).FullName)
{
File.Copy(sourceFile, destinationFile, true);
}
}
}
#endif
public static void CopyToDir(string sourceFileName, string destDirName)
{
File.Copy(
sourceFileName,
Path.Combine(
destDirName,
Path.GetFileName(sourceFileName)));
}
///
/// Copies contents of one stream into another.
///
/// Stream to read from.
/// Stream to write to.
/// The number of bytes copied from the source.
public static int CopyStream(Stream source, Stream destination)
{
return CopyStream(source, destination, new byte[DefaultCopyBufferSize]);
}
///
/// Copies contents of one stream into another.
///
/// Stream to read from.
/// Stream to write to.
/// The copy buffer.
/// The number of bytes copied from the source.
public static int CopyStream(Stream source, Stream destination, byte[] copyBuffer)
{
ExceptionHelpers.CheckArgumentNotNull(source, "source");
ExceptionHelpers.CheckArgumentNotNull(destination, "destination");
ExceptionHelpers.CheckArgumentNotNull(copyBuffer, "copyBuffer");
var bytesCopied = 0;
int bytesRead;
do
{
bytesRead = source.Read(copyBuffer, 0, copyBuffer.Length);
destination.Write(copyBuffer, 0, bytesRead);
bytesCopied += bytesRead;
}
while (bytesRead != 0);
return bytesCopied;
}
///
/// Write an embedded resource to a local file
///
/// Resource to be written
/// File to write resource to
/// Assembly to extract resource from
#if !SILVERLIGHT
[SecuritySafeCritical]
// Calling File.Open demands FileIOPermission (Append flag) for the destination file path.
[PermissionSet(SecurityAction.Assert, Unrestricted = true)]
#endif
public static void WriteResourceToFile(string resourceName, string fileName, Assembly assembly)
{
using (var resourceStream = assembly.GetManifestResourceStream(resourceName))
{
if (resourceStream == null)
{
throw new IOException("Resource '" + resourceName + "' not found in '" + assembly.FullName + "'");
}
using (var fileStream = File.Open(fileName, FileMode.Append))
{
CopyStream(resourceStream, fileStream);
}
}
}
#if !SILVERLIGHT
///
/// Adds the given set of file attributes to the file at the given path
///
/// The name/path of the file
/// The bit-field of attributes to add
public static void AddFileAttributes(string fileName, FileAttributes toAdd)
{
File.SetAttributes(fileName, File.GetAttributes(fileName) | toAdd);
}
///
/// Removes the given set of file attributes from the file at the given path
///
/// The name/path of the file
/// The bit-field of attributes to remove
public static void RemoveFileAttributes(string fileName, FileAttributes toRemove)
{
File.SetAttributes(fileName, File.GetAttributes(fileName) & ~toRemove);
}
#endif
}
}