41、Web Streams、Serialization与Isolated Storage技术详解

Web Streams、Serialization与Isolated Storage技术解析

Web Streams、Serialization与Isolated Storage技术详解

1. Web Streams

在开发中,将异步文件读取与异步网络读取相结合,能够创建出可扩展的应用程序,以处理多个客户端的请求。而Web Streams允许我们直接从互联网上的任何网页读取数据,而非局限于自定义服务器提供的流。

1.1 WebRequest与WebResponse

WebRequest是一个用于请求由URI标识的资源的对象,比如网页的URL。我们可以使用WebRequest对象创建一个WebResponse对象,该对象将封装URI指向的对象。具体操作步骤如下:
1. 创建WebRequest对象:

HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("http://www.libertyassociates.com/book_edit.htm");

这里的 Create 方法是 WebRequest 的静态方法,根据传入的URI创建相应的 HttpWebRequest 对象,但返回类型为 WebRequest ,所以需要进行强制类型转换。
2. 获取WebResponse对象:

HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();

1.2 获取流并读取网页内容

通过调用 WebResponse 对象的 GetResponseStream 方法,我们可以获取封装网页内容的流,然后使用 StreamReader 读取该流。示例代码如下:

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace ReadingWebPageAsHTML
{
    public class Client
    {
        static public void Main(string[] Args)
        {
            // create a webRequest for a particular page
            HttpWebRequest webRequest =
                (HttpWebRequest)WebRequest.Create
                    ("http://www.jesseliberty.com/");
            // ask the web request for a webResponse encapsulating
            // that page
            HttpWebResponse webResponse =
                (HttpWebResponse)webRequest.GetResponse();
            // get the streamReader from the response
            StreamReader streamReader = new StreamReader(
                webResponse.GetResponseStream(), Encoding.ASCII);
            try
            {
                string outputString;
                outputString = streamReader.ReadToEnd();
                Console.WriteLine(outputString);
            }
            catch
            {
                Console.WriteLine("Exception reading from web page");
            }
            streamReader.Close();
        }
    }
}

这个功能可用于屏幕抓取,即把网页内容读取到缓冲区,然后提取所需信息。但要注意,所有屏幕抓取示例都假定你已获得该网站的版权许可。

1.3 流程图

graph TD;
    A[创建WebRequest对象] --> B[获取WebResponse对象];
    B --> C[获取流];
    C --> D[使用StreamReader读取流];

2. Serialization

当对象被流式传输到磁盘、存储在数据库中或跨上下文、应用程序域、进程或机器边界进行封送时,其各个成员数据必须进行序列化,即作为一系列字节写入流中。

2.1 可序列化对象

默认情况下,类型是不可序列化的。要使对象可序列化,必须使用 [Serializable] 属性显式标记它。如果对象仅由基本类型组成,CLR可以直接进行序列化;但如果包含其他用户定义的类型,这些类型也必须是可序列化的。

2.2 使用格式化器

在.NET应用程序中,序列化数据的格式通常为原生二进制格式或SOAP。SOAP是一种基于XML的简单轻量级协议,用于在Web上交换信息。CLR提供了 SoapFormatter 用于Web服务,以及 BinaryFormatter 用于快速本地存储或远程处理。

2.3 示例:序列化和反序列化对象

以下是一个名为 SumOf 的类的示例,用于演示序列化和反序列化的过程:

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

namespace SerializingDeserializingAnObject
{
    [Serializable]
    class SumOf
    {
        private int startNumber = 1;
        private int endNumber;
        private int[] theSums;

        public static void Main()
        {
            Console.WriteLine("Creating first one with new...");
            SumOf app = new SumOf(1, 10);
            Console.WriteLine("Creating second one with deserialize...");
            SumOf newInstance = SumOf.DeSerialize();
            newInstance.DisplaySums();
        }

        public SumOf(int start, int end)
        {
            startNumber = start;
            endNumber = end;
            ComputeSums();
            DisplaySums();
            Serialize();
        }

        private void ComputeSums()
        {
            int count = endNumber - startNumber + 1;
            theSums = new int[count];
            theSums[0] = startNumber;
            for (int i = 1, j = startNumber + 1; i < count; i++, j++)
            {
                theSums[i] = j + theSums[i - 1];
            }
        }

        private void DisplaySums()
        {
            foreach (int i in theSums)
            {
                Console.WriteLine("{0}, ", i);
            }
        }

