如何在C#中适配WSL、Windows及Linux环境的文件名传入?
跨环境C#文件名适配问题解决
问题背景
我正在开发一款接收文件名作为输入参数的C#程序,遇到了跨Windows、WSL、Linux环境的文件名适配问题。极简示例代码如下:
namespace Ns { internal class Program { static void Main(string[] args) { if (args.Length == 0) return; string filename = args[0]; Console.Write("Bytes received: "); foreach (var c in filename) Console.Write("{0:X2}", (int)c); Console.WriteLine(); Console.WriteLine("File {0} {1}found", filename, File.Exists(filename) ? "" : "not "); } } }
测试场景与现象
我创建了一个名为a*b的文件,在不同环境下测试得到如下结果:
- Windows cmd.exe环境:通过Tab补全输入
Program.exe ab,程序输出:
Bytes received: 61F02A62
File a?b found
- WSL终端环境:文件名转义为
./Program.exe a\*b时,程序输出:
Bytes received: 612A62
File a*b not found
但直接输入./Program.exe ab时,C#程序能正常找到该文件。
- Linux机器环境:创建
a*b文件后调用./Program.exe a\*b,程序输出:
Bytes received: 612A62
File a*b found
问题分析
星号的Unicode为\u002A,UTF-8中占1字节。Linux下传入星号可正常识别,但Windows下需要替换为\uF02A才能匹配文件。这类Windows文件名非法字符不止星号,且不能盲目替换所有\u002A,否则会破坏Linux环境的正常识别逻辑。
最终解决方案
针对Windows文件名非法字符创建替换映射列表,实现WSL和Windows环境的兼容;同时可在Linux环境下禁用替换逻辑。优化后的代码如下:
internal class Program { static List<char> bad = new List<char>(new char[] {'<', '>', ':', '"', '\\', '|', '?', '*' }); static char[] good = { '\uF03C', '\uF03E', '\uF03A', '\uF022', '\uF05C', '\uF07C', '\uF03F', '\uF02A' }; static void Main(string[] args) { if (args.Length == 0) return; string filename = ""; foreach (char c in args[0]) { int idx = bad.IndexOf(c); filename += idx == -1 ? c : good[idx]; } Console.WriteLine("File {0} {1}found", filename, File.Exists(filename) ? "" : "not "); } }
内容的提问来源于stack exchange,提问作者Henri Zole
相关产品推荐
相关产品推荐

