java高级应用i/o操作输入输出流

InputStream类提供了有关读入数据的方法,读入数据时都是以字节为单位,可以一个字节一个字节的读入数据,也可以读入任意长度的字节块。
OutputStream类输出流写出数据也是以字节为单位,即可以一个字节一个字节地写出数据,也可以一次写出任意长度的字节块。
1.InputStream类
mark()在输入流中任意位置做一标记,从标记位置开始,以后读入的字节数据可以用reset()方法取消,使输入流读入位置复位到标记处;完成这种标记复位的前提是markSupported()方法返回必须为true;在使用标记复位功能时,mark()所需readlimit参数代表一个极限值,表示从标记位置开始到reset()取消,最多读入的字节数,如果超过,在使用reset(),则复位位置不确定;
所有InputStream的子类都是针对不同的输入数据源,其类名的前缀清楚地表示出输入的数据源:
FileInputStream类的数据源是文件。
PipedInputStream类的数据源是管道。
FilterInputStream类及其子类是加强流,它的功能更加强大,使用更加灵活。
2.OutputStream类
OutputStream类的子类:
ByteArrayOutputStream类
FileOutputStream类
PipedOutputStream类
FilterOutputStream类和它的子类加强输出流的功能。

fileInputStream三个构造,使用不同的参数,name文件名,file文件对象;fdObj 用FileDescriptor对象表示文件名,FileDescriptor类定义一个本地文件系统。在生成FileInputStream对象时同时打开文件以供应用程序读入数据。

//read
//这个方法是对这个流一个一个字节的读,返回的int就是这个字节的int表示方式
//read(byte[] b)
//这个方法是先规定一个数组长度,将这个流中的字节缓冲到数组b中,返回的这个数组中的字节个数,这个缓冲区没有//满的话,则返回真实的字节个数,到未尾时都返回-1
//3.read(byte[] b, int off, int len)
//此方法其实就是多次调用了read()方法
InputStream in = Test.class.getResourceAsStream("/tt.txt");
 //System.out.println(in.available());//此方法是返回这个流中有多少个字节数,可以把数组长度定为这个

 byte[]tt=new byte[in.available()];
 int z;
 while((z=in.read(tt, 0, tt.length))!=-1){
  System.out.println(new String(tt,"utf-8"));
 }

生成FileOutputStream对象时,如果文件不存在,则创建该文件供程序输出数据,如果文件已经存在,则有改写和附加两种输出数据的方式:
改写的含义是先把原文件长度截为零,原文件数据被丢弃,然后再输出数据;
附加的含义是在原文件末尾追加输出数据,原文件数据仍然存在。除使用第二个构造函数生成对象外,其余都是以改写方式输出数据。第二个构造函数中增加了append参数,可以选择输出数据的方式,该参数为true表示附加方式,false表示改写方式。FileInputStream类和FileOutputStream类具有读写文件的方法,但它们读写数据的效率并不高,Java鼓励程序员用更有效的方法覆盖有关读写方法,以提高应用程序的性能
我们把FilterInputStream类和FilterOutputStream类以及它们的子类,称为加强输入输出流类,因为,利用这些流类不但可以改进程序的输入输出性能,而且功能更加强大。
FilterInputStream类的子类:
BufferedInputStream类
DataInputStream类
FilterOutputStream类的子类
BufferedOutputStream类
DataOutputStream类

这两个类都在标准读写功能和应用程序之间,增加输入输出缓冲机制,从而显著地提高输入输出的速度。
BufferedInputStream类用于提高读入数据的速度,构造函数如下:
public BufferedInputStream(InputStream in);
public BufferedInputStream(InputStream in, int size);
BufferedInputStream对象时可以设置输入缓冲区的大小,也可以使用缺省值,其值是2048字节。生成BufferedInputStream对象后,应用程序在读入数据时,直接取自于缓存区,从而提高读入数据的速度

1.SequenceInputStream类
SequenceInputStream类可以将两个或几个输入流不露痕迹地接合在一起,生成一个长长的接合流,在读入数据时,它忽略前面几个输入流的结束符EOF,直到最后一个流的结束符EOF时,才完成流的输入,其定义如下:

public SequenceInputStream(Enumeration<? extends InputStream> e)
通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。将按顺序读取由该枚举生成的输入流,以提供从此 SequenceInputStream 读取的字节。在用尽枚举中的每个输入流之后,将通过调用该流的 close 方法将其关闭。

参数:
e - 输入流的一个枚举。
另请参见:
Enumeration
public SequenceInputStream(InputStream s1, InputStream s2)
通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此SequenceInputStream 读取的字节