        private void Serialize()
        {
            Console.Write("Serializing...");
            // create a file stream to write the file
            FileStream fileStream =
                new FileStream("DoSum.out", FileMode.Create);
            // use the CLR binary formatter
            BinaryFormatter binaryFormatter =
                new BinaryFormatter();
            // serialize to disk
            binaryFormatter.Serialize(fileStream, this);
            Console.WriteLine("...completed");
            fileStream.Close();
        }

        public static SumOf DeSerialize()
        {
            FileStream fileStream =
                new FileStream("DoSum.out", FileMode.Open);
            BinaryFormatter binaryFormatter =
                new BinaryFormatter();
            SumOf retVal = (SumOf)binaryFormatter.Deserialize(fileStream);
            fileStream.Close();
            return retVal;
        }
    }
}

2.4 处理瞬态数据

在某些情况下,序列化数组可能是浪费的,因为可以根据起始和结束数字计算数组内容。我们可以使用 [NonSerialized] 属性标记不需要序列化的数据,但反序列化时需要实现 IDeserializationCallback 接口来修复对象。示例代码如下:

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

namespace WorkingWithNonSerializedObject
{
    [Serializable]
    class SumOf : IDeserializationCallback
    {
        private int startNumber = 1;
        private int endNumber;
        [NonSerialized]
        private int[] theSums;

        public static void Main()
        {
            Console.WriteLine("Creating first one with new...");
            SumOf app = new SumOf(1, 5);
            Console.WriteLine("Creating second one with deserialize...");
            SumOf newInstance = SumOf.DeSerialize();
            newInstance.DisplaySums();
        }

        public SumOf(int start, int end)
        {
            startNumber = start;
            endNumber = end;
            ComputeSums();
            DisplaySums();
            Serialize();
        }

        private void ComputeSums()
        {
            int count = endNumber - startNumber + 1;
            theSums = new int[count];
            theSums[0] = startNumber;
            for (int i = 1, j = startNumber + 1; i < count; i++, j++)
            {
                theSums[i] = j + theSums[i - 1];
            }
        }

        private void DisplaySums()
        {
            foreach (int i in theSums)
            {
                Console.WriteLine("{0}, ", i);
            }
        }

        private void Serialize()
        {
            Console.Write("Serializing...");
            // create a file stream to write the file
            FileStream fileStream =
                new FileStream("DoSum.out", FileMode.Create);
            // use the CLR binary formatter
            BinaryFormatter binaryFormatter =
                new BinaryFormatter();
            // serialize to disk
            binaryFormatter.Serialize(fileStream, this);
            Console.WriteLine("...completed");
            fileStream.Close();
        }

        public static SumOf DeSerialize()
        {
            FileStream fileStream =
                new FileStream("DoSum.out", FileMode.Open);
            BinaryFormatter binaryFormatter =
                new BinaryFormatter();
            SumOf retVal = (SumOf)binaryFormatter.Deserialize(fileStream);
            fileStream.Close();
            return retVal;
        }

        // fix up the nonserialized data
        public virtual void OnDeserialization(Object sender)
        {
            ComputeSums();
        }
    }
}

这个过程是一个典型的空间/时间权衡,不序列化数组可以减小文件大小,但可能会使反序列化速度变慢。

2.5 序列化与反序列化流程表格

步骤 操作 代码示例
1 创建可序列化类 [Serializable] class SumOf {...}
2 序列化对象 BinaryFormatter binaryFormatter = new BinaryFormatter(); FileStream fileStream = new FileStream("DoSum.out", FileMode.Create); binaryFormatter.Serialize(fileStream, this);
3 反序列化对象 FileStream fileStream = new FileStream("DoSum.out", FileMode.Open); BinaryFormatter binaryFormatter = new BinaryFormatter(); SumOf retVal = (SumOf)binaryFormatter.Deserialize(fileStream);

3. Isolated Storage

在开发应用程序时,有时需要存储永久的配置和状态数据,并且是基于每个用户的。这时,.NET Framework 提供的隔离存储就能派上用场。

3.1 隔离存储概述

隔离存储允许应用程序开发者基于每个用户来存储数据,它提供了传统 Windows .ini 文件或 Windows 注册表中 HKEY_CURRENT_USER 键的大部分功能。应用程序将数据保存到与应用程序关联的唯一数据隔舱中,CLR 通常使用文件系统上的目录来实现这个数据隔舱。管理员可以限制单个应用程序使用的隔离存储量,还可以通过安全机制防止不可信代码调用高可信代码来写入隔离存储。

