首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 檔案操作完全指南:屬性、讀寫、刪除與進階技巧

     編輯:關於C語言

前言

檔案操作是 C# 開發的基礎功夫。本文彙整常見場景:取得版本資訊、處理唯讀檔案刪除、判斷存在性、逐行讀寫、以及使用 Shell API 實現「移至資源回收筒」等進階功能,並附上可直接複製的最佳實踐程式碼。

1. 取得檔案版本資訊


using System.Diagnostics;

string path = @"D:\TEST.DLL";
if (File.Exists(path))
{
    FileVersionInfo info = FileVersionInfo.GetVersionInfo(path);
    Console.WriteLine($"版本:{info.FileVersion}");
    Console.WriteLine($"產品:{info.ProductName}");
    Console.WriteLine($"著作權:{info.LegalCopyright}");
}

2. 刪除唯讀檔案與覆蓋複製

File.Delete 無法刪除唯讀檔,File.Copy(..., true) 覆蓋時也會因目標唯讀而拋例外。標準流程:重設屬性 → 刪除 → 複製。


string src = @"E:\test.txt";
string dest = @"D:\tmp\test.txt";

if (File.Exists(dest))
{
    var fi = new FileInfo(dest);
    if ((fi.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
        fi.Attributes = FileAttributes.Normal; // 移除唯讀
    File.Delete(dest);
}
File.Copy(src, dest, true); // true = 允許覆蓋

3. 判斷檔案/目錄是否存在


bool fileExists = File.Exists(@"C:\data.txt");
bool dirExists = Directory.Exists(@"D:\LatestVersion");

4. 逐行讀取文字檔

使用 StreamReader 配合 Peek() 或 ReadLine() 回傳 null 判斷結尾。


int lineCount = 0;
using (var sr = new StreamReader(@"C:\log.txt", Encoding.UTF8))
{
    string line;
    while ((line = sr.ReadLine()) != null)
    {
        Console.WriteLine($"[{++lineCount}] {line}");
    }
}

5. 逐行寫入文字檔


using (var sw = new StreamWriter(@"D:\result.txt", false, Encoding.UTF8))
{
    for (int i = 0; i < 10; i++)
        sw.WriteLine($"這是第 {i} 行資料");
}

注意:StreamWriter 建構子第二個參數 append,false 覆蓋、true 附加。

6. 進階:將檔案移至資源回收筒 (SHFileOperation)

直接 File.Delete 是永久刪除。若需「可復原」刪除,必須呼叫 Shell API。


using System;
using System.Runtime.InteropServices;

public static class ShellFileOp
{
    private const uint FO_DELETE = 0x3;
    private const ushort FOF_ALLOWUNDO = 0x40;    // 移至資源回收筒
    private const ushort FOF_NOCONFIRMATION = 0x10; // 無確認對話框
    private const ushort FOF_SILENT = 0x04;         // 無進度 UI
    private const ushort FOF_NOERRORUI = 0x0400;    // 無錯誤 UI

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    private struct SHFILEOPSTRUCT
    {
        public IntPtr hwnd;
        public uint wFunc;
        [MarshalAs(UnmanagedType.LPWStr)] public string pFrom;
        [MarshalAs(UnmanagedType.LPWStr)] public string pTo;
        public ushort fFlags;
        public bool fAnyOperationsAborted;
        public IntPtr hNameMappings;
        [MarshalAs(UnmanagedType.LPWStr)] public string lpszProgressTitle;
    }

    [DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern int SHFileOperation(ref SHFILEOPSTRUCT lpFileOp);

    /// 
    /// 將檔案/目錄移至資源回收筒
    /// 
    public static bool DeleteToRecycleBin(string path)
    {
        if (!File.Exists(path) && !Directory.Exists(path)) return false;

        var op = new SHFILEOPSTRUCT
        {
            hwnd = IntPtr.Zero,
            wFunc = FO_DELETE,
            pFrom = path + '\0' + '\0', // 雙 null 結尾
            pTo = null,
            fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI
        };

        int result = SHFileOperation(ref op);
        return result == 0 && !op.fAnyOperationsAborted;
    }
}

// 使用
ShellFileOp.DeleteToRecycleBin(@"C:\temp.txt");

關鍵細節:pFrom 必須以雙 null 結尾(path + '\0\0'),否則 API 會讀取到記憶體垃圾導致失敗。

7. 常見陷阱與效能建議

情境建議
大檔案讀寫使用 FileStream + byte[] 緩衝,或 CopyToAsync
頻繁追加寫入保持 StreamWriter 開啟,避免反覆 Open/Close
跨平台路徑用 Path.Combine、Path.DirectorySeparatorChar
編碼問題明確指定 Encoding.UTF8,避免預設 ANSI 亂碼

總結

掌握 System.IO 命名空間的核心類別(File、FileInfo、Directory、DirectoryInfo、StreamReader/Writer),並善用 using 確保資源釋放,即能應對 90% 的檔案操作需求。特殊場景(資源回收筒、檔案關聯、延伸屬性)再引入 P/Invoke 補足。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved