数据怎么传递?

在两个终端之间AB。没有直接的网络连接,那么如果要进行AB的数据传递,可以通过中间介质来进行中介传递:通过移动U盘把数据从A上拷贝下来,然后再备份到B上,这时,两者通过间接的连接达到传递的目的。而这些数据在系统中是具体的,例如一个文本文件,文本中内容是一份人员表单,其中记录着一次聚会的人员名单,及聚会的时间,地点等信息。对于计算机来说这些数据就是二进制数据,而对于计算机应用者来说,这些数据是我们可见的,字符串类型的内容。

 

.net下,如何实现对文本文件的复制与保存的,是如何实现对字符串的读写的?

1)创建字符串并存在为文本

public void TestCreateText()

{

    string strContent = "这是一个文本file";

    StreamWriter writer = File.CreateText(@"k:\myText.txt");

    writer.WriteLine(strContent);

    writer.Close();

}

现在在文本中记录一个字串:这是一个文本file

 

通过IO进行创建文本,并向文本中写入字符串。实现很简单,过程很明了。

2)读取文本文件,并打印文本内容

public void TestReadText()

{

    string strContent = string.Empty;

    StreamReader reader = File.OpenText(@"k:\myText.txt");

    strContent=reader.ReadToEnd();

    reader.Close();

    Console.WriteLine(strContent);

}

 

3)保存客户信息到文本文件

其中的客户信息被封装到一个客户类实例中,那么如何保存?

 

public void TestWriteCustomerText()

{

    Customer customer = new Customer

    {

Unid = 1,

CustomerName = "Songjiang",

CreateTime = DateTime.Now,

Telephone = new Call

{ Mobile = "1111111",

FirmCall = "2222",

HomeCall = "3333" }

    };

 

    StreamWriter writer = File.AppendText(@"k:\myText.txt");

 

    writer.WriteLine(customer);

    writer.Close();

}

这种方法不可以的,因为StreamWriterWriteLine方法重载的object方法向文件写入的是并不是customer的内容。如果要写入这个客户实例的内容,包括标识,姓名,创建时间等信息,只能想可以解决的方法,例如把这些信息以字符串来表示,然后就可以写入文本了。

可以这样:

1)直白的记录

writer.WriteLine("unid:"+customer.Unid);

 

那么在读取的时候,例如从文本中显示,还要通过一些方法来解析。如果只是单纯的读取文本,可能它并不能明确的表示意义,例如这个文本读取的内容是:unid:1(尽管这里可以看出并知道它表示unid1)。如果可以把它还原为一个客户实例,那么可以说,它是有意义的(至少在一定范围内,它是有意义的,最起码它确实表示一个客户的unid)。

 

2)通过Json来实现

Json可以明确的解析,尽管它的文本意义不能很好的表示(至少不能一目了然),但这种方法是可以满足以上的要求。

public void TestJsonWriter()

{

    Customer customer = new Customer

    {

Unid = 1,

CustomerName = "Songjiang",

CreateTime = DateTime.Now,

Telephone = new Call {

Mobile = "1111111",

FirmCall = "2222",

HomeCall = "3333" }

    };

 

DataContractJsonSerializer ds =

new DataContractJsonSerializer(typeof(Customer));

    FileStream fs = new FileStream(@"k:\myText.txt", FileMode.Open);

 

    ds.WriteObject(fs, customer);

 

    fs.Close();

}

能过对客户实例进行Json化(可以说Json序列化),然后生成json串,进行文本保存。

Json序列化和反序列化有很多种实现方法,在.net3.5中提供了json序列化和反序列化的实现。它的名字空间是:

System.Runtime.Serialization.Json

类库文件为:System.ServiceModel.Web.dll

更多序列化和json序列化内容请见:

http://www.cnblogs.com/jams742003/archive/2010/03/03/1677288.html

 

下边通过读取json字串,转换为json对象,最终转换为客户类实例:

public void TestJsonReader()

{

    Customer customer = new Customer();

DataContractJsonSerializer ds =

new DataContractJsonSerializer(typeof(Customer));

    FileStream fs = new FileStream(@"k:\myText.txt", FileMode.Open);

    customer=(Customer)ds.ReadObject(fs);

    fs.Close();

    Console.WriteLine(customer.Unid);

}

这种json序列化保存的客户数据(Customer类的一个实例,一个客户信息)是有规则的,这个规则对于两方(序列化和反序列化)来说是约定好的,这种约定使得双方都可以通过这种约定保存或读取数据,并使数据有意义。

 

3)文本的二进制

一个文本文件对于我们来说是一个可以直接读的文本内容,一个大字符串,但在电脑上保存时(物理上),它是以二进制格式进行保存的。

例如:得到abc这个字符串的二进制

Ascii码环境下,abc这个字符串的二进制是:

97 98 99

1100001 1100010 1100011

 

对于文本文件是如何读取的?例如通过记事本来打开上边用到的那个文本。

·得到这个文本的二进制流

·得到这个文件的字符编码,文本文件默认的是ANSI编码,在中文系统下,它就是GB2312编码。