隔离存储的重要之处在于,CLR 提供了一个标准的位置来存储应用程序的数据,但不强制或支持特定的数据布局或语法。通常,我们会以文本形式存储数据,常见的是键值对。它是保存用户配置信息(如登录名、各种窗口和小部件的位置等特定于应用程序和用户的信息)的好机制。数据为每个用户存储在单独的文件中,还可以通过区分代码的不同身份方面(按程序集或按源应用程序域)进一步隔离文件。

3.2 写入隔离存储

使用隔离存储写入数据相对简单,具体步骤如下:
1. 创建 IsolatedStorageFileStream 实例,初始化时指定文件名和文件模式(如创建、追加等)。
2. 在该文件上创建 StreamWriter
3. 像写入其他流一样写入数据。

以下是示例代码:

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Text;

namespace WritingToIsolatedStorage
{
    public class Tester
    {
        public static void Main()
        {
            Tester app = new Tester();
            app.Run();
        }

        private void Run()
        {
            // create the configuration file stream
            IsolatedStorageFileStream configFile =
                new IsolatedStorageFileStream
                    ("Tester.cfg", FileMode.Create);
            // create a writer to write to the stream
            StreamWriter writer =
                new StreamWriter(configFile);
            // write some data to the config. file
            String output;
            System.DateTime currentTime = System.DateTime.Now;
            output = "Last access: " + currentTime.ToString();
            writer.WriteLine(output);
            output = "Last position = 27,35";
            writer.WriteLine(output);
            // flush the buffer and clean up
            writer.Close();
            configFile.Close();
        }
    }
}

运行此代码后,在硬盘上搜索 Tester.cfg 文件,它可能位于类似以下的路径:

C:\Documents and Settings\Jesse\Local Settings\Application Data\
IsolatedStorage\mipjwcsz.iir\2hzvpjcc.p0y\StrongName.
mwoxzllzqpx3u0taclp1dti11kpddwyo\Url.a2f4v2g3ytucslmvlpt2wmdxhrhqg1pz\
Files

3.3 读取隔离存储

要读取隔离存储中的数据,可按以下步骤操作:
1. 重新打开文件,创建 IsolatedStorageFileStream 实例。
2. 创建 StreamReader 对象。
3. 使用标准的流操作读取文件内容。

示例代码如下:

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Text;

namespace WritingToIsolatedStorage
{
    public class Tester
    {
        private void Run()
        {
            // open the configuration file stream
            IsolatedStorageFileStream configFile =
                new IsolatedStorageFileStream
                    ("Tester.cfg", FileMode.Open);
            // create a standard stream reader
            StreamReader reader =
                new StreamReader(configFile);
            // read through the file and display
            string theEntry;
            do
            {
                theEntry = reader.ReadLine();
                Console.WriteLine(theEntry);
            } while (theEntry != null);
            reader.Close();
            configFile.Close();
        }
    }
}

3.4 隔离存储操作流程图

graph TD;
    A[创建IsolatedStorageFileStream] --> B[创建StreamWriter];
    B --> C[写入数据];
    C --> D[关闭流];
    E[打开IsolatedStorageFileStream] --> F[创建StreamReader];
    F --> G[读取数据];
    G --> H[关闭流];

3.5 隔离存储操作步骤表格

操作类型 步骤 代码示例
写入 1. 创建 IsolatedStorageFileStream
2. 创建 StreamWriter
3. 写入数据
4. 关闭流
IsolatedStorageFileStream configFile = new IsolatedStorageFileStream("Tester.cfg", FileMode.Create); StreamWriter writer = new StreamWriter(configFile); writer.WriteLine("Last access: " + System.DateTime.Now.ToString()); writer.Close(); configFile.Close();
读取 1. 打开 IsolatedStorageFileStream
2. 创建 StreamReader
3. 读取数据
4. 关闭流
IsolatedStorageFileStream configFile = new IsolatedStorageFileStream("Tester.cfg", FileMode.Open); StreamReader reader = new StreamReader(configFile); string theEntry; do { theEntry = reader.ReadLine(); Console.WriteLine(theEntry); } while (theEntry != null); reader.Close(); configFile.Close();

综上所述,Web Streams、Serialization 和 Isolated Storage 是.NET 开发中非常有用的技术。Web Streams 让我们能够方便地从互联网上的网页读取数据;Serialization 帮助我们将对象进行序列化和反序列化,以便在不同场景下存储和传输;Isolated Storage 则为我们提供了一种安全、方便的方式来存储每个用户的配置和状态数据。通过合理运用这些技术,我们可以开发出更强大、更灵活的应用程序。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值