在C#中使用不同类型的编码方案的十六进制字节输出有什么区别?

时间:2015-05-12 06:34:29

标签: c# encoding

考虑以下C#代码

     int x = 126;
     string s = "126";
     FileStream fs = new FileStream("test.txt", FileMode.Create);
     StreamWriter sw = new StreamWriter(fs);
     sw.WriteLine(x);
     sw.WriteLine(s);

输出(以十六进制字节存储在test.txt中)为31 32 36 0D 0A 31 32 36 0D 0A

如果我对第4行进行了更改:

StreamWriter sw = new StreamWriter(fs, Encoding.Unicode);

输出为:FF FE 31 00 32 00 36 00 0D 00 0A 00 31 00 32 00 36 00 0D 00 0A 00

有人可以帮我解释逻辑吗?是否有关于使用C#

的文件系统的不同编码方案及其行为的参考

1 个答案:

答案 0 :(得分:5)

我建议您阅读Joel Spolsky's excellent article on the subject of character sets and encodings。简而言之:

  • 文件只是一个字节序列。
  • 字符串是一系列字符。
  • 字符集定义一组字符并指定一个唯一的代码点(一个代表该字符的整数 - 注意"整数"是每个角色不一定是int
  • 如果要将字符串存储在文件中,则需要将字符序列转换为字节序列。对于256个字符或更少字符的字符集,字符和字节之间通常存在一对一的对应关系,但对于较大的字符集(如Unicode),它会变得更复杂。
  • 编码定义如何将字符串字符的代码点转换为字节。

因此,当您更改编码时,相同的字符串会被转换为不同的字节序列。

请注意,字符集和编码的行为与编程语言无关。更改是如何引用和使用各种编码和字符集(通常,编码与特定字符集绑定,因此选择编码也将隐式选择字符集)。在C#的情况下,Encoding.Unicode命名不佳 - 它是Unicode 字符集,但是UTF-16LE 编码(其中)如果您只使用英文字符,则每隔一个字节为00

另外,请注意,字符串在程序内部表示为char数组,其中每个char是一个值,表示来自UTF-16编码的两个后续字节(因此某些奇特的字符实际上可能表示为两个char值)。您无法直接访问该数组,并且大多数字符串功能都试图抽象出这一事实。此内部编码不会影响字符串写入文件的方式(或者,您手动选择编码,或者获取您正在调用的操作的默认字符集 - StreamWriter为UTF -8(感谢@xanatos的纠正))。