XIKEW.COM - 实用教程 - C# 8.0&.NET Core 3.0编码和解码文本 - 实用教程,C# 8.0, .NET Core 3.0,Modern Cross-Platform Development, Chapter 09, Working with Files, Streams, and Serialization - 关于《C# 8.0 And .NET Core 3.0 Modern Cross-Platform Development》第九章编码相关知识

C# 8.0&.NET Core 3.0编码和解码文本
NETCORE 5/24/2020 2:53:31 PM 阅读:6

关于《C# 8.0 And .NET Core 3.0 Modern Cross-Platform Development》第九章编码相关知识

关键字:C# 8.0, .NET Core 3.0,Modern Cross-Platform Development, Chapter 09, Working with Files, Streams, and Serialization

编码和解码文本

文字字符可以用不同的方式表示。 例如,可以使用摩尔斯电码将字母编码为一系列点和破折号,以在电报线上传输。

以类似的方式,计算机中的文本以比特(1和0)的形式存储,表示代码空间中的一个码位。大多数码位表示单个字符,但它们也可以具有其他含义,如格式化。

例如,ASCII具有一个包含128个码位的代码空间。 .NET使用一种称为Unicode的标准在内部对文本进行编码。 Unicode具有超过一百万个码位。

有时,您需要将文本移到.NET外部,以供不使用Unicode或使用Unicode变体的系统使用,因此了解如何在编码之间进行转换非常重要。

下表列出了计算机常用的一些替代文本编码: |Encoding|描述说明| | --- | --- | |ASCII|使用字节的低7位对有限范围的字符进行编码。| |UTF-8|将每个Unicode码位表示为一到四个字节的序列。| |UTF-7|它设计为在7位通道上比UTF-8效率更高,但存在安全性和稳健性问题,因此建议在UTF-7上使用UTF-8。| |UTF-16|这将每个Unicode码位表示为一个或两个16位整数的序列。| |UTF-32|这将每个Unicode码位表示为32位整数,因此是固定长度的编码,而其他Unicode编码长度都是可变的。| |ANSI/ISO encodings|这提供了对用于支持特定语言或一组语言的各种代码页的支持。|

如今在大多数情况下,UTF-8是一个很好的默认值,这就是为什么它实际上是默认编码,即Encoding.Default

将字符串编码为字节数组

让我们探索文本编码。

  1. 创建一个名为WorkingWithEncodings的新控制台应用程序项目,将其添加到Chapter09工作区,然后选择该项目作为OmniSharp的活动项目。
  2. 导入System.Text命名空间,并静态导入Console类。
  3. 在Main方法中添加语句以使用用户选择的编码对字符串进行编码,遍历每个字节,然后将其解码回字符串并输出,如以下代码所示:
WriteLine("Encodings");
WriteLine("[1] ASCII");
WriteLine("[2] UTF-7");
WriteLine("[3] UTF-8");
WriteLine("[4] UTF-16 (Unicode)");
WriteLine("[5] UTF-32");
WriteLine("[any other key] Default");
// choose an encoding
Write("Press a number to choose an encoding: ");
ConsoleKey number = ReadKey(intercept: false).Key;
WriteLine();
WriteLine();
Encoding encoder = number switch
{
    ConsoleKey.D1 => Encoding.ASCII,
    ConsoleKey.D2 => Encoding.UTF7,
    ConsoleKey.D3 => Encoding.UTF8,
    ConsoleKey.D4 => Encoding.Unicode,
    ConsoleKey.D5 => Encoding.UTF32,
    _ => Encoding.Default
};
// define a string to encode
string message = "A pint of milk is £1.99";
// encode the string into a byte array
byte[] encoded = encoder.GetBytes(message);
// check how many bytes the encoding needed
WriteLine("{0} uses {1:N0} bytes.",
encoder.GetType().Name, encoded.Length);
// enumerate each byte
WriteLine($"BYTE HEX CHAR");
foreach (byte b in encoded)
{
    WriteLine($"{b,4} {b.ToString("X"),4} {(char)b,5}");
}
// decode the byte array back into a string and display it
string decoded = encoder.GetString(encoded);
WriteLine(decoded);
  1. 运行应用程序并按1选择ASCII,并注意在输出字节时,井号(£)不能以ASCII表示,因此它使用问号代替,如以下输出所示:
ASCIIEncodingSealed uses 23 bytes.
BYTE HEX CHAR
65 41 A
32 20
112 70 p
105 69 i
110 6E n
116 74 t
32 20
111 6F o
102 66 f
32 20
109 6D m
105 69 i
108 6C l
107 6B k
32 20
105 69 i
115 73 s
32 20
63 3F ?
49 31 1
46 2E .
57 39 9
57 39 9
A pint of milk is ?1.99
  1. 重新运行该应用程序,然后按3选择UTF-8,请注意,UTF-8需要一个额外的字节(24个字节而不是23个字节),但是它可以存储£符号。
  2. 重新运行该应用程序,然后按4选择Unicode(UTF-16),并注意UTF-16每个字符需要两个字节,总共需要46个字节,并且可以存储£符号。 .NET在内部使用此编码来存储char和字符串值。

对文件中的文本进行编码和解码

使用Stream Helper类(例如StreamReader和StreamWriter)时,可以指定要使用的编码。 当您写入帮助程序时,文本将被自动编码,而当您从帮助程序中读取时,字节将被自动解码。

要指定编码,请将编码作为第二个参数传递给助手类型的构造函数,如以下代码所示:

var reader = new StreamReader(stream, Encoding.UTF7);
var writer = new StreamWriter(stream, Encoding.UTF7);

优化方案:通常您将无法选择要使用哪种编码,因为您将生成一个文件供其他系统使用。 但是如果这样做,请选择使用最少字节数但可以存储所需每个字符的字节。