一、简单介绍以下BufferedStream

在前几章的讲述中,我们已经能够掌握流的基本特性和特点,一般进行对流的处理时,系统肩负着IO所带来的开销,调用十分频繁,这时候就应该想个办法减少这种开销,而且必须在已有的Stream进行扩展,有了以上2点要求,那么我们今天的主题BufferedStream闪亮登场了。BufferedStream能够实现流的缓存,换句话说也就是在内存中能够缓存一定的数据而不是时时给系统带来负担,同时BufferedStream可以对缓存中的数据进行写入或读取,所以对流的性能带来一定的提升,但是无法同时进行读取或写入工作,如果不使用缓冲区也行,BufferedStream能够保证不用缓冲区时不会降低因缓冲区带来的读取或写入性能的下降

二、如何理解缓冲区

缓冲区是内存中的一块连续区域,用来缓存或临时存储数据,也就是说可以通过缓冲区逐步对数据进行读取或写入操作。BufferedStream中的缓冲区可以由用户设定,其表现形式为Byte数组,想象下没有缓冲区将是多么的可怕,假如我们的非固态硬盘没有缓冲区,如果我们下载速度达到惊人的10m左右,那么下载一个2G或者更大的文件时,磁头的读写是非常的频繁,直接的结果是磁头寿命急剧减少,甚至将硬盘直接烧毁或损坏。

三、BufferedStream的优势

理解了缓冲区的重要性后,让我们再来谈一下BufferedStream的优势,首先大家肯定觉得疑惑,为什么MemoryStream同样也是在内存中对流进行操作,和BufferedStream有什么区别呢?BufferedStream并不是将所有内容都存放到内存中,而MemoryStream则是,BufferedStream必须跟其他流如FileStream结合使用,而MemoryStream则不需要,聪明的你肯定能够想到,BufferedStream必然类似于一个流的包装类,对流进行“缓存功能的扩展包装”,所以BufferedStream的优势不仅体现在其原有的缓存功能上,更体现在如何帮助原有的类实现其功能上的扩展层面上。

四、BufferedStream的构造

1、BufferedStream(Stream stream)

其实BufferedStream的构造主要功能还是设置缓冲区大小,如果没有制定则默认是用4096字节的进行初始化

2、BufferedStream(Stream stream, int i)

第二个参数是手动制定缓冲区大小,第一次使用此构造函数初始化BufferedStream对象时分配共享读/写缓冲区。如果所有的读和写大小都等于缓冲区大小,则不使用共享缓冲区、

五、BufferedStream的属性

1、CanRead已重写。

获取一个值,该值指示当前流是否支持读取。如果支持读取,则为true;如果流已关闭或者时通过只读访问方式打开的,则为false;如果Stream派生的类不支持读取,则对StreamRerader、StringReader、TextReader的Read、ReadByte、BeginRead、EndRead和Peek方法的调用将引发NotSupportedException。如果该流已关闭,则属性将返回false。

2、CanSeek已重写。

获取一个值,该值指示当前流是否支持查找。如果支持查找,则为true;如果流已关闭或者如果流是由操作系统句柄(如管道或者控制台的输出)构造的,则为false。如果从Stream派生的类不支持查找,即对Length、SetLength、Position和Seek的调用将引发NotSupportedException。如果该流已关闭,此属性将返回false。

3、CanWrite已重写。

获取一个值,该值指示当前流是否支持写入。如果支持写入,则为true;如果流已关闭或者通过只读方式打开的,则为false。如果从Stream派生的类不支持写入,则调用SetLength、Write或WriteByte将引发NotSupportedException。如果流已关闭,此属性将返回false。

4、Length已重写。

获取流的长度,长度以字节为单位。

5、Position已重写。

获取当前流内的位置。get访问器调用Seek获取基础流中的当前位置,然后根据缓冲区中的当前位置调整此值。set访问器将以前写入缓冲区的所有数据复制到基础流中,然后调用Seek。支持搜索到超出流长度的任何位置。

六、BufferedStream的方法

BufferedStream的方法基本上和Stream类一致,没有其独有的方法

