字符编码

1、ASCII、UTF8、Unicode三种编码方式的区别

 1 private static void ShowCode() {
 2     string[] strArray = { "b", "abcd", "", "甲乙丙丁" };
 3     byte[] buffer;
 4     string mode, back;
 5 
 6     foreach (string str in strArray) {
 7 
 8         for (int i = 0; i <= 2; i++) {
 9             if (i == 0) {
10                 buffer = Encoding.ASCII.GetBytes(str);
11                 back = Encoding.ASCII.GetString(buffer, 0, buffer.Length);
12                 mode = "ASCII";
13             } else if (i == 1) {
14                 buffer = Encoding.UTF8.GetBytes(str);
15                 back = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
16                 mode = "UTF8";
17             } else {
18                 buffer = Encoding.Unicode.GetBytes(str);
19                 back = Encoding.Unicode.GetString(buffer, 0, buffer.Length);
20                 mode = "Unicode";
21             }
22 
23             Console.WriteLine("Mode: {0}, String: {1}, Buffer.Length: {2}",
24                 mode, str, buffer.Length);
25 
26             Console.WriteLine("Buffer:");
27             for (int j = 0; j <= buffer.Length - 1; j++) {
28                 Console.Write(buffer[j] + " ");
29             }
30 
31             Console.WriteLine("\nRetrived: {0}\n", back);
32         }
33     }
34 }

输出为:

Mode: ASCII, String: b, Buffer.Length: 1
Buffer: 98
Retrived: b

Mode: UTF8, String: b, Buffer.Length: 1
Buffer: 98
Retrived: b

Mode: Unicode, String: b, Buffer.Length: 2
Buffer: 98 0
Retrived: b

Mode: ASCII, String: abcd, Buffer.Length: 4
Buffer: 97 98 99 100
Retrived: abcd

Mode: UTF8, String: abcd, Buffer.Length: 4
Buffer: 97 98 99 100
Retrived: abcd

Mode: Unicode, String: abcd, Buffer.Length: 8
Buffer: 97 0 98 0 99 0 100 0
Retrived: abcd

Mode: ASCII, String: 乙, Buffer.Length: 1
Buffer: 63
Retrived: ?

Mode: UTF8, String: 乙, Buffer.Length: 3
Buffer: 228 185 153
Retrived: 乙

Mode: Unicode, String: 乙, Buffer.Length: 2
Buffer: 89 78
Retrived: 乙

Mode: ASCII, String: 甲乙丙丁, Buffer.Length: 4
Buffer: 63 63 63 63
Retrived: ????

Mode: UTF8, String: 甲乙丙丁, Buffer.Length: 12
Buffer: 231 148 178 228 185 153 228 184 153 228 184 129
Retrived: 甲乙丙丁

Mode: Unicode, String: 甲乙丙丁, Buffer.Length: 8
Buffer: 50 117 89 78 25 78 1 78
Retrived: 甲乙丙丁

大体上可以得出这么几个结论:

  • ASCII不能保存中文(貌似谁都知道=_-`)。
  • UTF8是变长编码。在对ASCII字符编码时,UTF更省空间,只占1个字节,与ASCII编码方式和长度相同;Unicode在对ASCII字符编码时,占用2个字节,且第2个字节补零。
  • UTF8在对中文编码时需要占用3个字节;Unicode对中文编码则只需要2个字节。

(以上转载自http://www.tracefact.net/CSharp-Programming/Network-Programming-Part2.aspx

2 escape与unescape

2.1

escape

  该方法不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: * @ - _ + . / 。其他所有的字符都会被转义序列替换。

1  escape('abddd<br />');  // "abddd%3Cbr%20/%3E"
2  'abddd<br />'.length;   // 11
3  "abddd%3Cbr%20/%3E".length; // 17
4  
5  escape('ab<>cd实力');   // "ab%3C%3Ecd%u5B9E%u529B"
6  'ab<>cd实力'.length;     // 8
7  "ab%3C%3Ecd%u5B9E%u529B".length; // 22

unescape

  该函数的工作原理是这样的:通过找到形式为 %xx 和 %uxxxx 的字符序列(x 表示十六进制的数字),用 Unicode 字符 \u00xx 和 \uxxxx 替换这样的字符序列进行解码。

1 unescape('abddd%3Cbr%20/%3E'); // "abddd<br />"
2 unescape('ab%3C%3Ecd%u5B9E%u529B'); // "ab<>cd实力"

  需要注意,javascript中字符串是以Unicode编码形式存储,因此,escape与unescape是将字符在转义字符与Unicode字符间转换(注意转义字符也是已Unicode形式存储)。

2.2

  另外两种编解码方式(encodeURI与decodeURI、encodeURIComponent与decodeURIComponent)也类似,即转化为转义字符。他们的区别如下:

encodeURI:

  该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。

  该方法的目的是对 URI 进行完整的编码,因此对以下在 URI 中具有特殊含义的 ASCII 标点符号,encodeURI() 函数是不会进行转义的:;/?:@&=+$,#

encodeURIComponent:

  该方法不会对 ASCII 字母和数字进行编码,也不会对这些 ASCII 标点符号进行编码: - _ . ! ~ * ' ( ) 。

  其他字符(比如 :;/?:@&=+$,# 这些用于分隔 URI 组件的标点符号),都是由一个或多个十六进制的转义序列替换的。

另外一个与escape的不同之处是,encodeURI 与 encodeURIComponent 采用uft-8对字符串进行编码,如下

1 escape('ab<>cd实力')    // "ab%3C%3Ecd%u5B9E%u529B"
2 encodeURI('ab<>cd实力') // "ab%3C%3Ecd%E5%AE%9E%E5%8A%9B"
3 encodeURIComponent('ab<>cd实力')    // "ab%3C%3Ecd%E5%AE%9E%E5%8A%9B"

(以上参考自http://www.w3school.com.cn/

3、数据传输

  前台页面与后台服务器数据传输时(通过http request与response),只能传输ASCII字符集(如url、post的数据),因此,在交互数据时,如果包含其他字符(如中文字符),需对字符进行编码。

  前台页面:escape与unescape等。

  后台:HttpUtility.UrlEncode与HttpUtility.UrlDecode, 且编码或解码均采用utf-8。

  注:前台页面在向服务器传输数据时,不能显示包含html标签,否则会报错:

  "异常详细信息: System.Web.HttpRequestValidationException: 从客户端(ExportField="<form method="post" ...")中检测到有潜在危险的 Request.Form 值。"

  解决方法为进行字符编码(如escape)。

posted @ 2015-03-03 13:27  Matt_Cheng  阅读(253)  评论(0编辑  收藏  举报