- 论坛徽章:
- 0
|
PipedInputStream类和PipedOutputStream类用于在应用程序中创建管道通信。一个PipedInputStream实例对象必须和PipedOutputStream实例对象进行连接而产生一个通信管道,PipedOutputsStream可以向管道中写入数据,PipedInputStream可以从管道中读取PipedOutputStream写入的数据,这两个类主要用来完成线程之间的通信,一个线程的PipedInputStream对象能够从另外一个线程的PipedOutputStream对象中读取数据。
下面来看一个两个线程互相通信的例子:
建一个发送者的类:
import java.io.*;
public class Sender extends Thread//发送者线程
{
private PipedOutputStream out = new PipedOutputStream();//向主进程发送数据
public PipedOutputStream getOutputStream()//得到输出流
{
return out;
}
public void run()
{
String strInfo = new String("hello,receiver!");//向out写入数据
try
{
out.write(strInfo.getBytes());//写入"hello,receiver!"
out.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
建一个接收者的类:
import java.io.*;
public class Receiver extends Thread {
private PipedInputStream in = new PipedInputStream();//从主进程读取数据
public PipedInputStream getInputStream()
{
return in;
}
public void run()
{
byte [] buf = new byte[1024];
try
{
int len = in.read(buf);//接收数据
System.out.println("the following message comes from sender:\n" +
new String(buf,0,len));//打印出收到的信息
in.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
主程序:
import java.io.*;
public class PipedStreamTest {
public static void main(String[] args) throws Exception{
Sender s = new Sender();
Receiver r = new Receiver();
PipedOutputStream out = s.getOutputStream();
PipedInputStream in = r.getInputStream();
//out.connect(in);//两个管道相连接
in.connect(out);
s.start();
r.start();
}
}
JDK还提供了PipedReader和PipedWriter类,用来处理字符文本的管道通信。它们和PipedInputStream类和PipedOutputStream类很类似。
使用管道流类可以实现各个程序模块之间的松耦合通信,这样就可以在程序中灵活的将多个这样的模块的输入流和输出流相连,以拼装成满足各种应用的程序,而不用对模块内部进行修改。刚才那个例子程序中的Sender和Reciever的输入和输出管道相连,Sender发送的数据就被Reciever接收到了。
ByteArrayInputStream类和ByteArrayOutputStream类:
内存虚拟文件和内存映象文件其实就是把内存中的一块数据存储缓冲区虚拟成一个文件,原来该写入硬盘上的内容可以被写到内存中,原来该从硬盘中读取的内容也可以从内存中读取。要在程序中定义一个大的程序缓冲区,这个缓冲区通常就是一个字节数组。java中定义了两个专门的类,就是ByteArrayInputStream类和ByteArrayOutputStream类,用于以IO流的方式来完成对字节数组内容的读写,来支持类似内存虚拟文件或者内存映像文件的功能。
ByteArrayInputStream类有两个默认的构造函数:
ByteArrayInputStream(byte[] b):使用一个字节数组当中所有的数据做为数据源,程序可以向输入流方式一样读取字节,就像一个虚拟的文件了,用文件的方式去读取它里面的数据。
ByteArrayInputStream(byte[] b,int offset,int len):从数组当中的第offset开始,一直取出len个这个字节做为数据源。
ByteArrayOutputStream类有两个默认的构造函数:
ByteArrayOutputStream():创建一个32个字节的缓冲区
ByteArrayOutputStream(int):根据参数指定大小创建缓冲区
这两个构造函数创建的缓冲区大小在数据过多的时候都会自动增长,如果创建缓冲区以后,程序就可以把它象虚拟文件一样似的往它里面写入内容,当写完内容以后调用ByteArrayOutputStream()就可以把其中的内容当作字节数组返回。
下面来看个例子:编写一个把输入流中的所有英文字母变成大写字母,然后将结果写入到一个输出流对象。用这个函数来将一个字符串中的所有字符转换成大写。
import java.io.*;
public class ByteArrayTest {
public static void main(String[] args) throws Exception{
String tmp = "abcdefghijklmnopq";
byte[] src = tmp.getBytes();
ByteArrayInputStream input = new ByteArrayInputStream(src);
ByteArrayOutputStream output = new ByteArrayOutputStream();
transform(input,output);
byte[] result = output.toByteArray();//将结果返回
System.out.println(new String(result));
transform(System.in,System.out);//键盘小写输入,打印大写输出
}
public static void transform(InputStream in,OutputStream out) throws Exception
{
int ch = 0;
while((ch = in.read()) != -1)//InputStream和OutputStream只能用于读取一个字节,所以用了while循环
{
int upperCh = Character.toUpperCase((char)ch);
out.write(upperCh);
}
}
}
一个字符串其实就相当于一个字符数据的存储缓冲区,JDK中还提供了StringReader和StringWriter类来以字符IO流的形式处理字符串,这两个类分别对应ByteArrayInputStream类和ByteArrayOutputStream类。
在编写与IO流相关的程序代码时,一定要考虑好程序代码的可复用性,可以从下面几个方面考虑:
1.System.in是连接到键盘的,它是InputStream类型的实例对象,System.out是连接到显示器,是PrintStream类的实例对象。程序可以使用System.in来读取键盘上的数据,可以使用System.out来将数据输出到显示器上,键盘被当作一个特殊的输入文件,显示器被当作一个特殊的输出文件处理
2.无论是文件流还是网络流,它都有一个结束标记来表示底层物理设备中的数据的中止点,不管底层物理设备用什么样的方式来实现数据的终止点,InputStream类的read()总是返回-1来表示输入流的结束。
3.在Windows下,按下Ctrl+z组合键可以产生键盘输入流的结束标记。在Linux下是Ctrl+d
经验:如果要编写从键盘上连续读取一大段数据的时候,应该尽量将读取数据的过程放在函数中完成,并且使用-1作为键盘输入的结束点,在函数中编写的程序代码不应直接使用System.in来读取数据,而是用一个InputStream类型的形式参数对象来读取数据,然后将System.in作为实参来传递给InputStream类型的形式参数来调用该函数。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/36711/showart_479854.html |
|