最近在写一段代码,将本地文件压缩加密后发送到服务器,发送到服务器的类用一个输入流作为参数获取要上传的数据,而压缩类和加密类都是输出流。

如何将输出流转换为输入流,最直观的方法是缓存输出流的全部内容到内存或文件中,但是当数据变大的时候,这两种方法显然都不太合适。

通过使用管道,可以将一个输出流转换为输入流。管道是一个操作系统功能,由一个循环缓存区构成,用于进程间通信,将一个进程的输出做为另一个进程的输入,Linux命令行脚本大量的用到管道通信,Windows同样也支持管道。.net对管道有封装的类,使用管道,在两个线程间通信,将一个进程的输出传递到另一个进程作为输入,.net中管道类继承自Stream类,可以将输出流无缝衔接到输入流。

参照AnonymousPipeClientStream类和AnonymousPipeServerStream类的文档,将进程间通信改为线程间通信,就实现了在一个应用程序中将输出类转换为输入类的功能,代码如下:

         [TestMethod]
public void OutputStream2InputStreamUsingPipe()
{
int iStreamSize = * ; var t = new Thread((data) =>
{
using (var pipe = new AnonymousPipeClientStream(
PipeDirection.Out, (string)data))
{
for (var i = ; i < iStreamSize; i++)
pipe.WriteByte((byte)'A');
}
}); using (var ms = new MemoryStream())
{
using (var pipe = new AnonymousPipeServerStream(
PipeDirection.In, HandleInheritability.Inheritable))
{
t.Start(pipe.GetClientHandleAsString());
var buffer = new byte[ * ];
int len;
while ((len = pipe.Read(buffer, , buffer.Length)) > )
{
Thread.Sleep();
ms.Write(buffer, , len);
}
}
t.Join();
Assert.AreEqual(iStreamSize, ms.Length);
}
}

在上述代码中在一个新建线程中向管道的一端写入数据,在主线程中从管道的另一端读取数据。如果写入前和读取后都需要对数据进行处理的话,若能将数据处理工作分配到两个线程上,既解决了流转换的问题,而且如果数据处理工作占用CPU很多的话双线程带来的效率提升不仅会抵消掉使用管道带来的开销,还能进一步提升整体效率,一举两得。

代码中Thread.Sleep(100)明确地使管道的写入和读取不同步,以验证管道的功能:当读取线程进入Sleep状态时,管道缓冲区被写满(windows和linux下缓存区可能都是一个内存页4K),写入操作被阻塞。

在.NET中使用管道将输出流转换为输入流的更多相关文章

  1. Angular4中常用管道(转载)

    Angular4中常用管道 通常我们需要使用管道实现对数据的格式化,Angular4中的管道和之前有了一些变化,下面说一些常用的管道. 一.大小写转换管道 uppercase将字符串转换为大写 low ...

  2. Angular4中常用管道

    通常我们需要使用管道实现对数据的格式化,Angular4中的管道和之前有了一些变化,下面说一些常用的管道. 一.大小写转换管道 uppercase将字符串转换为大写 lowercase将字符串转换为小 ...

  3. java中PipedStream管道流通信详细使用(详解)

    多线程使用PipedStream 通讯 Java 提供了四个相关的管道流,我们可以使用其在多线程进行数据传递,其分别是 类名 作用 备注 PipedInputStream 字节管道输入流 字节流 Pi ...

  4. 详解Java中的IO输入输出流!

    目录 本片要点 基本分类 发展史 文件字符流 输出的基本结构 流中的异常处理 异常处理新方式 读取的基本结构 运用输入与输出完成复制效果 文件字节流 缓冲流 字符缓冲流 装饰设计模式 转换流(适配器) ...

  5. 如何在eclipse jee中创建Maven project并且转换为Dynamic web project

    如何在eclipse jee中创建Maven project并且转换为Dynamic web project 注意:该文档只针对以下eclipse版本,如图 为了方便,我将我本地的压缩包放在了微云网盘 ...

  6. 将html中的br换行符转换为文本输入中的换行符(转)

    PHP中的有个非常好的函数:nl2br(),将文本框中的换行转换为HTML页面的<br />,但是如何实现将html中的<br />换行符转换为文本框中的换行符呢?下面这几个方 ...

  7. Core 1.0中的管道-中间件模式

    ASP.NET Core 1.0中的管道-中间件模式 SP.NET Core 1.0借鉴了Katana项目的管道设计(Pipeline).日志记录.用户认证.MVC等模块都以中间件(Middlewar ...

  8. .NET客户端实现Redis中的管道(PipeLine)与事物(Transactions)

    序言 Redis中的管道(PipeLine)特性:简述一下就是,Redis如何从客户端一次发送多个命令,服务端到客户端如何一次性响应多个命令. Redis使用的是客户端-服务器模型和请求/响应协议的T ...

  9. SQL零星技术点:SQL中转换money类型数值转换为字符串问题

    --SQL中转换money类型数值转换为字符串问题,直接转换就转为两位了,所以需要做一下处理.具体请看下述sql实例. 1 create table #test(price money) insert ...

随机推荐

  1. MongoDB 分页查询的方法及性能

    最近有点忙,本来有好多东西可以总结,Redis系列其实还应该有四.五.六...不过<Redis in Action>还没读完,等读完再来总结,不然太水,对不起读者. 自从上次Redis之后 ...

  2. RSA密钥之C#格式与Java格式转换

    前言 最近由于项目需求,服务端由c#编写,客户端由java编写.通信数据使用RSA非对称加密.但是java和c#生成的密钥格式是不一样的,所以需要转换格式才可以正常使用.网上搜到使用java进行格式转 ...

  3. Python 学习第十九天 django知识

    一,django 知识总结 1,同一个name属性的标签,多个值获取 <form action="/login/" method="POST" encty ...

  4. Eclipse导入到最新版Android Studio详解

    说到使用AndroidStudio,除了新建的项目,我们都会面临的问题是原先Eclipse的代码该怎么导入到AndroidStudio中使用.这方面相关的资料还比较少,自己摸索了一下,总结出这篇博客, ...

  5. java网络编程1

    Socket的构造方法包括: 1.Socket(),无参构造方法: 2.Socket(InetAddress address,int port) throws UnknownHostException ...

  6. getSlotFromBufferLocked: unknown buffer: 0xf3d94ca0

    安卓6.0模拟器导致,换一个模拟器解决

  7. eclipse的maven项目,如何使用java run main函数

    项目使用maven管理,一般说来就使用jetty:run了.但是对于做功能测试和集成测试的用例,需要使用自定义的quickrun来运行进行测试环境的参数设定和功能隔离,google一番发现maven有 ...

  8. css3实现圆形逐渐减少动画

    写这个动画刚开始完全没有思路,后来参考网上的资料发现可以用半圆实现,具体原理如下: 1.,一个div作为背景,三个div做出三个半圆出来,一个用于旋转,一个靠左(用于与背景吻合),一个靠右(用于与背景 ...

  9. Python爬虫学习(10):Selenium的好基友PhantomJS

    上一节中我们学习了selenium,用python来操作浏览器,在做网页自动化测试的时候最好不过了 .如果我们来做爬虫用一个带界面的浏览器似乎不太好吧,那可咋办呢?别着急,下来我们要介绍的就是一款不带 ...

  10. 半吊子学习Swift--天气预报程序-准备工作

    MacBookPro买完快半年了,当初想着买个本本学点ios,买完就看了几天的教程[捂脸],最近发现人都要废了,想重新开始学习Swift并将每天的进程通过博客发布来督促自己. 由于文笔不好,接触Swi ...