dotnet中Stream、string及byte[]的相关操作
string与byte[](UTF-8)
//string to byte[] string str = "abc中文"; //0x61 0x62 0x63 0xE4 0xB8 0xAD 0xE6 0x96 0x87 byte[] bytes = Encoding.UTF8.GetBytes(str); //byte[] to string //abc中文 str = Encoding.UTF8.GetString(bytes);
string与byte[](ASCII)
//string to byte[] string str = "abc中文"; //注意:由于ASCII不支持中文,中文转码失败会变成问号(0x3F) //0x61 0x62 0x63 0x3F 0x3F byte[] bytes = Encoding.ASCII.GetBytes(str); //byte[] to string //abc?? str = Encoding.ASCII.GetString(bytes); Console.WriteLine(str);
string与byte[](GBK)
GBK是GB2312的扩展,其实现在所使用的GB码都是GBK编码,GB2312早就是过去时,但GB2312这个名字由于用了太久,惯性太大,所以一直保留着,并在在当今GB2312与GBK这两个名称被看作是等价的。在dotnet core中,GBK编码默认不被支持,必须引入nuget包:System.Text.Encoding.CodePages,且在程序入口处注册:Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
//string to byte[] string str = "abc中文"; //0x61 0x62 0x63 0xD6 0xD0 0xCE 0xC4 byte[] bytes = Encoding.GetEncoding("GBK").GetBytes(str); //byte[] to string //abc中文 str = Encoding.GetEncoding("GBK").GetString(bytes);
byte[]与MemoryStream
Stream其实就是对byte[]的一种抽象与封装,计算机世界里的一切代码数据,其实都可以看做Stream,里面包含的是一个个有次序的字节。当然了,跟byte[]相比,Stream通常不能随机访问。MemoryStream表示内存中的Stream,数据存在于内存中,所以它是一个能随机访问的Stream。byte[]与MemoryStream之间能非常方便地转换。
//byte[] to MemoryStream byte[] bytes = {0x61, 0x62, 0x63, 0xE4, 0xB8, 0xAD, 0xE6, 0x96, 0x87}; MemoryStream ms = new MemoryStream(bytes); //MemoryStream to byte[] bytes = ms.ToArray();
string与MemoryStream
string与byte[]互转,byte[]与MemoryStream互转,所以这个就不是问题了。
byte[]与Stream
不是所有Stream都像MemoryStream一样能直接和byte[]互转,比如说FileStream,那怎么办呢?不能直接转,那就使用“读写”这两个动作啊,写到Stream去,以及从Stream中读取。
//byte[] to Stream byte[] bytes = {0x61, 0x62, 0x63, 0xE4, 0xB8, 0xAD, 0xE6, 0x96, 0x87}; using (FileStream fs = File.Create("d:\\test.txt")) { fs.Write(bytes); } //Stream to byte[] using (FileStream fs = File.OpenRead("d:\\test.txt")) { bytes = new byte[fs.Length]; fs.Read(bytes); Console.WriteLine(BytesToHexString(bytes)); }
string与文件
由于我们经常要读取文本文件,或把文本写到文件中去,所以dotnet提供了两个简便方法,让我们可以不管FileStream。
string str = "ABC中文"; //string to file File.WriteAllText("d:\\test.txt", str); //file to string str = File.ReadAllText("d:\\test.txt");
注意,这两个方法都是认为文件使用了UTF-8编码。另外我是推荐使用这两个方法快速访问文本文件的,因为不同编码格式的文本文件其实还有个字节序标记(BOM,Byte Order Mark)的概念,不过这里就不展开了。
string与Stream
如果Stream来自于网络,没有File.ReadAllText这种方法,那应该怎么做?你当然可以用Stream的Read/Write方法,但读出来byte[]之后还需要再转为string,有点周折。所以dotnet引入了两个对象,StreamReader和StreamWriter,用它们可以实现string到Stream之间的转换。(为简单起见,下面的例子依然使用FileStream)
//Write string to Stream using (FileStream fs = File.Create("d:\\test.txt")) { StreamWriter writer = new StreamWriter(fs); writer.Write("ABC中文"); writer.Flush(); } //Read string from Stream using (FileStream fs = File.OpenRead("d:\\test.txt")) { StreamReader reader = new StreamReader(fs) string str = reader.ReadToEnd();//也可以用ReadLine逐行读取 }
注意1:writer自带缓存调用Flush方法确保数据已经写入流中,另一种方法是将writer包到using代码块中,例子见下
注意2:StreamWriter和StreamReader默认使用UTF-8编码,如果要换一种编码方式,需要手动指定,例子见下
//Write string to Stream using (FileStream fs = File.Create("d:\\test.txt")) { using (StreamWriter writer = new StreamWriter(fs, Encoding.GetEncoding("GBK"))) { writer.Write("ABC中文"); } } //Read string from Stream using (FileStream fs = File.OpenRead("d:\\test.txt")) { StreamReader reader = new StreamReader(fs, Encoding.GetEncoding("GBK")); string str = reader.ReadToEnd();//也可以用ReadLine逐行读取 }
注意:要使用GBK编码,请参考“string与byte[](GBK)”中的描述。