• 消息(1)——数据的保存与脱机状态下的数据传输


    数据怎么传递?

    在两个终端之间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环境下进行的字符编码以及流之间的转化工作。

    博客园大道至简

    http://www.cnblogs.com/jams742003/

    转载请注明:博客园

  • 相关阅读:
    python之路day10命名空间和作用域、函数嵌套,作用域链、闭包
    20200719 千锤百炼软工人第十四天
    20200720 千锤百炼软工人第十五 天
    JavaScript中基本数据类型和引用数据类型的区别
    js 经纬度坐标格式化 度分秒转度 度转度分秒
    export ,export default 和 import 区别 以及用法
    10月28日学习日志
    10月20日学习日志
    10月29日学习日志
    10月27日学习日志
  • 原文地址:https://www.cnblogs.com/jams742003/p/1700605.html
Copyright © 2020-2023  润新知