·解释流

――――――――――――――――――――――――

{"CreateTime":"\/Date(1269854982203+0800)\/","CustomerName":"Songjiang","Telephone":{"FirmCall":"2222","HomeCall":"3333","Mobile":"1111111"},"Unid":1}

――――――――――――――――――――――――

 

这是一长字符串,里边没有127以后的字符,即它们都属Ascii码范围。它的二进制就是分别得到这些Ascii字符的二进制。

 

例如:前三个{“C这三个字符的编码,通过Ascii码表:123 34 67这时10进制,在16进制下是:7b 22 43

ultra打开这个文本文件,并查看16进制就是:7b 22 43。(在有些编码环境下,文本文件前有多余的字符,叫做BOM

 

图片文件在物理上也是二进制格式存储的,但在电脑上可以看到这些二进制所表示的内容(一张图片)。用记事本打开一张gif。是一堆的乱码,但前三个gif是认识的。记事本默认ANSI编码,在中文系统下是GB2312编码。

 

4)文本文件中的图文混排

现在把一张gif图与一些文本以文本格式存在一起。为简单起见,文本内容为:

A然后是图片的二进制。

首先说明一下图片如果用记事本打开看到的乱码的问题:对于二进制来说,图片读到流,然后写到字节数组中。我的操作系统是win2003,记事本默认的字符编码格式为ANSI,在中文系统下代表GB2312,所以从记事本打开图片的通过GB2312字符编码对字节数组的解析。

public void TestAscii()

{

    StreamWriter writer = File.CreateText(@"k:\MixTest.txt");

 

    FileStream fileStream = new FileStream(@"k:\x1.gif", FileMode.Open);

    BinaryReader reader = new BinaryReader(fileStream, _encoding);

 

    byte[] bb=new byte[fileStream.Length];

    reader.Read(bb, 0, bb.Length);

   

    Encoding encoding = Encoding.GetEncoding(936);

string strTemp = encoding.GetString(bb);

 

    reader.Close();

    fileStream.Close();

    writer.WriteLine(strTemp);

    writer.Close();   

}

那么图片就被保存成了GB2312字符串。这个过程不可逆,因为其中的转换可能不是包含的关系。例如:FFAscii码环境下就会被?号所代替,然后还有其它例如BOM等因素,所以这种在GB2312下转换图片是不可逆的。(乱码不可怕,乱码其实不乱,它只是所在的字符集中的字符而已,但未转换前可能不是这个样子)

如果要把图片保存为文本串要保证:

·对于00FF间的字节都要有正确的表示,Ascii码就不行

·一定要是一个字节是一个字节。意思就是整个数组不能中间添加其它的字节

 

解决方法:

第一步,通过找00FF之间存在的都是一个字节的字符编码来实现,例如:ISO/IEC 8859-1字符集,它是第一个8位字符集,而ascii7位的,只能表示0—1278859-1的代码页为:28591

第二步,对字节进行Base64类似的变换。让中文下的环境支持编码,不要添加或删除字节。

 

写入到文本中的顺序是:ISO8859-1字串——Base64字串——gb2312串(默认)

从文本到图片的顺序是:gb2312字串(默认)——Base64字串——ISO8859-1字串

 

写入到文本:

public void TestReadPic()

{

    //1 iso

    Encoding _encoding = Encoding.GetEncoding(28591);

    StreamReader sr = new StreamReader(@"k:\x1.gif", _encoding);

    string strTemp=sr.ReadToEnd();

    sr.Close();

 

    //2 base64

    byte[] bb = _encoding.GetBytes(strTemp);

    string strBase64 = Convert.ToBase64String(bb);

 

    StreamWriter writer = File.CreateText(@"k:\MixTest.txt");

    writer.Write(strBase64);

    writer.Close();

}

 

保存的Base64字串(ANSI编码下,在中文系统中,ANSIGB2312)中的一段:

 

R0lGODlhZABkAPcAAAAAM8FvZ2ItH//pvF0qIHpQbjMzM/

LNr2tjQ4GAntKypPDp60lCRmg2KTQYUh4E

……

 

然后是从文本文件到图片:

public void TestWritePic()

{

    //1 base64

    Encoding _encoding = Encoding.GetEncoding(936);

    StreamReader sr = new StreamReader(@"k:\MixTest.txt", _encoding);

    string strBase64 = sr.ReadToEnd();

    sr.Close();

 

    //2 ISO

    byte[] bb = Convert.FromBase64String(strBase64);//iso字节

    Encoding encoding = Encoding.GetEncoding(28591);

    string strReturn = encoding.GetString(bb);

   

    FileStream fs = File.Create(@"k:\MixTest3.gif");

    fs.Write(bb, 0, bb.Length);

    fs.Close();

}

 

图片是正常的。

 

图文混排的方式也在以上的基础上实现了。

 

以上就是数据存放的方式,以及在.net环境下进行的字符编码以及流之间的转化工作。

posted on 2010-03-30 14:21  梅桦  阅读(783)  评论(0编辑  收藏  举报