七、简单示例:李用socket读取网页并保存在本地

     public class Server
{
//端口
private const int webPort = ;
//默认接收缓存大小
private byte[] receiveBufferBytes = new byte[];
//需要获取网页的url
private readonly string _webPageUrl; public Server(string webPageUrl)
{
_webPageUrl = webPageUrl;
} /// <summary>
/// 从网页上获取数据
/// </summary>
public void FetchWebPageData()
{
if (!string.IsNullOrWhiteSpace(_webPageUrl))
{
FetchWebPageData(_webPageUrl);
} Console.ReadLine();
} /// <summary>
/// 从网页上获取数据
/// </summary>
/// <param name="webPageUrl">网页Url</param>
private void FetchWebPageData(string webPageUrl)
{
//通过Url获取主机信息
IPHostEntry iphe = Dns.GetHostEntry(GetHostNameByStrUrl(webPageUrl));
Console.WriteLine($"远程服务器名:{iphe.HostName}");
//通过主机信息获取其IP
IPAddress[] address = iphe.AddressList;
IPEndPoint ipep = new IPEndPoint(address[], );
//实例化一个socket用于接收网页数据
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//连接
socket.Connect(ipep);
if (socket.Connected)
{
//发送头文件,这样次啊能下载网页数据
socket.Send(Encoding.ASCII.GetBytes(GetHeader(webPageUrl)));
}
else
{
return;
}
//接收头一批数据
var count = socket.Receive(receiveBufferBytes);
//转化为string
var getString = Encoding.Default.GetString(receiveBufferBytes);
//创建流文件
FileStream fs=new FileStream(@"f:\\test.html",FileMode.OpenOrCreate);
//创建缓存流
BufferedStream bs=new BufferedStream(fs);
using (fs)
{
using (bs)
{
byte[] finalContent = Encoding.Default.GetBytes(getString.ToCharArray());
//将头一批数据写入本地硬盘
bs.Write(finalContent,,finalContent.Length);
//循环通过socket接收数据
while (count > )
{
count = socket.Receive(receiveBufferBytes, receiveBufferBytes.Length, SocketFlags.None);
//直接将接收到的byte数据写入本地硬盘
bs.Write(receiveBufferBytes, , receiveBufferBytes.Length);
Console.WriteLine(Encoding.Default.GetString(receiveBufferBytes));
}
}
}
} /// <summary>
/// 得到Header
/// </summary>
/// <param name="webPageUrl"></param>
/// <returns></returns>
private string GetHeader(string webPageUrl)
{
return $"GET {GetRelativeUrlByStrUrl(webPageUrl)}HTTP/1.1\r\nHOST:{GetHostNameByStrUrl(webPageUrl)}\r\nConnection:Close\r\n\r\n";
} /// <summary>
/// 得到相对路径
/// </summary>
/// <param name="strUrl">网页url</param>
/// <returns></returns>
public string GetRelativeUrlByStrUrl(string strUrl)
{
var iIndex = strUrl.IndexOf(@"//", StringComparison.Ordinal);
if (iIndex <= )
{
return "/";
} var strTemp = strUrl.Substring(iIndex + );
iIndex = strTemp.IndexOf(@"/", StringComparison.Ordinal);
if (iIndex > )
{
return strTemp.Substring(iIndex);
} return "/";
} /// <summary>
/// 根据Url得到Host
/// </summary>
/// <param name="strUrl">网页Url</param>
/// <returns></returns>
public string GetHostNameByStrUrl(string strUrl)
{
var iIndex = strUrl.IndexOf(@"//", StringComparison.Ordinal);
if (iIndex <= )
{
return "";
} var strTemp = strUrl.Substring(iIndex + );
iIndex = strTemp.IndexOf(@"/", StringComparison.Ordinal);
if (iIndex > )
{
return strTemp.Substring(, iIndex);
} return strTemp;
}
}

好了,BufferedStream相关知识就分享到这里了。

