你的位置:首页 > Java教程

[Java教程]Java IO 技术之基本流类


流式IO

流(Stream)是字节的源或目的。

01

 

      两种基本的流是:输入流(Input Stream)和输出流(Output Stream)。可从中读出一系列字节的对象称为输入流。而能向其中写入一系列字节的对象称为输出流。

流的分类

节点流:从特定的地方读写的流类,例如:磁盘或一块内存区域。
过滤流:使用节点流作为输入或输出。过滤流是使用一个已经存在的输入流或输出流连接创建的。

InputStream

2

三个基本的读方法

      abstract int read() :读取一个字节数据,并返回读到的数据,如果返回-1,表示读到了输入流的末尾。
      int read(byte[] b) :将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。
      int read(byte[] b, int off, int len) :将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。off指定在数组b中存放数据的起始偏移位置;len指定读取的最大字节数。

其它方法
      long skip(long n) :在输入流中跳过n个字节,并返回实际跳过的字节数。
      int available() :返回在不发生阻塞的情况下,可读取的字节数。
      void close() :关闭输入流,释放和这个流相关的系统资源。
      void mark(int readlimit) :在输入流的当前位置放置一个标记,如果读取的字节数多于readlimit设置的值,则流忽略这个标记。
      void reset() :返回到上一个标记。
      boolean markSupported() :测试当前流是否支持mark和reset方法。如果支持,返回true,否则返回false。

OutputStream

3

三个基本的写方法
     abstract void write(int b) :往输出流中写入一个字节。
     void write(byte[] b) :往输出流中写入数组b中的所有字节。
     void write(byte[] b, int off, int len) :往输出流中写入数组b中从偏移量off开始的len个字节的数据。
其它方法
     void flush() :刷新输出流,强制缓冲区中的输出字节被写出。
     void close() :关闭输出流,释放和这个流相关的系统资源。

 

-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Demo1:在控制台读取键盘输入,然后显示。Ctrl+C结束运行
-------------------------------------------------------------------------------

import java.io. * ; public  class StreamDemo  {   public  static  void main(String[] args) throws Exception  {  int data;   while ((data = System.in.read()) !=  - 1 )  {  System.out.write(data); }  }  }

-------------------------------------------------------------------------------
-------------------------------------------------------------------------------

 

基本的流类

1、FileInputStream和FileOutputStream

节点流,用于从文件中读取或往文件中写入字节流。如果在构造FileOutputStream时,文件已经存在,则覆盖这个文件。

-------------------------------------------------------------------------------
Demo2:将字符串写入特定文件,注意write方法只接收字符数组。
-------------------------------------------------------------------------------

import java.io. * ;   public  class StreamDemo  {   public  static  void main(String[] args) throws Exception  {  FileOutputStream fos =  new FileOutputStream( " 1.txt " );   /**/ /*   * 注意:FileOutputStream的write方法接收字符数组,不能接收String字符串,  * 所以要用String的getBytes方法生成一个字符数组   */  fos.write( " http://www.cnblogs.com " .getBytes());  fos.close();  }  }

-------------------------------------------------------------------------------
-------------------------------------------------------------------------------

String的构造方法的API:
------------
Java API:
------------
String
public String(byte[] bytes,
              int offset,
              int length)

构造一个新的 String,方法是使用指定的字符集解码字节的指定子数组。新的 String 的长度是一个字符集函数,因此不能等于该子数组的长度。

当给定字节在给定字符集中无效的情况下,该构造方法无指定的行为。当需要进一步控制解码过程时,应使用 CharsetDecoder 类。

参数:
bytes - 要解码为字符的字节
offset - 要解码的首字节的索引
length - 要解码的字节数
抛出:
IndexOutOfBoundsException - 如果 offset 和 length 参数索引字符超出 bytes 数组的范围

从以下版本开始:
JDK1.1
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Demo3:将字符串写入特定文件,注意write方法只接收字符数组。
  然后通过文件输出流读取数据,注意使用String特定的构造方法。
-------------------------------------------------------------------------------

