singrdk/base/Libraries/System.IO/File.cs

409 lines
17 KiB
C#
Raw Permalink Normal View History

2008-03-05 09:52:00 -05:00
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
2008-11-17 18:29:00 -05:00
//============================================================
//
// Class: File
//
// Purpose: A collection of methods for manipulating Files.
//
//===========================================================
2008-03-05 09:52:00 -05:00
using System;
using System.Runtime.InteropServices;
using System.Text;
using FileSystem.Utils;
using Microsoft.Singularity.Directory;
2008-11-17 18:29:00 -05:00
namespace System.IO
{
2008-03-05 09:52:00 -05:00
// Class for creating FileStream objects, and some basic file management
// routines such as Delete, etc.
//| <include file='doc\File.uex' path='docs/doc[@for="File"]/*' />
public sealed class File
{
private const int GetFileExInfoStandard = 0;
private File()
{
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.OpenText"]/*' />
public static StreamReader OpenText(String path)
{
if (path == null)
throw new ArgumentNullException("path");
return new StreamReader(path);
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.CreateText"]/*' />
public static StreamWriter CreateText(String path)
{
if (path == null)
throw new ArgumentNullException("path");
return new StreamWriter(path,false);
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.AppendText"]/*' />
public static StreamWriter AppendText(String path)
{
if (path == null)
throw new ArgumentNullException("path");
return new StreamWriter(path,true);
}
// Copies an existing file to a new file. An exception is raised if the
// destination file already exists. Use the
// Copy(String, String, boolean) method to allow
// overwriting an existing file.
//
//| <include file='doc\File.uex' path='docs/doc[@for="File.Copy"]/*' />
public static void Copy(String sourceFileName, String destFileName) {
Copy(sourceFileName, destFileName, false);
}
// Copies an existing file to a new file. If overwrite is
// false, then an IOException is thrown if the destination file
// already exists. If overwrite is true, the file is
// overwritten.
//
//| <include file='doc\File.uex' path='docs/doc[@for="File.Copy1"]/*' />
public static void Copy(String sourceFileName, String destFileName, bool overwrite) {
InternalCopy(sourceFileName, destFileName,overwrite);
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.InternalCopy"]/*' />
/// <devdoc>
/// Note: This returns the fully qualified name of the destination file.
/// </devdoc>
internal static String! InternalCopy(String sourceFileName, String destFileName, bool overwrite) {
2008-11-17 18:29:00 -05:00
if (sourceFileName == null || destFileName == null)
2008-03-05 09:52:00 -05:00
throw new ArgumentNullException((sourceFileName==null ? "sourceFileName" : "destFileName"), "ArgumentNull_FileName");
2008-11-17 18:29:00 -05:00
if (sourceFileName.Length == 0 || destFileName.Length == 0)
2008-03-05 09:52:00 -05:00
throw new ArgumentException("Argument_EmptyFileName", (sourceFileName.Length==0 ? "sourceFileName" : "destFileName"));
String fullSourceFileName = Path.GetFullPathInternal(sourceFileName);
String fullDestFileName = Path.GetFullPathInternal(destFileName);
bool r = Native.CopyFile(fullSourceFileName, fullDestFileName, !overwrite);
if (!r) {
__Error.WinIOError(0, destFileName);
}
return fullDestFileName;
}
// Creates a file in a particular path. If the file exists, it is replaced.
// The file is opened with ReadWrite accessand cannot be opened by another
// application until it has been closed. An IOException is thrown if the
// directory specified doesn't exist.
//
// Your application must have Create, Read, and Write permissions to
// the file.
//
//| <include file='doc\File.uex' path='docs/doc[@for="File.Create"]/*' />
public static FileStream Create(String path) {
return Create(path, FileStream.DefaultBufferSize);
}
// Creates a file in a particular path. If the file exists, it is replaced.
// The file is opened with ReadWrite access and cannot be opened by another
// application until it has been closed. An IOException is thrown if the
// directory specified doesn't exist.
//
// Your application must have Create, Read, and Write permissions to
// the file.
//
//| <include file='doc\File.uex' path='docs/doc[@for="File.Create1"]/*' />
public static FileStream Create(String path, int bufferSize) {
return new FileStream(path, FileMode.Create, FileAccess.ReadWrite,
FileShare.None, bufferSize);
}
// Deletes a file. The file specified by the designated path is deleted.
// If the file does not exist, Delete succeeds without throwing
// an exception.
//
// On NT, Delete will fail for a file that is open for normal I/O
// or a file that is memory mapped.
//
// Your application must have Delete permission to the target file.
//
//| <include file='doc\File.uex' path='docs/doc[@for="File.Delete"]/*' />
public static void Delete(String path) {
2008-11-17 18:29:00 -05:00
if (path == null)
2008-03-05 09:52:00 -05:00
throw new ArgumentNullException("path");
String fullPath = Path.GetFullPathInternal(path);
ErrorCode error;
bool r = Native.DeleteFile(fullPath, out error);
if (!r) {
//int err = __Error.ErrorCodeToWin32Error(error);
//__Error.WinIOError(err, path);
2008-11-17 18:29:00 -05:00
__Error.SingularityIOError(error,path);
2008-03-05 09:52:00 -05:00
}
}
// Tests if a file exists. The result is true if the file
// given by the specified path exists; otherwise, the result is
// false. Note that if path describes a directory,
// Exists will return true.
//
// Your application must have Read permission for the target directory.
//
//| <include file='doc\File.uex' path='docs/doc[@for="File.Exists"]/*' />
2008-11-17 18:29:00 -05:00
public static bool Exists(String! path)
2008-03-05 09:52:00 -05:00
{
DirectoryServiceContract.Imp dsRoot = DirectoryService.NewClientEndpoint();
if (dsRoot == null) throw new Exception("No directory service endpoint.");
bool ok = Exists(dsRoot, path);
2008-11-17 18:29:00 -05:00
delete dsRoot;
return ok;
2008-03-05 09:52:00 -05:00
}
2008-11-17 18:29:00 -05:00
2008-03-05 09:52:00 -05:00
public static bool Exists(DirectoryServiceContract.Imp:Ready! dsRoot, String! path) {
2008-11-17 18:29:00 -05:00
try {
2008-03-05 09:52:00 -05:00
path = Path.GetFullPathInternal(path);
2008-11-17 18:29:00 -05:00
if (path == null)
2008-03-05 09:52:00 -05:00
return false;
2008-11-17 18:29:00 -05:00
if (path.Length == 0)
2008-03-05 09:52:00 -05:00
return false;
2008-11-17 18:29:00 -05:00
bool exists = FileUtils.FileExists(dsRoot, (!)path);
#if false // uncomment to debug file access.
Console.WriteLine("FileExists({0}) = {1}", path, exists);
#endif
return exists;
}
catch (ArgumentException) {
}
catch (NotSupportedException) {} // To deal with the fact that security can now throw this on :
catch (IOException) {
2008-03-05 09:52:00 -05:00
}
return false;
}
2008-11-17 18:29:00 -05:00
internal static bool InternalExists(String path) {
2008-03-05 09:52:00 -05:00
Native.FILE_ATTRIBUTE_DATA data = new Native.FILE_ATTRIBUTE_DATA();
int dataInitialised = FillAttributeInfo(path,ref data);
if (dataInitialised != 0)
return false;
return (data.fileAttributes & Native.FILE_ATTRIBUTE_DIRECTORY) == 0;
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.Open"]/*' />
public static FileStream Open(String path,FileMode mode) {
return Open(path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.None);
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.Open1"]/*' />
public static FileStream Open(String path,FileMode mode, FileAccess access) {
return Open(path,mode, access, FileShare.None);
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.Open2"]/*' />
public static FileStream Open(String path, FileMode mode, FileAccess access, FileShare share) {
return new FileStream(path, mode, access, share);
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.SetCreationTime"]/*' />
public static void SetCreationTime(String path, DateTime creationTime)
{
SetCreationTimeUtc(path, creationTime.ToUniversalTime());
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.SetCreationTimeUtc"]/*' />
public static void SetCreationTimeUtc(String path, DateTime creationTimeUtc)
{
IntPtr handle = IntPtr.Zero;
FileStream fs = OpenFile(path, FileAccess.Write, ref handle);
bool r = Native.SetFileTime(handle, new long[] {creationTimeUtc.ToFileTimeUtc()}, null, null);
2008-11-17 18:29:00 -05:00
if (!r) {
2008-03-05 09:52:00 -05:00
fs.Close();
__Error.WinIOError(0, path);
}
fs.Close();
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.GetCreationTimeUtc"]/*' />
public static DateTime GetCreationTimeUtc(String! path)
{
String fullPath = Path.GetFullPathInternal(path);
Native.FILE_ATTRIBUTE_DATA data = new Native.FILE_ATTRIBUTE_DATA();
int dataInitialised = FillAttributeInfo(fullPath,ref data);
if (dataInitialised != 0)
__Error.WinIOError(dataInitialised, path);
if (data.fileAttributes == -1)
throw new IOException(String.Format("IO.PathNotFound_Path", path));
return DateTime.FromFileTimeUtc(data.ftCreationTime);
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.SetLastAccessTimeUtc"]/*' />
public static void SetLastAccessTimeUtc(String path, DateTime lastAccessTimeUtc)
{
IntPtr handle = IntPtr.Zero;
FileStream fs = OpenFile(path, FileAccess.Write, ref handle);
bool r = Native.SetFileTime(handle, null, new long[] {lastAccessTimeUtc.ToFileTimeUtc()}, null);
2008-11-17 18:29:00 -05:00
if (!r) {
2008-03-05 09:52:00 -05:00
fs.Close();
__Error.WinIOError(0, path);
}
fs.Close();
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.GetLastAccessTimeUtc"]/*' />
public static DateTime GetLastAccessTimeUtc(String! path)
{
String fullPath = Path.GetFullPathInternal(path);
Native.FILE_ATTRIBUTE_DATA data = new Native.FILE_ATTRIBUTE_DATA();
int dataInitialised = FillAttributeInfo(fullPath,ref data);
if (dataInitialised != 0)
__Error.WinIOError(dataInitialised, path);
if (data.fileAttributes == -1)
throw new IOException(String.Format("IO.PathNotFound_Path", path));
return DateTime.FromFileTimeUtc(data.ftLastAccessTime);
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.SetLastWriteTimeUtc"]/*' />
public static void SetLastWriteTimeUtc(String path, DateTime lastWriteTimeUtc)
{
IntPtr handle = IntPtr.Zero;
FileStream fs = OpenFile(path, FileAccess.Write, ref handle);
bool r = Native.SetFileTime(handle, null, null, new long[] {lastWriteTimeUtc.ToFileTimeUtc()});
2008-11-17 18:29:00 -05:00
if (!r) {
2008-03-05 09:52:00 -05:00
fs.Close();
__Error.WinIOError(0, path);
}
fs.Close();
}
2008-11-17 18:29:00 -05:00
public static DateTime GetLastWriteTime(String! path)
{
//TODO: FIXFIX need to convert to local time some day
return GetLastWriteTimeUtc(path);
}
2008-03-05 09:52:00 -05:00
//| <include file='doc\File.uex' path='docs/doc[@for="File.GetLastWriteTimeUtc"]/*' />
public static DateTime GetLastWriteTimeUtc(String! path)
{
String fullPath = Path.GetFullPathInternal(path);
Native.FILE_ATTRIBUTE_DATA data = new Native.FILE_ATTRIBUTE_DATA();
int dataInitialised = FillAttributeInfo(fullPath,ref data);
if (dataInitialised != 0)
__Error.WinIOError(dataInitialised, path);
if (data.fileAttributes == -1)
throw new IOException(String.Format("IO.PathNotFound_Path", path));
return DateTime.FromFileTimeUtc(data.ftLastWriteTime);
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.GetAttributes"]/*' />
public static FileAttributes GetAttributes(String! path)
{
String fullPath = Path.GetFullPathInternal(path);
Native.FILE_ATTRIBUTE_DATA data = new Native.FILE_ATTRIBUTE_DATA();
int dataInitialised = FillAttributeInfo(fullPath,ref data);
if (dataInitialised != 0)
__Error.WinIOError(dataInitialised, path);
if (data.fileAttributes == -1)
__Error.WinIOError(Native.ERROR_FILE_NOT_FOUND, path);
return (FileAttributes) data.fileAttributes;
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.SetAttributes"]/*' />
public static void SetAttributes(String! path,FileAttributes fileAttributes)
{
String fullPath = Path.GetFullPathInternal(path);
bool r = Native.SetFileAttributes(fullPath, (int) fileAttributes);
if (!r) {
__Error.WinIOError(0, path);
}
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.OpenRead"]/*' />
public static FileStream OpenRead(String path) {
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
}
//| <include file='doc\File.uex' path='docs/doc[@for="File.OpenWrite"]/*' />
public static FileStream OpenWrite(String path) {
return new FileStream(path, FileMode.OpenOrCreate,
FileAccess.Write, FileShare.None);
}
// Moves a specified file to a new location and potentially a new file name.
// This method does work across volumes.
//
//| <include file='doc\File.uex' path='docs/doc[@for="File.Move"]/*' />
public static void Move(String sourceFileName, String destFileName) {
2008-11-17 18:29:00 -05:00
if (sourceFileName == null || destFileName == null)
2008-03-05 09:52:00 -05:00
throw new ArgumentNullException((sourceFileName==null ? "sourceFileName" : "destFileName"), "ArgumentNull_FileName");
2008-11-17 18:29:00 -05:00
if (sourceFileName.Length == 0 || destFileName.Length == 0)
2008-03-05 09:52:00 -05:00
throw new ArgumentException("Argument_EmptyFileName", (sourceFileName.Length==0 ? "sourceFileName" : "destFileName"));
String fullSourceFileName = Path.GetFullPathInternal(sourceFileName);
String fullDestFileName = Path.GetFullPathInternal(destFileName);
if (!InternalExists(fullSourceFileName))
__Error.WinIOError(Native.ERROR_FILE_NOT_FOUND,sourceFileName);
2008-11-17 18:29:00 -05:00
if (!Native.MoveFile(fullSourceFileName, fullDestFileName)) {
2008-03-05 09:52:00 -05:00
__Error.WinIOError(0, destFileName);
}
}
internal static int FillAttributeInfo(String path, ref Native.FILE_ATTRIBUTE_DATA data)
{
int dataInitialised = 0;
// For floppy drives, normally the OS will pop up a dialog saying
// there is no disk in drive A:, please insert one. We don't want that.
bool success = Native.GetFileAttributesEx(path, GetFileExInfoStandard, ref data);
if (!success) {
data.fileAttributes = -1;
dataInitialised = 0;
}
return dataInitialised;
}
private static FileStream! OpenFile(String path, FileAccess access, ref IntPtr handle)
{
return new FileStream(path, FileMode.Open, access, FileShare.ReadWrite, 1);
}
// Defined in WinError.h
private const int ERROR_INVALID_PARAMETER = 87;
private const int ERROR_ACCESS_DENIED = 0x5;
}
}