如何在C#中读写智能引号(和其他愚蠢的字符)

时间:2012-11-30 02:42:55

标签: c# unicode encoding ascii stringbuilder

我正在编写一个程序,将文件中的所有文本读入字符串,循环查看字符串,然后使用Stringbuilder将字符追加回另一个字符串。我遇到的问题是,当它被写回来时,这样的特殊字符看起来就像�个字符。我不需要进行转换,我只是希望它以我读取它的方式写回来:

    StringBuilder sb = new StringBuilder();
    string text = File.ReadAllText(filePath);
    for (int i = 0; i < text.Length; ++i) {
        if (text[i] != '{') {  // looking for opening curly brace
            sb.Append(text[i]);
            continue;
        }
        // Do stuff
    }
    File.WriteAllText(destinationFile, sb.ToString());

我尝试使用不同的编码(UTF-8,UTF-16,ASCII),但后来它更糟糕了;我开始得到问号符号和汉字(是的,有点霰弹枪的方法,但我只是在试验)。 我读过这篇文章:http://www.joelonsoftware.com/articles/Unicode.html ......但它并没有真正解释为什么我看到我所看到的东西,除非在C#中,读者在遇到像这样奇怪的字符时开始切断位。在此先感谢您的帮助!

2 个答案:

答案 0 :(得分:11)

TL; DR绝对不是UTF-8,你甚至不使用UTF-8来读取生成的文件。读为Windows1252,写为Windows1252(如果您要使用相同的查看方法查看生成的文件)


我们首先要说的是普通用户制作的文件无法使用UTF-8。并非Windows中的所有程序都支持它(excel,notepad ..),更不用说将其作为默认编码(即使大多数开发人员工具也不默认为utf-8,这让我感到疯狂)。由于很多开发人员都不明白编码这样的东西是否存在,那么普通用户在utf-8恶意环境中保存文件的可能性是多少?

这是您的问题首先出现的地方。根据{{​​3}},您使用File.ReadAllText(filePath);的重载只能检测UTF-8或UTF-32。

实际上,只需读取包含"a”a"的Windows-1252中正常编码的文件,就会生成字符串"a�a",其中documentation(阅读维基百科部分,它描述了你所处的情况!)用于替换无效字节。当替换字符再次编码为UTF-8并解释为Windows-1252时,您将看到�,因为UTF-8中的字节是0xEF, 0xBF, 0xBD,这是字节对于Windows-1252中的�

所以把它读作Windows-1252,你就在那里:

Encoding windows1252 = Encoding.GetEncoding("Windows-1252");
String result = File.ReadAllText(@"C:\myfile.txt", windows1252);
Console.WriteLine(result); //Correctly prints "a”a" now

因为您看到了�,所以您正在查看新制作的文件的工具也在使用Windows-1252。因此,如果目标是让文件在该工具中显示正确的字符,则必须将输出编码为Windows-1252:

Encoding windows1252 = Encoding.GetEncoding("Windows-1252");
File.WriteAllText(@"C:\myFile", sb.toString(), windows1252);

答案 1 :(得分:3)

文本可能是UTF8。

File.ReadAllText(filePath, Encoding.UTF8)

加上

File.WriteAllText(destinationFile, sb.ToString(), Encoding.UTF8)

应该涵盖处理Unicode字符。如果你做一个或另一个,你将得到垃圾输出,无论是什么都没有。