繁体   English   中英

c# - 替换扩展 ascii 字符

[英]c# - Replacing extended ascii characters

我正在解析一些包含 99.9% ascii 字符的文本文件。 数字、基本标点符号和字母 AZ(大写和小写)。

这些文件还包含名称,这些名称偶尔包含扩展 ascii 字符集的字符,例如变音符号 Ü 和 cedillas ç。

我只想使用标准 ascii,所以我通过一系列简单的 replace() 命令处理任何名称来处理这些扩展字符......

myString = myString.Replace("ç", "c");
myString = myString.Replace("Ü", "U");

这适用于我想要替换的所有奇怪字符,除了 Ø(大写 O,带有正斜杠)。 我认为这具有相当于 157 的十进制数。

如果我在每个字符上使用 ToInt32() 逐个字符地处理字符串,它声称十进制等效值为 65533 - 远远超出扩展 ascii 代码的正常范围。

问题

  • 为什么myString.Replace("Ø", "O"); 为这个角色工作?
  • 如何将“Ø”替换为“O”?

其他信息 - 可能是相关的。 用记事本打开文件,字符显示为“Ø”。 与其他来源的比较表明数据是正确的(即完整的字符串是“Jørgensen” - 一个有效的丹麦名称)。 在 Visual Studio 中查看角色显示为“�”。 我在数百个不同的文件中遇到了完全相同的问题(使用这个字符)。 我可以愉快地替换我遇到的所有其他扩展字符而不会出现问题。 我正在使用System.IO.File.ReadAllLines()将所有行读入字符串数组进行处理。

  1. 当“知道”它时,替换对'Ø'工作正常:
  Console.WriteLine("Jørgensen".Replace("ø", "o"));

在您的情况下,问题是您尝试使用错误的编码读取数据,这就是字符串不包含您要替换的字符的原因。 Ø是扩展 ASCII 集的一部分 - iso-8859-1 ,但File.ReadAllLines尝试使用 BOM 字符检测编码,并且我怀疑在您的情况下会回UTF-8 (请参阅文档中的备注)。

您在 VS 代码中看到的相同行为 - 它尝试使用 UTF-8 编码打开文件并向您显示 �: 错误的编码 如果您将编码切换到正确的编码 - 它会正确显示文本: 正确的加法

如果您知道文件使用什么编码,只需明确使用它,这里有一个示例来说明差异:

            // prints J?rgensen
            File.ReadAllLines("data.txt")
                .Select(l => l.Replace("Ø", "O"))
                .ToList()
                .ForEach(Console.WriteLine);
            // prints Jorgensen
            File.ReadAllLines("data.txt",Encoding.GetEncoding("iso-8859-1"))
                .Select(l => l.Replace("Ø", "O"))
                .ToList()
                .ForEach(Console.WriteLine);
  1. 如果您想使用默认 ASCII 集中的字符,您可以将扩展集中的所有特殊字符转换为基本字符(这将是丑陋且不平凡的)。 或者您可以在线搜索如何处理您的问题,您可能会找到String.Normalize()这个线程以及其他一些建议。
        public static string RemoveDiacritics(string s)
        {
            var normalizedString = s.Normalize(NormalizationForm.FormD);
            var stringBuilder = new StringBuilder();

            for(var i = 0; i < normalizedString.Length; i++)
            {
                var c = normalizedString[i];
                if(CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
                    stringBuilder.Append(c);
            }

            return stringBuilder.ToString();
        }
...
            // prints Jorgensen
            File.ReadAllLines("data.txt", Encoding.GetEncoding("iso-8859-1"))
                .Select(RemoveDiacritics)
                .ToList()
                .ForEach(Console.WriteLine);

我强烈建议您深入阅读C#:Jon Skeet的 Unicode 和Victor Stinner 的 Programming with Unicode书籍,以更好地理解:)

PS。 我的代码示例功能强大,紧凑但效率很低,如果您解析大文件,请考虑使用其他解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM