zoukankan      html  css  js  c++  java
  • 七、数据流

      流(stream)是对串行传输的数据(以字节为单位)的一种抽象表示,底层的设备可以是文件、外部设备、主存、网络套接字等。

      流提供三种基本操作:

        写入:将数据从内存缓冲区传输到外部源。

        读取:将数据从外部源传输到内存缓冲区。

        查找:重新设置流的当前位置,以便随机读写。需要注意的是,并不是所有的流类型都能够支持查找,例如,网络流没有当前位置的统一概念,因此一般不支持查找。

        说明:Stream类提供有多种操作流的方法,其中Read和Write方法是Stream类及其派生类都提供的实现,可支持在字节级别上对数据进行读写。

    文件流(FileStream类)

        FileStream类继承于Stream类,一个FileStream类的实例实际上代表一个磁盘文件,使用FileStream类可以对文件系统上的文件进行读取、写入、打开和关闭操作。

        1、创建FileStream实例

           (1)常用的构造函数具有三个参数,例如: 

          FileStream(string path, FileMode mode, FileAccess access)

        FileMode值用于指定当文件不存在时是否创建该文件,并确定是保留还是改写现有文件的内容

        FileAccess值是枚举的一个成员,它控制对文件的访问权限

        File和FileInfo类也提供了创建FileStream对象的方法。其中,OpenRead方法返回只读文件流,OpenWrite方法返回只写文件流。

        例如:FileStream fs= File.OpenRead("C:\File1.txt");

      2. 读文件

        在获取FileStream实例之后,可利用FileStream对象的Read方法读取文件中的数据。该方法用于从流中读取字节块并将该数据写入给定字节数组中。

        其语法形式为:

        public override int Read(byte[] array,int offset, int count)

        array : 存储从文件流中读取的数据。

        offset : array字节数组中开始写入数据的下标,一般为0。

        size : 要从文件流中读出字节的大小

        返回值: 从FileStream中读取的字节数。

     FileStream fs;
                //读取文件所在路径
                String filePath = "d:\test.txt";
    
                //打开文件
                try
                {
                    fs = new FileStream(filePath, FileMode.Open);
                }
                catch
                {
                    Console.WriteLine("文件打开失败");
                    return;
                }
                //尚未读取的文件内容长度
                long left = fs.Length;
                //存储读取结果
                byte[] bytes = new byte[100];
                //每次读取长度
                int maxLength = bytes.Length;
                //读取位置
                int start = 0;
                //实际返回结果长度
                int num = 0;
                //当文件未读取长度大于0时,不断进行读取
                while (left > 0)
                {
                    fs.Position = start;
                    num = 0;
                    if (left < maxLength)
                    {
                        num = fs.Read(bytes, 0, Convert.ToInt32(left));
                    }
                    else
                    {
                        num = fs.Read(bytes, 0, maxLength);
                    }
                    if (num == 0)
                    {
                        break;
                    }
                    start += num;
                    left -= num;
                    Console.WriteLine(Encoding.UTF8.GetString(bytes));
                }
                Console.WriteLine("end of file");
                Console.ReadLine();
                fs.Close();
    View Code

      3. 写文件 Stream类及其所有子类都提供了Write方法,FileStream类也不例外。该方法可将字节数组写入流。

        语法形式为

     public override void Write (
    
            byte[] buffer, //包含要写入流的数据
    
            int offset, // buffer中开始写入数据的位置
    
            int size //要写入流的字节数
    
          )

    Demo:

    FileStream fs = null;
                String filePath = "d:\test.txt";
                //将待写入数据从字符串转换为字节数组
                Encoding encoder = Encoding.UTF8;
                Byte[] bytes = encoder.GetBytes("HelloWorld!
    
    ");
                try
                {
                    fs = File.OpenWrite(filePath);
                    //设定书写的开始位置为文件的末尾
                    fs.Position = fs.Length;
                    //将待写入内容追加到文件末尾
                    fs.Write(bytes, 0, bytes.Length);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("文件打开失败{0}", ex.ToString());
                }
                finally
                {
                    fs.Close();
                }
                Console.ReadLine();
    View Code

    内存流(MemoryStream类)

      MemoryStream类表示的是保存在内存中的数据流。由内存流封装的数据可以在内存中直接访问。 MemoryStream类的构造函数具有多种重载形式,常用的构造函数有:

        (1)MemoryStream () 该构造函数初始分配的容量大小为0,随着数据的不断写入容量可以不断扩展。

        (2)MemoryStream (Byte[]) 该构造函数获取的MemoryStream实例根据Byte[]字节数组进行初始化,并且实例容量大小固定即为字节数组的长度。由于实例的容量不

        能扩展,该构造函数一般用于数据不发生变化的场合。

            Encoding encoder = Encoding.UTF8;
                String testdata = "测试数据";
                char[] chars = testdata.ToCharArray();
                Byte[] bytes = new Byte[encoder.GetByteCount(chars, 0, chars.Length)];
                MemoryStream mem = new MemoryStream(bytes);

        (3)MemoryStream (int capacity) 通过该构造函数创建初始容量大小为capacity的实例,并且实例容量大小可扩展。

     //构造MemoryStream实例,并输出初始分配容量及使用量大小
                MemoryStream mem = new MemoryStream();
                Console.WriteLine("初始分配容量:{0}", mem.Capacity);
                Console.WriteLine("初始使用量:{0}", mem.Length);
    
                //将待写入数据从字符串转换为字节数组
                UnicodeEncoding encoder = new UnicodeEncoding();
                Byte[] bytes = encoder.GetBytes("新增数据");
    
                //向内存流中写入数据
                for (int i = 1; i < 4; i++)
                {
                    Console.WriteLine("第{0}写入新数据", i);
                    mem.Write(bytes, 0, bytes.Length);
                }
    
                //写入数据后MemoryStream实例的容量和使用量大小
                Console.WriteLine("当前分配容量:{0}", mem.Capacity);
                Console.WriteLine("当前使用量:{0}", mem.Length);
                Console.ReadLine();
    View Code

    网络流(NetworkStream类)

      在System.Net.Sockets名称空间中有一个NetworkStream类,用于通过网络套接字发送和接收数据。

      NetworkStream类支持对网络数据的同步或异步访问,它可被视为在数据来源端和接收端之间架设了一个数据通道. 只用于面向连接的数据传输

      写入操作是指从来源端内存缓冲区到网络上的数据传输;

      读取操作是从网络上到接收端内存缓冲区(如字节数组)的数据传输。

      NetworkStream的用法

      1、构造NetworkStream:

      (1)利用TcpClient获取网络流对象,例如:

           TcpClient tcpClient = new TcpClient();
                tcpClient.Connect("www.abcd.com", 51888);
                NetworkStream networkStream = tcpClient.GetStream();

      (2)利用Socket获取网络流对象,例如:

          NetworkStream myNetworkStream = new NetworkStream(mySocket);

      2、发送数据

     public override void Write(byte[] buffer, int offset, int size)
            {
                if (networkStream.CanWrite)
                {
                    byte[] myWriteBuffer = Encoding.ASCII.GetBytes("测试信息");
                    networkStream.Write(myWriteBuffer, 0, myWriteBuffer.Length);
                }
            }

      3、接收数据

    public override int Read (
                byte[] buffer,  //buffer:内存中用于存储从NetworkStream读取的数据的位置。
                int offset,     //offset:buffer 中开始将数据存储到的位置。
                int size        //Size:要从NetworkStream中读取的字节数。
            ) 

    StreamWriter与StreamReader类

        StreamReader类主要完成以一种特定的编码从流中读取字符的功能,一般用于对文本数据的读取操作;

        StreamWriter类则主要以特定的编码向流中写入字符,一般用于对文本数据的写操作。

      1、创建StreamWriter实例

           //(1)StreamWriter(String path)
                StreamWriter sw= new StreamWriter(@"D:	est.txt");
                //(2)File及FileInfo类提供的CreateText方法
                StreamWriter sw = File.CreateText(@"D:	est.txt");
                //(3)StreamWriter(Stream stream)
                FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite);
                StreamWriter sw = new StreamWriter(fs);
                NetworkStream networkStream = client.GetStream();
                StreamWriter sw = new StreamWriter(networkStream);  

      2、写入文本:

     StreamWriter sw = null;
                String strPath = @"D:	est.txt";
                try
                {
                    sw = new StreamWriter(strPath);
                    sw.WriteLine("当前时间为{0}", DateTime.Now);
                    Console.WriteLine("写文件成功!");
                }
                catch (Exception ex)
                {
    
                    Console.WriteLine("写文件失败:{0}", ex.ToString());
                }
                finally
                {
                    if (sw != null)
                        sw.Close();
                }
    View Code

      3.创建StreamReader实例

    1)SteamReader (Stream stream)
        利用流对象创建SteamReader对象。例如:
        NetworkStream networkStream = client.GetStream();
        SteamReader sr = new SteamReader (networkStream)
    (2)SteamReader (String path)
        如果需要处理的是文件流,则可以根据文件路径创建一个以UTF8编码的SteamReader对象。例如:
        SteamReader sr = new SteamReader ("D:\test.txt");

      4.读取文本

           String s = "";
                using (StreamReader sr = new StreamReader("D:\test.txt"))
                {
                    s = sr.ReadToEnd();
                }
                //using块结束,StreamReader对象占用资源被释放。
                Console.WriteLine(s);
                Console.ReadLine();

    BinaryReader与BinaryWrite类

      BinaryReaderBinaryWriter类,用于以二进制模式读写流。  

      它们提供的一些读写方法是对称的,比如针对不同的数据结构,   

      BinaryReader提供了ReadByte、ReadBoolean、ReadInt、ReadInt16、ReadDouble、ReadString等方法,

      与之对应BinaryWriter则提供了多个重载Write方法。  

      例如当Write方法传递的参数为Int32类型时,

      BinaryWriter类的Write方法将Int32类型数据转化为长度为4的字节数组,并将字节流传递给一个Stream对象。 

    // 为文件打开一个二进制编写器。
                FileStream fs;
                fs = new FileStream("D:\BinFile.dat", FileMode.OpenOrCreate, FileAccess.ReadWrite);
                BinaryWriter bw = new BinaryWriter(fs);
    
                // 准备不同类型的数据。
                double aDouble = 1234.67;
                int anInt = 34567;
                char[] aCharArray = { 'A', 'B', 'C' };
    
                // 利用Write方法的多种重载形式写入数据
                bw.Write(aDouble);
                bw.Write(anInt);
                bw.Write(aCharArray);
                int length = Convert.ToInt32(bw.BaseStream.Length);
                fs.Close();
                bw.Close();
    
    
                //读取并输出数据
                fs = new FileStream("D:\BinFile.dat", FileMode.OpenOrCreate, FileAccess.Read);
                BinaryReader br = new BinaryReader(fs);
                Console.WriteLine(br.ReadDouble().ToString());
                Console.WriteLine(br.ReadInt32().ToString());
    
                char[] data = br.ReadChars(length);
                for (int i = 0; i < data.Length; i++)
                {
                    Console.Write("{0,7:x} ", data[i]);
                }
                fs.Close();
                br.Close();
                Console.ReadLine();
    View Code
  • 相关阅读:
    Elasticsearch Query DSL 整理总结(三)—— Match Phrase Query 和 Match Phrase Prefix Query
    Elasticsearch Query DSL 整理总结(二)—— 要搞懂 Match Query,看这篇就够了
    Elasticsearch Query DSL 整理总结(一)—— Query DSL 概要,MatchAllQuery,全文查询简述
    Elasticsearch Java Rest Client API 整理总结 (三)——Building Queries
    Elasticsearch date 类型详解
    python 历险记(五)— python 中的模块
    python 历险记(四)— python 中常用的 json 操作
    python 历险记(三)— python 的常用文件操作
    Elasticsearch Java Rest Client API 整理总结 (二) —— SearchAPI
    Elasticsearch Java Rest Client API 整理总结 (一)——Document API
  • 原文地址:https://www.cnblogs.com/xchit/p/socket_7.html
Copyright © 2011-2022 走看看