File: src\libraries\System.Private.CoreLib\src\System\IO\FileInfo.cs
Web Access
Project: src\src\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj (System.Private.CoreLib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using System.Runtime.Versioning;
using System.Text;
 
namespace System.IO
{
    // Class for creating FileStream objects, and some basic file management
    // routines such as Delete, etc.
    public sealed class FileInfo : FileSystemInfo
    {
        private FileInfo() { }
 
        public FileInfo(string fileName)
            : this(fileName ?? throw new ArgumentNullException(nameof(fileName)), isNormalized: false)
        {
        }
 
        internal FileInfo(string originalPath, string? fullPath = null, string? fileName = null, bool isNormalized = false)
        {
            OriginalPath = originalPath;
 
            fullPath ??= originalPath;
            Debug.Assert(!isNormalized || !PathInternal.IsPartiallyQualified(fullPath.AsSpan()), "should be fully qualified if normalized");
 
            FullPath = isNormalized ? fullPath ?? originalPath : Path.GetFullPath(fullPath);
            _name = fileName;
        }
 
        public override string Name => _name ??= Path.GetFileName(OriginalPath);
 
        public long Length
        {
            get
            {
                if ((Attributes & FileAttributes.Directory) == FileAttributes.Directory)
                {
                    throw new FileNotFoundException(SR.Format(SR.IO_FileNotFound_FileName, FullPath), FullPath);
                }
                return LengthCore;
            }
        }
 
        public string? DirectoryName => Path.GetDirectoryName(FullPath);
 
        public DirectoryInfo? Directory
        {
            get
            {
                string? dirName = DirectoryName;
                if (dirName == null)
                    return null;
                return new DirectoryInfo(dirName);
            }
        }
 
        public bool IsReadOnly
        {
            get
            {
                return (Attributes & FileAttributes.ReadOnly) != 0;
            }
            set
            {
                if (value)
                    Attributes |= FileAttributes.ReadOnly;
                else
                    Attributes &= ~FileAttributes.ReadOnly;
            }
        }
 
        /// <summary>
        /// Initializes a new instance of the <see cref="FileStream" /> class with the specified creation mode, read/write and sharing permission, the access other FileStreams can have to the same file, the buffer size, additional file options and the allocation size.
        /// </summary>
        /// <remarks><see cref="FileStream(string,FileStreamOptions)"/> for information about exceptions.</remarks>
        public FileStream Open(FileStreamOptions options) => File.Open(NormalizedPath, options);
 
        public StreamReader OpenText()
            => new StreamReader(NormalizedPath, Encoding.UTF8, detectEncodingFromByteOrderMarks: true);
 
        public StreamWriter CreateText()
            => CreateStreamWriter(append: false);
 
        public StreamWriter AppendText()
            => CreateStreamWriter(append: true);
 
        public FileInfo CopyTo(string destFileName) => CopyTo(destFileName, overwrite: false);
 
        public FileInfo CopyTo(string destFileName, bool overwrite)
        {
            ArgumentException.ThrowIfNullOrEmpty(destFileName);
 
            string destinationPath = Path.GetFullPath(destFileName);
            FileSystem.CopyFile(FullPath, destinationPath, overwrite);
            return new FileInfo(destinationPath, isNormalized: true);
        }
 
        public FileStream Create()
        {
            FileStream fileStream = File.Create(NormalizedPath);
            Invalidate();
            return fileStream;
        }
 
        public override void Delete()
        {
            FileSystem.DeleteFile(FullPath);
            Invalidate();
        }
 
        public override bool Exists
        {
            get
            {
                try
                {
                    return ExistsCore;
                }
                catch
                {
                    return false;
                }
            }
        }
 
        public FileStream Open(FileMode mode)
            => Open(mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.None);
 
        public FileStream Open(FileMode mode, FileAccess access)
            => Open(mode, access, FileShare.None);
 
        public FileStream Open(FileMode mode, FileAccess access, FileShare share)
            => new FileStream(NormalizedPath, mode, access, share);
 
        public FileStream OpenRead()
            => new FileStream(NormalizedPath, FileMode.Open, FileAccess.Read, FileShare.Read, File.DefaultBufferSize, false);
 
        public FileStream OpenWrite()
            => new FileStream(NormalizedPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
 
        // Moves a given file to a new location and potentially a new file name.
        // This method does work across volumes.
        public void MoveTo(string destFileName)
        {
            MoveTo(destFileName, false);
        }
 
        // Moves a given file to a new location and potentially a new file name.
        // Optionally overwrites existing file.
        // This method does work across volumes.
        public void MoveTo(string destFileName, bool overwrite)
        {
            ArgumentException.ThrowIfNullOrEmpty(destFileName);
 
            string fullDestFileName = Path.GetFullPath(destFileName);
 
            // These checks are in place to ensure Unix error throwing happens the same way
            // as it does on Windows.These checks can be removed if a solution to
            // https://github.com/dotnet/runtime/issues/14885 is found that doesn't require
            // validity checks before making an API call.
            if (!new DirectoryInfo(Path.GetDirectoryName(FullName)!).Exists)
                throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, FullName));
 
            if (!Exists)
                throw new FileNotFoundException(SR.Format(SR.IO_FileNotFound_FileName, FullName), FullName);
 
            FileSystem.MoveFile(FullPath, fullDestFileName, overwrite);
 
            FullPath = fullDestFileName;
            OriginalPath = destFileName;
            _name = Path.GetFileName(fullDestFileName);
 
            // Flush any cached information about the file.
            Invalidate();
        }
 
        public FileInfo Replace(string destinationFileName, string? destinationBackupFileName)
            => Replace(destinationFileName, destinationBackupFileName, ignoreMetadataErrors: false);
 
        public FileInfo Replace(string destinationFileName, string? destinationBackupFileName, bool ignoreMetadataErrors)
        {
            ArgumentNullException.ThrowIfNull(destinationFileName);
 
            FileSystem.ReplaceFile(
                FullPath,
                Path.GetFullPath(destinationFileName),
                destinationBackupFileName != null ? Path.GetFullPath(destinationBackupFileName) : null,
                ignoreMetadataErrors);
 
            return new FileInfo(destinationFileName);
        }
 
        [SupportedOSPlatform("windows")]
        public void Decrypt() => File.Decrypt(FullPath);
 
        [SupportedOSPlatform("windows")]
        public void Encrypt() => File.Encrypt(FullPath);
 
        private StreamWriter CreateStreamWriter(bool append)
        {
            StreamWriter streamWriter = new StreamWriter(NormalizedPath, append);
            Invalidate();
            return streamWriter;
        }
    }
}