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
  • 相关阅读:
    C#生成满足特定要求的密码
    抽象方法(abstract method) 和 虚方法 (virtual method), 重载(overload) 和 重写(override)的区别于联系
    面试问题 ---C#中的委托
    面试问题
    如何用DOS命令,获取一个目录下的文件数目
    vim怎么把一个写的代码文件另存到任意文件夹里?
    WIN7 不用格式化磁盘怎么把FAT32系统改成NTFS系统
    rhel6 中安装使用finger命令
    Redhat enterpise6 安装unix2dos/dos2unix
    阐述Linux操作系统之rpm五种基本操作
  • 原文地址:https://www.cnblogs.com/xchit/p/socket_7.html
Copyright © 2011-2022 走看看