【Stream—6】BufferedStream相关知识分享的更多相关文章

  1. 【Stream—7】NetworkStream相关知识分享

    一.NetworkStream的作用 和先前的流有所不同,NetworkStream的特殊性可以在它的命名空间中得以了解(System.Net.Sockets),聪明的你马上就会反应过来:既然是在网络 ...

  2. FileStream相关知识分享

    一.如何理解FIleStream 通过前3章的学些,相信大家对于Stream已经有一定的了解,但是又如何去理解FileStream呢?请看下图: 我们磁盘中的任何文件都是通过二进制数组组成,最为直观的 ...

  3. MemoryStream相关知识分享

    一.简单介绍一下MemoryStream MemoryStream是内存流,为系统内存提供读写操作,由于MemoryStream是通过无符号字节数组组成的,可以说MemoryStream的性能可以算比 ...

  4. StreamWriter 相关知识分享

    在介绍StreamWriter之前,我们首先来了解一下它的父类TextWriter. 一.TextWriter 1.TextWriter的构造函数和常用属性方法 下面是TextWriter的构造函数: ...

  5. XML的相关基础知识分享(二)

    前面我们讲了一下XML相关的基础知识(一),下面我们在加深一下,看一下XML高级方面. 一.命名空间 1.命名冲突 XML命名空间提供避免元素冲突的方法. 命名冲突:在XML中,元素名称是由开发者定义 ...

  6. XML的相关基础知识分享

    XML和Json是两种最常用的在网络中数据传输的数据序列化格式,随着时代的变迁,XML序列化用于网络传输也逐渐被Json取代,前几天,单位系统集成开发对接接口时,发现大部分都用的WebService技 ...

  7. 关于StreamReader的知识分享

    今天我们来简单的介绍一下StreamReader,在将StreamReader之前,我们先来了解一下他的父类:TextReader.对于TextReader,大家可能比较陌生,下面我们来看一下Text ...

  8. listener监听器的相关知识

    从别人的博客上我学习了listener的相关知识现在分享给大家 1.概念: 监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上 ...

  9. 【转】java NIO 相关知识

    原文地址:http://www.iteye.com/magazines/132-Java-NIO Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的 ...

随机推荐

  1. ESP8266开发之旅 网络篇⑯ 无线更新——OTA固件更新

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  2. 原来热加载如此简单,手动写一个 Java 热加载吧

    1. 什么是热加载 热加载是指可以在不重启服务的情况下让更改的代码生效,热加载可以显著的提升开发以及调试的效率,它是基于 Java 的类加载器实现的,但是由于热加载的不安全性,一般不会用于正式的生产环 ...

  3. 基础安全术语科普(四)——RFID

    RFID —— Radio Frequency Identification (射频识别技术) 概念:RFID属于一种无源技术(Passive Technology) 使用:生活中RFID无处不在.如 ...

  4. 《HTML5+CSS3+JavaScript 从入门到精通(标准版)》学习笔记(二)

    这是一个应用的例子,学以致用嘛 <!--这些代码我就直接放在了博客园的"页首Html代码"中,用于自定义博客,效果就是页面左上角的白色文字--> <p> & ...

  5. OptimalSolution(3)--链表问题(1)简单

    单链表Node节点类 public class Node { public int val; public Node next; public Node(int val) { this.val = v ...

  6. video2

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  7. dbms_job基础

    a.创建job: dbms_job.submit(jobno,what,next_date,interval);b.删除job: dbms_job.remove(jobno); c.修改要执行的操作: ...

  8. Mui 长按保存图片

    必须先要 引入 mui.js,然后参考具体代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8 ...

  9. PhpStudy2018后门漏洞预警及漏洞复现&检测和执行POC脚本

    PhpStudy2018后门漏洞预警及漏洞复现&检测和执行POC脚本 phpstudy介绍 Phpstudy是国内的一款免费的PHP调试环境的程序集成包,其通过集成Apache.PHP.MyS ...

  10. CSPS模拟 86

    看见异或两个字就孩怕 T1 按位? T2 这道异或稍水啊233 貌似可以打表找找规律 emm七种转移,有重复刷表 优化一下? T3 skyh已经接了2杯水了(实际情况他已经ak了) cbx开始抬头傻笑 ...