编码解析

Unicode编码、ASCII码、UTF-8编码、GB2312编码分析总结

一、由简到繁顺序来总结:

1、ASCII编码:

在计算机内部,所有的信息最终都表示为一个二进制的字符串。每一个二进制位(bit)有0和1两种状态。一个字节(byte)共由八个二进制位来组成,共有256种状态,从 0000000到11111111。

阿拉伯数字、英文字母、标点符号等这些字符,怎么定义才能让计算机识别呢?因为计算机只识别二进制位0和1,所以以上这些字符就必须与二进制位(0和1)建立关系,才能让计算机识别。

60年代初,计算机界制定了一套统一的字符编码,来表示字符与二进制位之间的关系。这种统一的字符编码就叫做ASCII编码。ASCII码一共规定了128个字符的编码,比如空格“SPACE”是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的1位统一规定为0。

在英语国家,128个ASCII编码足以表达所有字符,但其它非英语国家,字符不是由英文字符组成,这样就需要增加编码以表达这些字符,对于超过128个字符的编码被称为非ASCII编码。比如:在中国,我们用简体中文,字符编码方式为GB2312。

2、Unicode编码:

Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。Unicode编码可以表示字符很多,所以采用不定字节长来表示。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。

3、UTF-8编码

UTF-8编码是Unicode 的实现方式之一。UTF-8以字节为单位对Unicode进行编码。它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

4、Unicode与UTF-8编码的转化

从Unicode到UTF-8的编码方式如下:

  Unicode编码16进制) ║ UTF-8 字节流二进制)

  000000 – 00007F ║ 0xxxxxxx

  000080 – 0007FF ║ 110xxxxx 10xxxxxx

  000800 – 00FFFF ║ 1110xxxx 10xxxxxx 10xxxxxx

  010000 – 10FFFF ║ 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

  UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。UTF-8编码的最大长度是4个字节。从上表可以看出,4字节模板有21个x,即可以容纳21位二进制数字。Unicode的最大码位0x10FFFF也只有21位。

  例1:“汉”字的Unicode编码是0x6C49。0x6C49在0x0800-0xFFFF之间,使用用3字节模板了:1110xxxx 10xxxxxx 10xxxxxx。将0x6C49写成二进制是:0110 1100 0100 1001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。

UTF-16与UTF-32在此不做介绍。

5、GB2312编码方式:

我国采用简体中文,所有中文字符都采用GB2312编码方式。

GB2312编码使用的是区位码寻字方式,1-9区存放中文符号,16-55区存放一级汉字,56-87区存放二级汉字,如第1个汉字位于16区的第1位,为:’啊’,所以1601,即0x1001就代表了该’啊’的区位码值.
区位码变换为机器内码需要分别将区码和位码加0xA0,所以’啊’的机器内码就是,0xB0A1
4.国际码=区位码+0x2020
机器内码=国际码+0x8080 也就是=区位码+0xa0a0

6、Unicode编码与GB2312编码的关系

Unicode对汉字进行了重新编码,这和GB2312编码的方式和顺序完全不同,unicode对汉字编码从0x4E00开始,到0x9FA5为止,所以Unicode和GB2312编码的转换,就需要一个转换对照表,实现快速转换。

7、转义字符序列与Unicode编码关系
一般转义字符序列用‘\?’表示,?代表所想表达的字符。如:‘\n’代表换行标志。转义字符序列也可以用\U????来表示。????代表16进制的Unicode编码。如:‘\u0066’代表字符‘f‘。

例:”my name\’s GuoXiong”与”my name\u0027s GuoXiong”//都是表示my name’s GuoXiong

C#字符串、字节数组和内存流间的相互转换
定义string变量为str,内存流变量为ms,比特数组为bt

1.字符串=>比特数组

1)byte[] bt=System.Text.Encoding.Default.GetBytes”字符串”);

2)byte[] bt=Convert.FromBase64String”字符串”);

补充:

System.Text.Encoding.Unicode.GetBytesstr);
System.Text.Encoding.UTF8.GetBytesstr);
System.Text.Encoding.GetEncoding”gb2312″).GetBytesstr); //指定编码方式

