一、简单介绍以下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. 安装配置 Android Studio

    概述 Android Studio 本身应该是开箱即用的,但是由于 dl.google.com 访问太慢,导致了这样那样的问题,因此我们只需要改一下 hosts 就行了 具体步骤 在Ping检测网站查 ...

  2. RGB颜色值

  3. Spring MVC(1)Spring MVC的初始化和流程以及SSM的实现

    一.Spring MVC概述 1.Spring MVC 的架构 对于持久层而言,随着软件的发展,迁移数据库的可能性很小,所以在大部分情况下都用不到Hibernate的HQL来满足迁移数据库的要求.与此 ...

  4. Vuforia添加虚拟按键

    AR虚拟按键为真实识别图上的按键,通过按键可以实现真实与虚拟之间的按键交流 (一)添加按键 点击target,打开advance,添加虚拟按键,即可在此target下添加虚拟按键 注:虚拟按键无法旋转 ...

  5. (一)初识EasyTouch

    Easy Touch是一个手指触控(可以鼠标)的插件,可以非常方便的实现各种功能,使用插件第一步是添加Easy Touch组件,可以右键添加也可以在一个空的游戏物体上添加Easy Touch脚本(非事 ...

  6. django-模板之with标签(十二)

    就是给传过来的值取个别名.

  7. fenby C语言 P32

    a[0] a[0][0] a[0][1] a[0][2] a[1] a[1][0] a[1][1] a[1][2]//一维数组 int a[2][3]//二维数组int (*p)[3]=a; #inc ...

  8. java 项目时间和服务器时间不一致

    今天线上项目关于时间的几个任务都出了问题,查看日志发现日志的时间不对,用的是log4j,日志输出的时间都早了很长时间. 1 首先先登上服务器查看了服务器的系统时间 linux下 date命令 时间正确 ...

  9. 为什么磁盘慢会导致Linux负载飙升?

    一.CPU利用率和负载率的区别 这里要区别CPU负载和CPU利用率,它们是不同的两个概念,但它们的信息可以在同一个top命令中进行显示.CPU利用率显示的是程序在运行期间实时占用的CPU百分比,这是对 ...

  10. Go调用cpp类

    CGO是C语言和Go语言之间的桥梁,所以GO是没有办法直接使用CPP的类的. 我们可以通过增加一族C语言函数接口作为CPP类和CGO之前的桥梁的,这样 就可以实现C和Go之间的互联. my_buffe ...