1

我有个问题。Unicode 2019 是这个字符:'</p>

这是一个正确的单引号。它被编码为 UTF8。但我担心它会被双重编码。

>>> u'\u2019'.encode('utf-8')
'\xe2\x80\x99'
>>> u'\xe2\x80\x99'.encode('utf-8')
'\xc3\xa2\xc2\x80\xc2\x99'
>>> u'\xc3\xa2\xc2\x80\xc2\x99'.encode('utf-8')
'\xc3\x83\xc2\xa2\xc3\x82\xc2\x80\xc3\x82\xc2\x99'
>>> print(u'\u2019')
’
>>> print('\xe2\x80\x99')
’
>>> print('\xc3\xa2\xc2\x80\xc2\x99')
’
>>> '\xc3\xa2\xc2\x80\xc2\x99'.decode('utf-8')
u'\xe2\x80\x99'
>>> '\xe2\x80\x99'.decode('utf-8')
u'\u2019'

这就是上面使用的原理。

如何在 C# 中完成粗体部分?

如何获取 UTF8 编码的字符串,转换为字节数组,将其转换为字符串,然后再次解码?

这个方法我试过了,但是输出不适合ISO-8859-1,好像...

    string firstLevel = "’";
    byte[] decodedBytes = Encoding.UTF8.GetBytes(firstLevel);

    Console.WriteLine(Encoding.UTF8.GetChars(decodedBytes));
    // ’

    Console.WriteLine(decodeUTF8String(firstLevel));
    //â�,��"�
    //I was hoping for this:
    //’

了解更新:

乔恩帮助我解决了最基本的问题:从“’”到“’”,然后再到“'”但我想尊重他回答的核心建议:

  1. 了解正在发生的事情
  2. 修复原罪

我努力排在第一位。

编码/解码

我对这些术语感到非常困惑。我将它们与加密/解密之类的术语混淆了,仅仅是因为“En ...”和“De ...”我忘记了它们翻译的内容,以及它们翻译的内容。我混淆了这些起点和终点;它是否与十六进制、字符实体、代码点和字符映射等其他模糊术语有关。

我想在基本层面上解决定义。这个问题的上下文中的编码和解码是:

  1. 解码
    • 对应于 C# {Encoding}。'''GetString'''(bytesArray)
    • 对应 Python stringObject.'''decode'''({Encoding})
    • 根据一些称为“编码”的转换方案,将字节作为输入,并转换为字符串表示作为输出,由上面的 {Encoding} 表示。
    • 字节 -> 字符串
  2. 编码
    • 对应于 C# {Encoding}。'''GetBytes'''(stringObject)
    • 对应 Python stringObject.'''encode'''({Encoding})
    • 解码的反面。
    • 字符串 -> 字节(Python 除外)

Python中的字节与字符串

所以 Encode 和 Decode 带我们在字节和字符串之间来回切换。

虽然 Python 帮助我了解出了什么问题,但它也可能会混淆我对编码/解码“基础”的理解。乔恩说:

可惜Python在很大程度上隐藏了【二进制数据和文本数据的区别】

我认为这就是 PEP所说的意思:

Python 的当前字符串对象被重载。它们用于保存字符序列和字节序列。这种重载目的会导致混乱和错误。

Python 3.* 不会以这种方式重载字符串。:

蟒蛇 2.7

>>> #Encoding example. As a generalization, "Encoding" produce bytes.
>>> #In Python 2.7, strings are overloaded to serve as bytes
>>> type(u'\u2019'.encode('utf-8'))
<type 'str'>

蟒蛇 3.*

>>> #In Python 3.*, bytes and strings are distinct
>>> type('\u2019'.encode('utf-8'))
<class 'bytes'>

Python 2 和 3 之间的另一个重要(相关)区别是它们的默认编码:

>>>import sys
>>>sys.getdefaultencoding()

蟒蛇2

'ascii'

蟒蛇 3

'utf-8'

虽然 Python 2 说 'ascii',但我认为它意味着一种特定类型的 ASCII

  • 它确实“不是”表示 ISO-8859-1,它支持范围(256),这是 Jon 用来解码的(下面讨论)
  • 它表示ASCII,最简单的品种,只有范围(128)

虽然 Python 3 不再将字符串作为字节和字符串重载,但解释器仍然可以很容易地忽略正在发生的事情并在类型之间移动。IE

  • 只需在 Python 2.* 中的字符串前放一个“u”,它就是一个 Unicode 文字
  • 只需在 Python 3.* 中的字符串前放一个“b”,它就是一个字节文字

编码和 C

Jon 指出 C# 使用 UTF-16 来更正我上面的“UTF-8 编码字符串”注释;

每个字符串实际上都是 UTF-16。我的理解是:如果C#有一个字符串对象“s”,那么计算机内存实际上有对应UTF-16映射中那个字符的字节。即,(包括字节顺序标记??) feff0073。

他还在我要求的破解方法中使用了 ISO-8859-1。我不确定为什么。我现在头很痛,所以当我有一些看法时我会回来的。

我会回到这个帖子。我希望我解释得当。我会把它变成一个维基?

4

1 回答 1

4

您需要了解,从根本上说,这是由于有人误解了二进制数据和文本数据之间的区别。遗憾的是,Python 在很大程度上隐藏了这种差异——在 C# 中意外地执行这种特殊形式的双重编码是相当困难的。不过,这段代码应该适合你:

using System;
using System.Text;

class Test
{
    static void Main()
    {
        // Avoid encoding issues in the source file itself...
        string firstLevel = "\u00c3\u00a2\u00c2\u0080\u00c2\u0099";
        string secondLevel = HackDecode(firstLevel);
        string thirdLevel = HackDecode(secondLevel);
        Console.WriteLine("{0:x}", (int) thirdLevel[0]); // 2019
    }

    // Converts a string to a byte array using ISO-8859-1, then *decodes*
    // it using UTF-8. Any use of this method indicates broken data to start
    // with. Ideally, the source of the error should be fixed.
    static string HackDecode(string input)
    {
        byte[] bytes = Encoding.GetEncoding(28591)
                               .GetBytes(input);
        return Encoding.UTF8.GetString(bytes);
    }
}
于 2013-07-27T06:32:51.593 回答