string str = “中国?ss123?”;
byte[] bytes = System.Text.Encoding.Default.GetBytesstr); //gb2312编码 汉字占2个字节、英文字母占1个字节 bytes长度为12
string s = System.Text.Encoding.Default.GetStringnew byte[] { bytes[0],bytes[1] });//解码后为“中”

byte[] bytes = {97, 98, 99, 100, 101, 102};
string str = System.Text.Encoding.ASCII.GetStringbytes); //结果为:abcdef ASCII码表

常用方法:

GetString 已重载。 在派生类中重写时,将一个字节序列解码为一个字符串。
GetChars 已重载。 在派生类中重写时,将一个字节序列解码为一组字符。
GetBytes 已重载。 在派生类中重写时,将一组字符编码为一个字节序列。

GetByteCount 已重载。 在派生类中重写时,计算对一组字符进行编码所产生的字节数。
GetCharCount 已重载。 在派生类中被重写时,计算对字节序列进行解码所产生的字符数。

GetDecoder 在派生类中重写时,获取一个解码器,该解码器将已编码的字节序列转换为字符序列。
GetEncoder 在派生类中重写时,获取一个解码器,该解码器将Unicode字符序列转换为已编码的字节序列

2.比特数组 => 字符串

1)string str=System.Text.Encoding.Default.GetStringbt);

2)string str=Convert.ToBase64Stringbt);

3.字符串 => 流

1)MemoryStream ms=new MemoryStreamSystem.Text.Encoding.Default.GetBytes”字符串”));

2)MemoryStream ms=new MemoryStreamConvert.FromBase64String”字符串”));

4.流 => 字符串

1)string str=Convert.ToBase64Stringms.ToArray));

2)string str=System.Text.Encoding.Default.GetStringms.ToArray));

5.比特数组 => 流

1)MemoryStream ms=new MemoryStreambt);

2)MemoryStream ms=new MemoryStream);ms.Readbt,0,bt.Lenght);

6.流 => 比特数组

1)byte[] bt=ms.ToArray);

2)MemoryStream ms=new MemoryStream);ms.Writebt,0,ms.Length);

1、两种不同的方法计算字符串的长度

string strTmp = “wk986王克东”;

int i = System.Text.Encoding.Default.GetBytesstrTmp).Length; //算汉字的长度
int j = strTmp.Length; //不算汉字的长度

Console.WriteLine”字符串{0},算汉字的长度:{1},不算汉字长度:{2}”, strTmp,i,j);

//转换成数组计算数组的长度

byte[] bytStr = System.Text.Encoding.Default.GetBytesstrTmp);
int len = bytStr.Length;
Console.WriteLine”字符串长度:”+len.ToString));
Console.Read);

2、System.Text.StringBuilder””)

和字符串“+”是不一样的,在C#中,字符串是“引用”类型,每加一个是重新建立了一个字符串,当字符串特别大的时候,性能消耗大,所以要用StringBuilder。

System.Text.StringBuilder sb = new System.Text.StringBuilder””);
sb.Append”中华”);
sb.Append”人民”);
sb.Append”共和国”);
Console.WriteLinesb);

//判断汉字个数

private int ChkGBKLenstring str)
{
System.Text.ASCIIEncoding n = new System.Text.ASCIIEncoding);
byte[] b = n.GetBytesstr);
int l = 0;
for int i = 0; i <= b.Length – 1; i++)
{
if b[i] == 63) //判断是否为汉字或全脚符号
{
l++;
}
}
return l;
}

C#中流,字节,字符,字符串

首先要明白它们本身是由什么组成的:

流:二进制

字节:无符号整数

字符:Unicode编码字符

字符串:多个Unicode编码字符

那么在.net下它们之间如何转化呢?

一般是遵守以下规则:

流->字节数组->字符数组->字符串

下面就来具体谈谈转化的语法:

流->字节数组

MemoryStream ms = new MemoryStream);

byte[] buffer = new byte[ms.Length];

ms.Readbuffer, 0, int)ms.Length);

