You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows环境下C#如何读取仅大小写不同的文件?

在Windows系统中用C#读取区分大小写的文件/路径

刚好之前处理过类似的问题,Windows下默认不区分大小写的文件系统确实会给这类仓库操作添不少麻烦,下面给你两种实用的C#解决方案,分别适配不同的.NET版本:

先划个重点:Windows NTFS文件系统**默认是「不区分大小写但保留大小写」**的,普通的.NET文件API(比如File.Exists、Directory.GetFiles)会自动忽略大小写匹配,所以要精准识别仅大小写不同的文件,得用专门的手段。

方法一:用.NET 5+的EnumerationOptions(首推)

从.NET 5开始,官方终于提供了原生的大小写敏感枚举选项,不用再折腾原生API了,代码简洁又可靠:

using System.IO;

// 替换成你的仓库路径
var repoPath = @"C:\YourLocalRepo";
var caseSensitiveOptions = new EnumerationOptions
{
    IgnoreCase = false, // 关键:关闭忽略大小写,开启精准匹配
    RecurseSubdirectories = true // 如果需要递归遍历子目录就打开
};

// 枚举目录下所有区分大小写的文件
foreach (var filePath in Directory.EnumerateFiles(repoPath, "*", caseSensitiveOptions))
{
    Console.WriteLine(filePath);
}

// 精准检查某个大小写的文件是否存在
bool hasUpperCaseFile = File.Exists(Path.Combine(repoPath, "File.txt"), caseSensitiveOptions);
bool hasLowerCaseFile = File.Exists(Path.Combine(repoPath, "file.txt"), caseSensitiveOptions);

方法二:P/Invoke调用Win32原生函数(兼容旧版.NET)

如果你还在维护.NET Framework或.NET Core 3.1及更早版本的项目,那就得直接调用Windows原生API了——毕竟旧版.NET没提供直接的大小写敏感支持。

示例1:枚举区分大小写的文件

using System;
using System.Runtime.InteropServices;
using System.IO;

public static class CaseSensitiveFileUtils
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    private struct WIN32_FIND_DATA
    {
        public uint dwFileAttributes;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
        public uint nFileSizeHigh;
        public uint nFileSizeLow;
        public uint dwReserved0;
        public uint dwReserved1;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string cFileName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
        public string cAlternateFileName;
    }

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern IntPtr FindFirstFileW(string lpFileName, out WIN32_FIND_DATA lpFindFileData);

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern bool FindNextFileW(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool FindClose(IntPtr hFindFile);

    public static void ListCaseSensitiveFiles(string directoryPath)
    {
        var searchPattern = Path.Combine(directoryPath, "*");
        IntPtr searchHandle = FindFirstFileW(searchPattern, out WIN32_FIND_DATA fileData);

        if (searchHandle == IntPtr.Zero)
        {
            throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
        }

        try
        {
            do
            {
                // 跳过当前目录和父目录的占位符
                if (fileData.cFileName != "." && fileData.cFileName != "..")
                {
                    var fullPath = Path.Combine(directoryPath, fileData.cFileName);
                    Console.WriteLine(fullPath);
                }
            } while (FindNextFileW(searchHandle, out fileData));
        }
        finally
        {
            FindClose(searchHandle);
        }
    }
}

// 使用方式
CaseSensitiveFileUtils.ListCaseSensitiveFiles(@"C:\YourLocalRepo");

示例2:精准打开特定大小写的文件

如果要直接读取某个指定大小写的文件(比如只打开File.txt而不是file.txt),可以用CreateFileW:

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr CreateFileW(
    string lpFileName,
    uint dwDesiredAccess,
    uint dwShareMode,
    IntPtr lpSecurityAttributes,
    uint dwCreationDisposition,
    uint dwFlagsAndAttributes,
    IntPtr hTemplateFile);

private const uint GENERIC_READ = 0x80000000;
private const uint OPEN_EXISTING = 3;

public static FileStream OpenExactCaseFile(string filePath)
{
    IntPtr fileHandle = CreateFileW(
        filePath,
        GENERIC_READ,
        0,
        IntPtr.Zero,
        OPEN_EXISTING,
        0,
        IntPtr.Zero);

    if (fileHandle == (IntPtr)(-1))
    {
        throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
    }

    return new FileStream(fileHandle, FileAccess.Read);
}

// 使用方式
using (var stream = OpenExactCaseFile(@"C:\YourLocalRepo\File.txt"))
using (var reader = new StreamReader(stream))
{
    string content = reader.ReadToEnd();
    Console.WriteLine(content);
}

额外提醒

  • 如果你是用Git管理仓库,记得把core.ignorecase设为false,不然Git可能会自动转换文件名大小写,导致本地文件系统的大小写混乱:执行git config core.ignorecase false即可。
  • 即使你用代码能区分这些文件,Windows资源管理器等系统工具还是会默认把它们当成同一个文件,操作时一定要小心,避免误删或覆盖。

内容的提问来源于stack exchange,提问作者KroegerBa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:07:06