import java.io. * ; public  class StreamDemo  {   public  static  void main(String[] args) throws Exception  { FileOutputStream fos =  new FileOutputStream( " 1.txt " );    /**/ /*   * 注意:FileOutputStream的write方法接收字符数组,不能接收String字符串,  * 所以要用String的getBytes方法生成一个字符数组   */  fos.write( " http://www.cnblogs.com " .getBytes());  fos.close();    // 使用String的这个构造方法:  // String(byte[] bytes, int offset, int length)     FileInputStream fis =  new FileInputStream( " 1.txt " );  byte [] buf =  new  byte [ 100 ];  int len = fis.read(buf);    // 使用String的这个构造方法:  // String(byte[] bytes, int offset, int length)   System.out.println( new String(buf, 0 , len));  fis.close();  // 使用完后记得关闭文件流   }  }

-------------------------------------------------------------------------------
运行结果:

-------------------------------------------------------------------------------

2、BufferedInputStream和BufferedOutputStream

过滤流,需要使用已经存在的节点流来构造,提供带缓冲的读写,提高了读写的效率。
   
------------
Java API:
------------
构造方法摘要
BufferedOutputStream(OutputStream out)
          创建一个新的缓冲输出流,以将数据写入指定的基础输出流。
BufferedOutputStream(OutputStream out, int size)
          创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的基础输出流。
-------------------------------------------------------------------------------
BufferedOutputStream
public BufferedOutputStream(OutputStream out)
创建一个新的缓冲输出流,以将数据写入指定的基础输出流。

参数:
out - 基础输出流。
BufferedOutputStream
public BufferedOutputStream(OutputStream out,
                            int size)
创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的基础输出流。

参数:
out - 基础输出流。
size - 缓冲区的大小。
抛出:
IllegalArgumentException - 如果 size <= 0
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Demo4:通过一个OutputStream对象来构造一个BufferedOutputStream对象。
  而FileOutputStream类是OutputStream类的子类,所以可以用它来构造。
-------------------------------------------------------------------------------

import java.io. * ;   public  class StreamDemo {    public  static  void main(String[] args) throws Exception {    FileOutputStream fos =  new FileOutputStream( " 1.txt " );  BufferedOutputStream bos =  new BufferedOutputStream(fos);  bos.write( " http://www.cnblogs.com " .getBytes()); }  }

-------------------------------------------------------------------------------
运行结果:1.txt文件为空。原因:缓冲区没有写满,程序没有向文件写数据。
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
解决方法1:使用flush()方法:
-------------------------------------------------------------------------------
Demo4:使用flush()方法,可以使程序立即向文件写数据。
-------------------------------------------------------------------------------

import java.io. * ;  public  class StreamDemo {    public  static  void main(String[] args) throws Exception {    FileOutputStream fos =  new FileOutputStream( " 1.txt " );  BufferedOutputStream bos =  new BufferedOutputStream(fos);  bos.write( " http://www.cnblogs.com " .getBytes());   bos.flush(); }  }

-------------------------------------------------------------------------------
运行结果:数据被写入相应的文件。
-------------------------------------------------------------------------------
解决方法2:使用close()方法:
-------------------------------------------------------------------------------
Demo5:使用close()方法,同样可以使程序立即向文件写数据。
-------------------------------------------------------------------------------

import java.io. * ;   public  class StreamDemo {    public  static  void main(String[] args) throws Exception {    FileOutputStream fos =  new FileOutputStream( " 1.txt " );  BufferedOutputStream bos =  new BufferedOutputStream(fos);  bos.write( " http://www.cnblogs.com " .getBytes());   bos.close(); }  }

-------------------------------------------------------------------------------
运行结果:数据被写入相应的文件。
-------------------------------------------------------------------------------

flush()和close()的区别:
还要使用流对象,还需要写数据,使用flush(),否则使用close()。

另外,使用close()将关闭自己的流对象,同时会关闭与之相关的流对象,如FileOutputStream流。

 

-------------------------------------------------------------------------------
Demo6:使用BufferedInputStream流,从文件中读取数据。
  同样要用InputStream流对象或者其子类的对象来构造。
-------------------------------------------------------------------------------

import java.io. * ;  public  class StreamDemo {    public  static  void main(String[] args) throws Exception {    FileOutputStream fos =  new FileOutputStream( " 1.txt " );  BufferedOutputStream bos =  new BufferedOutputStream(fos);  bos.write( " http://www.cnblogs.com " .getBytes());   bos.close();   FileInputStream fis =  new FileInputStream( " 1.txt " );  BufferedInputStream bis =  new BufferedInputStream(fis);  byte [] buf =  new  byte [ 100 ];  int len = bis.read(buf);    // 使用String的这个构造方法:  // String(byte[] bytes, int offset, int length)   System.out.println( new String(buf, 0 , len));  bis.close(); }  }

-------------------------------------------------------------------------------
运行结果:
-------------------------------------------------------------------------------

 

3、DataInputStream和DataOutputStream

过滤流,需要使用已经存在的节点流来构造,提供了读写Java中的基本数据类型的功能。
------------
Java API:
------------
java.io
类 DataOutputStream
java.lang.Object
  java.io.OutputStream
      java.io.FilterOutputStream
          java.io.DataOutputStream
所有已实现的接口:
Closeable, DataOutput, Flushable
public class DataOutputStream
extends FilterOutputStream
implements DataOutput

数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。

 

从以下版本开始:
JDK1.0
-------------------------------------------------------------------------------
构造方法摘要
DataOutputStream(OutputStream out)
          创建一个新的数据输出流,将数据写入指定基础输出流。
-------------------------------------------------------------------------------
DataOutputStream
public DataOutputStream(OutputStream out)
创建一个新的数据输出流,将数据写入指定基础输出流。计数器 written 被设置为零。

参数:
out - 基础输出流,将被保存供以后使用。
-------------------------------------------------------------------------------
Demo7:使用DataOutputStream流,将基本数据类型以二进制形式写入文件中。
  同样要用InputStream流对象或者其子类的对象来构造,
  这里使用BufferedOutputStream对象来构造。
-------------------------------------------------------------------------------

import java.io. * ;  public  class StreamDemo {   public  static  void main(String[] args) throws Exception {   FileOutputStream fos =  new FileOutputStream( " dos.txt " );  // 获得写入文件功能   BufferedOutputStream bos =  new BufferedOutputStream(fos); // 获得缓冲功能   DataOutputStream dos =  new DataOutputStream(bos);  // 获得写入基本类型功能      /*   * 定义8种基本类型的对象   */   byte b =  3 ;  short s =  4 ;  int i =  78 ;  long l =  100000 ;   char ch =  ' a ' ;  boolean bl =  false ;  float f =  4.5f ;  double d =  4.0001 ;    /*   * 将8种基本类型的对象写入文件中   */  dos.writeByte(b);  dos.writeShort(s);  dos.writeInt(i);  dos.writeLong(l);  dos.writeChar(ch);  dos.writeBoolean(bl);  dos.writeFloat(f);  dos.writeDouble(d);  dos.close(); }  }

-------------------------------------------------------------------------------
运行结果:8种基本类型的数据以二进制形式写入指定的文件中。
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Demo8:从指定的文件中读取8种基本类型的数据
-------------------------------------------------------------------------------

import java.io. * ;  public  class StreamDemo {   public  static  void main(String[] args) throws Exception {   FileOutputStream fos =  new FileOutputStream( " dos.txt " );  // 获得写入文件功能   BufferedOutputStream bos =  new BufferedOutputStream(fos); // 获得缓冲功能   DataOutputStream dos =  new DataOutputStream(bos);  // 获得写入基本类型功能      /*   * 定义8种基本类型的对象   */   byte b =  3 ;  short s =  4 ;  int i =  78 ;  long l =  100000 ;   char ch =  ' a ' ;  boolean bl =  false ;  float f =  4.5f ;  double d =  4.0001 ;    /*   * 将8种基本类型的对象写入文件中   */  dos.writeByte(b);  dos.writeShort(s);  dos.writeInt(i);  dos.writeLong(l);  dos.writeChar(ch);  dos.writeBoolean(bl);  dos.writeFloat(f);  dos.writeDouble(d);  dos.close();   FileInputStream fis =  new FileInputStream( " dos.txt " );  BufferedInputStream bis =  new BufferedInputStream(fis);  DataInputStream dis =  new DataInputStream(bis);  System.out.println(dis.readByte());  System.out.println(dis.readShort());  System.out.println(dis.readInt());  System.out.println(dis.readLong());  System.out.println(dis.readChar());  System.out.println(dis.readBoolean());  System.out.println(dis.readFloat());  System.out.println(dis.readDouble());  dis.close(); }  }

-------------------------------------------------------------------------------
运行结果:数据正常输出:
3
4
78
100000
a
false
4.5
4.0001
-------------------------------------------------------------------------------

 

4、PipedInputStream和PipedOutputStream

管道流,用于线程间的通信。一个线程的PipedInputStream对象从另一个线程的PipedOutputStream对象读取输入。要使管道流有用,必须同时构造管道输入流和管道输出流。
-------------------------------------------------------------------------------
------------
Java API:
------------
java.io
类 PipedInputStream
java.lang.Object
  java.io.InputStream
      java.io.PipedInputStream
所有已实现的接口:
Closeable
public class PipedInputStream
extends InputStream

传送输入流应该连接到传送输出流;传送输入流会提供要写入传送输出流的所有数据字节。通常,数据由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能会死锁该线程。传送输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。
从以下版本开始:
JDK1.0
-------------------------------------------------------------------------------
------------
Java API:
------------
java.io
类 PipedOutputStream
java.lang.Object
  java.io.OutputStream
      java.io.PipedOutputStream
所有已实现的接口:
Closeable, Flushable
public class PipedOutputStream
extends OutputStream

传送输出流可以连接到传送输入流,以创建通信管道。传送输出流是管道的发送端。通常,数据由某个线程写入 PipedOutputStream 对象,并由其他线程从连接的 PipedInputStream 读取。不建议对这两个对象尝试使用单个线程,因为这样可能会死锁该线程。

从以下版本开始:
JDK1.0
-------------------------------------------------------------------------------
------------
Java API:
------------
connect
public void connect(PipedInputStream snk)
             throws IOException
将此传送输出流连接到接收者。如果此对象已经连接到其他某个传送输入流,则抛出 IOException。

如果 snk 为未连接的传送输入流,而 src 为未连接的传送输出流,则可以通过以下任一调用使其连接:
src.connect(snk)
或:
snk.connect(src)
这两个调用的效果相同。

参数:
snk - 要连接的传送输入流。
抛出:
IOException - 如果发生 I/O 错误。
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
Demo9:利用管道输入流和输出流进行通讯。
-------------------------------------------------------------------------------

import java.io. * ;  public  class PipedStreamDemo {   public  static  void main(String[] args) {  PipedOutputStream pos =  new PipedOutputStream();  PipedInputStream pis =  new PipedInputStream();    try  {  pos.connect(pis);   // pis.connect(pos); 二选一即可      new Producer(pos).start();   new Consumer(pis).start();  }  catch (IOException e) {   // TODO 自动生成 catch 块    e.printStackTrace();  }  }  }   /*  * 生产者线程  */  class Producer extends Thread {   private PipedOutputStream pos;   public Producer(PipedOutputStream pos) {  this .pos = pos; }    public  void run() {   try  {  pos.write( " Hello, welcome you! " .getBytes());  pos.close();  }  catch (Exception e) {  e.printStackTrace();  }  }  }   /*  * 消费者线程  */  class Consumer extends Thread {   private PipedInputStream pis;   public Consumer(PipedInputStream pis) {  this .pis = pis; }    public  void run() {   try  {   byte [] buf =  new  byte [ 100 ];   int len = pis.read(buf);  System.out.println( new String(buf, 0 , len));  pis.close();  // 关闭输入流   }  catch (Exception e) {  e.printStackTrace();  }  }  }

-------------------------------------------------------------------------------
运行结果:输出Hello, welcome you!
-------------------------------------------------------------------------------

转自:http://www.blogjava.net/coderdream/articles/65609.html