字节数组->流

byte[] buffer = new byte[10];

MemoryStream ms = new MemoryStreambuffer);

字节数组->字符数组

1.

byte[] buffer = new byte[10];

char[] ch = new ASCIIEncoding).GetCharsbuffer);

//或者:char[] ch = Encoding.UTF8.GetCharsbuffer)

2.

byte[] buffer = new byte[10];

char[] ch = new char[10];

forint i=0; i<buffer.Length; i++)

{

ch[i] = Convert.ToCharbuffer[i]);

}

字符数组->字节数组

1.

char[] ch = new char[10];

byte[] buffer = new ASCIIEncoding).GetBytesch);

//或者:byte[] buffer = Encoding.UTF8.GetBytesch)

2.

char[] ch = new char[10];

byte[] buffer = new byte[10];

forint i=0; i<ch.Length; i++)

{

buffer[i] = Convert.ToBytech[i]);

}

字符数组->字符串

char[] ch = new char[10];

string str = new stringch);

字符串->字符数组

string str = “abcde”;

char[] ch=str .ToCharArray);

字节数组->字符串

byte[] buffer = new byte[10];

string str = System.Text.Encoding.UTF8.GetStringbuffer);

//或者:string str = new ASCIIEncoding).GetStringbuffer);

字符串->字节数组

string str = “abcde”;

byte[] buffer=System.Text.Encoding.UTF8.GetBytesstr);

//或者:byte[] buffer= new ASCIIEncoding).GetBytesstr);

说明:主要就是用到了Convert类和System.Text命名空间下的类,Encoding是静态类,ASCIIEncoding是实体类,方法都是一样的!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace Encoding
{
class Program
{
static void Mainstring[] args)
{
var gb1 = System.Text.Encoding.GetEncoding”Unicode”);
Console.WriteLinegb1.GetStringgb1.GetBytes”测试”)));

var gb0 = System.Text.Encoding.GetEncoding”UTF-8″);
Console.WriteLinegb0.GetStringgb0.GetBytes”测试”)));

var gb = System.Text.Encoding.GetEncoding”GB2312″);
Console.WriteLinegb.GetStringgb.GetBytes”测试”)));

#region 测试代码

Console.WriteLineIsChineseLetter”测试”, 0));
Console.WriteLineChineseLetterCode”测试”, 0));
Console.WriteLineChineseLetterFromCodeChineseLetterCode”测试”, 0)));

Console.WriteLinegb1.GetString
Utf8_2_Unicodegb0.GetBytes”测试test”))));

//http://qkzz.net/article/3d697483-a5ae-4b50-9ae9-45dc6dd26141.htm
//http://topic.csdn.net/u/20090617/18/1907627e-ce38-4ae5-9755-1cc349a4ed1a.html
//一级汉字有 3755 个, 40 * 94=3760 个, 其中 d7fe, d7fd, d7fc, d7fb, d7fa 五位置为空
for byte i = 0xb0; i < 0xd8; i++)
{
for byte j = 0xa1; j < i != 0xd7 ? 0xff : 0xfa); j++)
{
Console.Writegb.GetStringnew[] { i, j }));
if j == 0xc7 || j == 0xee || j == i != 0xd7 ? 0xfe : 0xf9))
Console.WriteLine);
}
}

Console.WriteLineGetChineseLetterFromGb23120));
Console.WriteLineGetChineseLetterFromGb23123754));

//汉字的 Unicode 编码范围
for var i = 19968; i <= 40959; i++)
{
Console.WriteChineseLetterFromCodei));
}

#endregion

Console.Read);
}
public static string GetChineseLetterFromGb2312int rNum)
{
if rNum < 0 || rNum > 3754)
throw new ArgumentOutOfRangeException”rNum”, “超出一级汉字的范围!”);
var gb = System.Text.Encoding.GetEncoding”GB2312″);
return gb.GetStringnew[] { byte)0xb0 + rNum / 94)), byte)0xa1 + rNum % 94)) });
}

/// <summary>
/// UTF8 汉字字节流转成 Unicode 汉字字节流
/// </summary>
/// <param name=”input”></param>
/// <see cref=”http://hi.baidu.com/hyqsoft/blog/item/263795a164d1728346106464.html”/>
public static byte[] Utf8_2_Unicodebyte[] input)
{
var ret = new List<byte>);
for var i = 0; i < input.Length; i++)
{
if input[i] >= 240) // 11110xxx
{
//i += 3;
throw new Exception”四字节的 UTF-8 字符不能转换成两字节的 Unicode 字符!”);
}
//else if input[i] >= 224)
if input[i] >= 224) // 1110xxxx
{
ret.Addbyte)input[i + 2] & 63) | input[i + 1] & 3) << 6)));
ret.Addbyte)input[i] << 4) | input[i + 1] & 60) >> 2)));
i += 2;
}
else if input[i] >= 192) // 110xxxxx
{
ret.Addbyte)input[i + 1] & 63) | input[i] & 3) << 6)));
ret.Addbyte)input[i] & 28) >> 2));
i += 1;
}
else
{
ret.Addinput[i]);
ret.Add0);
}
}
return ret.ToArray);
}

#region 汉字与Unicode编码

public static bool IsChineseLetterstring input, int index)
{
var chfrom = Convert.ToInt32″4e00″, 16); //范围(0x4e00~0x9fff)转换成int(chfrom~chend)
var chend = Convert.ToInt32″9fa5″, 16);
if input != “”)
{
//var code = Char.ConvertToUtf32input, index);
var gb = System.Text.Encoding.GetEncoding”Unicode”);
var b = gb.GetBytesinput.Substringindex, 1));
var code = b[0] + b[1] * 0x100;

return code >= chfrom && code <= chend;
}
return false;
}

public static int ChineseLetterCodestring input, int index)
{
var chfrom = Convert.ToInt32″4e00″, 16); //范围(0x4e00~0x9fff)转换成int(chfrom~chend)
var chend = Convert.ToInt32″9fa5″, 16);
if input != “”)
{
var code = Char.ConvertToUtf32input, index);

return code >= chfrom && code <= chend ? code : 0;
}
return 0;
}

public static string ChineseLetterHexCodestring input, int index)
{
var code = ChineseLetterCodeinput, index);
return code != 0 ? code.ToString”X4″) : string.Empty;
}

public static string ChineseLetterFromCodeint code)
{
var chfrom = Convert.ToInt32″4e00″, 16); //范围(0x4e00~0x9fff)转换成int(chfrom~chend)
var chend = Convert.ToInt32″9fa5″, 16);
//return code >= chfrom && code <= chend ? Char.ConvertFromUtf32code) : string.Empty;
if code >= chfrom && code <= chend)
{
var gb = System.Text.Encoding.GetEncoding”Unicode”);
var b = new[] { byte)code % 0x100), byte)code / 0x100) };
return gb.GetStringb);
}
return string.Empty;
}

public static string ChineseLetterFromHexCodestring hexCode)
{
//var code = Convert.ToInt32hexCode, 16);
var code = int.ParsehexCode, NumberStyles.HexNumber);
return ChineseLetterFromCodecode);
}

#endregion

}
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace QuotedPrintable解码
{
class Program
{
static void Mainstring[] args)
{
string init_str = “K度空间”;
string encode_str = QuotedPrintable.Encodeinit_str);
string decode_str = QuotedPrintable.Decodeencode_str);

Console.WriteLine
“需要进行QuotedPrintable编码的原始字符串: ” +
” {0} ” +
“编码后得到的字符串: ” +
” {1} ” +
“对编码后得到的字符串进行解码得到的字符串: ” +
” {2} “, init_str, encode_str, decode_str);
}

public class QuotedPrintable
{
/// <summary>
/// QuotedPrintable解码函数
/// </summary>
/// <param name=”input”>需要解码的QuotedPrintable字符串</param>
/// <returns>解码后的字符串</returns>
public static string Decodestring input)
{
System.Text.Encoding encoding = System.Text.Encoding.GetEncoding”gb2312″);