import java.io.*;  
import java.util.*;  
class SequenceDemo1  
{  
   public static void main(String[] args)throws IOException  
   {  

       Vector<FileInputStream> v = new Vector<FileInputStream>();  

       v.add(new FileInputStream("c:\\1.txt"));  
       v.add(new FileInputStream("c:\\2.txt"));  
       v.add(new FileInputStream("c:\\3.txt"));  

       Enumeration<FileInputStream> en = v.elements();  

       SequenceInputStream sis = new SequenceInputStream(en);  

       FileOutputStream fos = new FileOutputStream("c:\\4.txt");  
       byte[] buf = new byte[1024];  
       int len = 0;  
       while((len=sis.read(buf))!=-1)  
       {  
           fos.write(buf,0,len);  
       }  
       fos.close();  
       sis.close();  

   }  
}  

2.管道输入输出流类
管道是UNIX的发明,它大大增强了流的概念。其含义如下面的命令串所示:
c:>dir|sort|more
这里使用了两个管道(用|表示)把三个命令连在一起,第一个管道把dir命令的输出连接到sort命令的输入,第二个管道将sort命令的输出连到more命令的输入,从而实现生成目录清单,进行排序后,一页一页地显示。
Java使用了管道技术,用PipedInputStream类和PipedOutputStream类实现管道操作,这两个类必须同时使用 。
管道技术在多线程系统中使用较多,它可以解决不同线程之间同步通讯的问题,从而保证大量数据交换顺利进行。
要实现多线程的同步通讯,必须把管道连接起来,这里有两种方法实现管道的连接:
使用带参数的构造函数。
使用不带参数的构造函数,再调用任何一个类的connect()方法,实现输入管道和输出管道的连接。

/*
管道流:
PipedInputStream
void connect(PipedOutputStream src)
使此管道输入流连接到管道输出流 src
PipedOutputStream
void connect(PipedInputStream snk)
在JDK我们看到PipedInputStream中有管道缓冲区,用来接收数据
管道流内部在实现时还有大量的对同步数据的处理
管道输出流和管道输入流执行时不能互相阻塞,所以一般要开启独立线程分别执行
顺便复习了多线程操作

class Demo              
{  
 public static void main(String[] args)  throws Exception  
 {  
   PipedInputStream pin = new PipedInputStream();  
   PipedOutputStream pout = new PipedOutputStream();  
   pin.connect(pout);  //输入流与输出流连接  

   ReadThread readTh   = new ReadThread(pin);  
   WriteThread writeTh = new WriteThread(pout);  
   new Thread(readTh).start();  
   new Thread(writeTh).start();  
 }  

 public static void sop(Object obj) //打印  
 {  
   System.out.println(obj);  
 }  
}  

class ReadThread implements Runnable  
{  
 private PipedInputStream pin;  
 ReadThread(PipedInputStream pin)   //  
 {  
   this.pin=pin;  
 }  

 public void run() //由于必须要覆盖run方法,所以这里不能抛,只能try  
 {  
   try  
   {  
     sop("R:读取前没有数据,阻塞中...等待数据传过来再输出到控制台...");  
     byte[] buf = new byte[1024];  
     int len = pin.read(buf);  //read阻塞  
     sop("R:读取数据成功,阻塞解除...");  

     String s= new String(buf,0,len);  
     sop(s);    //将读取的数据流用字符串以字符串打印出来  
     pin.close();      
   }  
   catch(Exception e)  
   {  
     throw new RuntimeException("R:管道读取流失败!");  
   }    
 }  

 public static void sop(Object obj) //打印  
 {  
   System.out.println(obj);  
 }  
}  

class WriteThread implements Runnable  
{  
 private PipedOutputStream pout;  
 WriteThread(PipedOutputStream pout)  
 {  
   this.pout=  pout;  
 }  

 public void run()  
 {  
   try  
   {  
     sop("W:开始将数据写入:但等个5秒让我们观察...");  
     Thread.sleep(5000);  //释放cpu执行权5秒  
     pout.write("W: writePiped 数据...".getBytes());  //管道输出流  
     pout.close();  
   }  
   catch(Exception e)  
   {  
     throw new RuntimeException("W:WriteThread写入失败...");  
   }  
 }  

 public static void sop(Object obj) //打印  
 {  
   System.out.println(obj);  
 }  
}  

结果:

R:读取前没有数据,阻塞中…等待数据传过来再输出到控制台…
W:开始将数据写入:但等个5秒让我们观察…
R:读取数据成功,阻塞解除…
W: writePiped 数据…

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读