StringBuilder result = new StringBuilder);
StringReader sr = new StringReaderinput);

string line = sr.ReadLine);

while line!=null )
{
bool addCRLF = true;
byte[] bytes = System.Text.Encoding.ASCII.GetBytes line.ToCharArray) );

forint i=0;i<bytes.Length;i++)
{
if bytes[i]>=33 && bytes[i]<=60 ) || bytes[i]>=62 && bytes[i]<=126 ) || bytes[i]==9 || bytes[i]==32)
{
result.Append Convert.ToChar bytes[i] ) );
continue;
}
else if bytes[i]==61 )
{
if i==bytes.Length-1 )
{
//eg. = soft line break;
addCRLF = false;
break;
}
else if bytes[i+1]==51 && bytes[i+2]==68 )
{
//eg. =3D
i++;i++;
result.Append “=” );
continue;
}
else
{
//eg. =B7=D6
byte[] b = new byte[2];
b[0] = Convert.ToByte Convert.ToCharbytes[i+1]).ToString)+Convert.ToCharbytes[i+2]).ToString),16 );
i++;i++;i++;
b[1] = Convert.ToByte Convert.ToCharbytes[i+1]).ToString)+Convert.ToCharbytes[i+2]).ToString),16 );
i++;i++;

result.Appendencoding.GetStringb));
continue;
}

}
}//end of for

line = sr.ReadLine);
if line!=null && addCRLF )
result.Append” “);
}//end of while
return result.ToString);
}

public static string Encodestring input)
{
System.Text.Encoding encoding = System.Text.Encoding.GetEncoding”gb2312″);
const int MAXLINELENGTH = 76;
int currentLineLength = 0;
byte[] bytes = encoding.GetBytesinput.ToCharArray));
StringBuilder result = new StringBuilder);

for int i = 0; i < bytes.Length; i++)
{
if bytes[i] == 10 || bytes[i] == 13)
{
if bytes[i] == 13 && GetNextBytei, bytes, 1) == 10)
{
CheckLineLengthMAXLINELENGTH, ref currentLineLength, 0, result);
result.Append” “);
currentLineLength = 0;
i++;
continue;
}

if bytes[i] == 10)
{
CheckLineLengthMAXLINELENGTH, ref currentLineLength, 0, result);
result.Append” “);
currentLineLength = 0;
}

if bytes[i] == 13)
{
CheckLineLengthMAXLINELENGTH, ref currentLineLength, 3, result);
result.Append”=” + ConvertToHexbytes[i]));
}
}
else
{
if bytes[i] >= 33 && bytes[i] <= 60) || bytes[i] >= 62 && bytes[i] <= 126))
{
CheckLineLengthMAXLINELENGTH, ref currentLineLength, 1, result);
result.AppendSystem.Convert.ToCharbytes[i]));
}
else
{
if bytes[i] == 9 || bytes[i] == 32)
{
CheckLineLengthMAXLINELENGTH, ref currentLineLength, 0, result);
result.AppendSystem.Convert.ToCharbytes[i]));
currentLineLength++;
}
else
{
CheckLineLengthMAXLINELENGTH, ref currentLineLength, 3, result);
result.Append”=” + ConvertToHexbytes[i]));
}
}
}
}

return result.ToString);
}

private static void CheckLineLengthint maxLineLength, ref int currentLineLength, int newStringLength, StringBuilder sb)
{
if currentLineLength + 1 == maxLineLength || currentLineLength + newStringLength + 1 >= maxLineLength)
{
sb.Append”= “);
currentLineLength = 0+newStringLength;
}
else
{
currentLineLength += newStringLength;
}
}

private static int GetNextByteint index, byte[] bytes, int shiftValue)
{
int newIndex = index + shiftValue;

if newIndex < 0 || newIndex > bytes.Length – 1 || bytes.Length == 0)
return -1;
else
return bytes[newIndex];
}

private static string ConvertToHexbyte number)
{
string result = System.Convert.ToStringnumber, 16).ToUpper);
return result.Length == 2) ? result : “0” + result;
}

}

}
}

SQL基础知识

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注