Java IO 技术之基本流类

Java IO 技术之基本流类
2011年03月08日
  转自http://www.blogjava.net/coderdream/articles/65609. html 很好的一篇文章,谢谢作者
  流式IO
  流(Stream)是字节的源或目的。
  
  两种基本的流是:输入流(Input Stream)和输出流(Output Stream)。可从中读出一系列字节的对象称为输入流。而能向其中写入一系列字节的对象称为输出流。
  流的分类
  节点流:从特定的地方读写的流类,例如:磁盘或一块内存区域。
  过滤流:使用节点流作为输入或输出。过滤流是使用一个已经存在的输入流或输出流连接创建的。
  InputStream
  
  三个基本的读方法
  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。
  java.io包中 InputStream的类层次
  OutputStream
  
  三个基本的写方法
  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() :关闭输出流,释放和这个流相关的系统资源。
  java.io包中 OutputStream的类层次
  -------------------------------------------------- -----------------------------
  -------------------------------------------------- -----------------------------
  Demo1:在控制台读取键盘输入,然后显示。Ctrl+C结束运行
  -------------------------------------------------- ----------------------------- 1
  
  import java.io.*;
  2
  
  3
  
  public class StreamDemo {
  4
  
  5
  
  public static void main(String[] args) throws Exception {
  6
  
  int data;
  7
  
  8
  
  while ((data = System.in.read()) != -1) {
  9
  
  System.out.write(data);
  10
  
  }
  11
  
  12
  
  }
  13
  
  14
  
  }
  15
  
  -------------------------------------------------- -----------------------------
  -------------------------------------------------- ----------------------------- 基本的流类
  1、FileInputStream和FileOutputStream
  节点流,用于从文件中读取或往文件中写入字节流。如果在构造FileOutputStream时,文件已经存在,则覆盖这个文件。
  -------------------------------------------------- -----------------------------
  Demo2:将字符串写入特定文件,注意write方法只接收字符数组。
  -------------------------------------------------- ----------------------------- 1
  
  import java.io.*;
  2
  
  3
  
  public class StreamDemo {
  4
  
  5
  
  public static void main(String[] args) throws Exception {
  6
  
  FileOutputStream fos = new FileOutputStream("1.txt");
  7
  
  8
  
  /*
  9
  
  * 注意:FileOutputStream的write方法接收字符数组,不能接收String字符串,
  10
  
  * 所以要用String的getBytes方法生成一个字符数组
  11
  
  */
  12
  
  fos.write("http://www.cnblogs.com".getBytes());
  13
  
  fos.close();
  14
  
  15
  
  }
  16
  
  17
  
  }
  -------------------------------------------------- -----------------------------
  -------------------------------------------------- -----------------------------
  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特定的构造方法。
  -------------------------------------------------- ----------------------------- 1
  
  import java.io.*;
  2
  
  3
  
  public class StreamDemo {
  4
  
  5
  
  public static void main(String[] args) throws Exception {
  6
  
  FileOutputStream fos = new FileOutputStream("1.txt");
  7
  
  8
  
  /*
  9
  
  * 注意:FileOutputStream的write方法接收字符数组,不能接收String字符串,
  10
  
  * 所以要用String的getBytes方法生成一个字符数组
  11
  
  */
  12
  
  fos.write("http://www.cnblogs.com".getBytes());
  13
  
  fos.close();
  14
  
  15
  
  // 使用String的这个构造方法:
  16
  
  // String(byte[] bytes, int offset, int length)
  17
  
  18
  
  FileInputStream fis = new FileInputStream("1.txt");
  19
  
  byte[] buf = new byte[100];
  20
  
  int len = fis.read(buf);
  21
  
  22
  
  // 使用String的这个构造方法:
  23
  
  // String(byte[] bytes, int offset, int length)
  24
  
  System.out.println(new String(buf, 0, len));
  25
  
  fis.close(); // 使用完后记得关闭文件流
  26
  
  27
  
  }
  28
  
  29
  
  }
  30
  
  31
  
  -------------------------------------------------- -----------------------------
  运行结果:http://www.cnblogs.com
  -------------------------------------------------- -----------------------------
  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
  import java.io.*;
  2
  
  3
  
  public class StreamDemo {
  4
  
  5
  
  public static void main(String[] args) throws Exception {
  6
  
  7
  
  FileOutputStream fos = new FileOutputStream("1.txt");
  8
  
  BufferedOutputStream bos = new BufferedOutputStream(fos);
  9
  
  bos.write("http://www.cnblogs.com".getBytes());
  10
  
  }
  11
  
  12
  
  }
  -------------------------------------------------- -----------------------------
  运行结果:1.txt文件为空。原因:缓冲区没有写满,程序没有向文件写数据。
  -------------------------------------------------- -----------------------------
  -------------------------------------------------- -----------------------------
  解决方法1:使用flush()方法:
  -------------------------------------------------- -----------------------------
  Demo4:使用flush()方法,可以使程序立即向文件写数据。
  -------------------------------------------------- ----------------------------- 1
  
  import java.io.*;
  2
  
  3
  
  public class StreamDemo {
  4
  
  5
  
  public static void main(String[] args) throws Exception {
  6
  
  7
  
  FileOutputStream fos = new FileOutputStream("1.txt");
  8
  
  BufferedOutputStream bos = new BufferedOutputStream(fos);
  9
  
  bos.write("http://www.cnblogs.com".getBytes());
  10
  
  11
  
  bos.flush();
  12
  
  }
  13
  
  14
  
  }
  -------------------------------------------------- -----------------------------
  运行结果:数据被写入相应的文件。
  -------------------------------------------------- -----------------------------
  解决方法2:使用close()方法:
  -------------------------------------------------- -----------------------------
  Demo5:使用close()方法,同样可以使程序立即向文件写数据。
  -------------------------------------------------- ----------------------------- 1
  
  import java.io.*;
  2
  
  3
  
  public class StreamDemo {
  4
  
  5
  
  public static void main(String[] args) throws Exception {
  6
  
  7
  
  FileOutputStream fos = new FileOutputStream("1.txt");
  8
  
  BufferedOutputStream bos = new BufferedOutputStream(fos);
  9
  
  bos.write("http://www.cnblogs.com".getBytes());
  10
  
  11
  
  bos.close();
  12
  
  }
  13
  
  14
  
  }
  -------------------------------------------------- -----------------------------
  运行结果:数据被写入相应的文件。
  -------------------------------------------------- -----------------------------
  flush()和close()的区别:
  还要使用流对象,还需要写数据,使用flush(),否则使用close()。
  另外,使用close()将关闭自己的流对象,同时会关闭与之相关的流对象,如FileOutputStream流。
  -------------------------------------------------- -----------------------------
  Demo6:使用BufferedInputStream流,从文件中读取数据。
  同样要用InputStream流对象或者其子类的对象来构造。
  -------------------------------------------------- ----------------------------- 1
  
  import java.io.*;
  2
  
  3
  
  public class StreamDemo {
  4
  
  5
  
  public static void main(String[] args) throws Exception {
  6
  
  7
  
  FileOutputStream fos = new FileOutputStream("1.txt");
  8
  
  BufferedOutputStream bos = new BufferedOutputStream(fos);
  9
  
  bos.write("http://www.cnblogs.com".getBytes());
  10
  
  11
  
  bos.close();
  12
  
  13
  
  FileInputStream fis = new FileInputStream("1.txt");
  14
  
  BufferedInputStream bis = new BufferedInputStream(fis);
  15
  
  byte[] buf = new byte[100];
  16
  
  int len = bis.read(buf);
  17
  
  18
  
  // 使用String的这个构造方法:
  19
  
  // String(byte[] bytes, int offset, int length)
  20
  
  System.out.println(new String(buf, 0, len));
  21
  
  bis.close();
  22
  
  }
  23
  
  24
  
  }
  -------------------------------------------------- -----------------------------
  运行结果:输出http://www.cnblogs.com
  -------------------------------------------------- -----------------------------
  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对象来构造。
  -------------------------------------------------- ----------------------------- 1
  
  import java.io.*;
  2
  
  3
  
  public class StreamDemo {
  4
  
  5
  
  public static void main(String[] args) throws Exception {
  6
  
  7
  
  FileOutputStream fos = new FileOutputStream("dos.txt"); // 获得写入文件功能
  8
  
  BufferedOutputStream bos = new BufferedOutputStream(fos); // 获得缓冲功能
  9
  
  DataOutputStream dos = new DataOutputStream(bos); // 获得写入基本类型功能
  10
  
  11
  
  /*
  12
  
  * 定义8种基本类型的对象
  13
  
  */
  14
  
  byte b = 3;
  15
  
  short s = 4;
  16
  
  int i = 78;
  17
  
  long l = 100000;
  18
  
  char ch = 'a';
  19
  
  boolean bl = false;
  20
  
  float f = 4.5f;
  21
  
  double d = 4.0001;
  22
  
  23
  
  /*
  24
  
  * 将8种基本类型的对象写入文件中
  25
  
  */
  26
  
  dos.writeByte(b);
  27
  
  dos.writeShort(s);
  28
  
  dos.writeInt(i);
  29
  
  dos.writeLong(l);
  30
  
  dos.writeChar(ch);
  31
  
  dos.writeBoolean(bl);
  32
  
  dos.writeFloat(f);
  33
  
  dos.writeDouble(d);
  34
  
  dos.close();
  35
  
  }
  36
  
  37
  
  }
  -------------------------------------------------- -----------------------------
  运行结果:8种基本类型的数据以二进制形式写入指定的文件中。
  -------------------------------------------------- -----------------------------
  -------------------------------------------------- -----------------------------
  Demo8:从指定的文件中读取8种基本类型的数据
  -------------------------------------------------- ----------------------------- 1
  
  import java.io.*;
  2
  
  3
  
  public class StreamDemo {
  4
  
  5
  
  public static void main(String[] args) throws Exception {
  6
  
  7
  
  FileOutputStream fos = new FileOutputStream("dos.txt"); // 获得写入文件功能
  8
  
  BufferedOutputStream bos = new BufferedOutputStream(fos); // 获得缓冲功能
  9
  
  DataOutputStream dos = new DataOutputStream(bos); // 获得写入基本类型功能
  10
  
  11
  
  /*
  12
  
  * 定义8种基本类型的对象
  13
  
  */
  14
  
  byte b = 3;
  15
  
  short s = 4;
  16
  
  int i = 78;
  17
  
  long l = 100000;
  18
  
  char ch = 'a';
  19
  
  boolean bl = false;
  20
  
  float f = 4.5f;
  21
  
  double d = 4.0001;
  22
  
  23
  
  /*
  24
  
  * 将8种基本类型的对象写入文件中
  25
  
  */
  26
  
  dos.writeByte(b);
  27
  
  dos.writeShort(s);
  28
  
  dos.writeInt(i);
  29
  
  dos.writeLong(l);
  30
  
  dos.writeChar(ch);
  31
  
  dos.writeBoolean(bl);
  32
  
  dos.writeFloat(f);
  33
  
  dos.writeDouble(d);
  34
  
  dos.close();
  35
  
  36
  
  FileInputStream fis = new FileInputStream("dos.txt");
  37
  
  BufferedInputStream bis = new BufferedInputStream(fis);
  38
  
  DataInputStream dis = new DataInputStream(bis);
  39
  
  System.out.println(dis.readByte());
  40
  
  System.out.println(dis.readShort());
  41
  
  System.out.println(dis.readInt());
  42
  
  System.out.println(dis.readLong());
  43
  
  System.out.println(dis.readChar());
  44
  
  System.out.println(dis.readBoolean());
  45
  
  System.out.println(dis.readFloat());
  46
  
  System.out.println(dis.readDouble());
  47
  
  dis.close();
  48
  
  }
  49
  
  50
  
  }
  -------------------------------------------------- -----------------------------
  运行结果:数据正常输出:
  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:利用管道输入流和输出流进行通讯。
  -------------------------------------------------- ----------------------------- 1
  
  import java.io.*;
  2
  
  3
  
  public class PipedStreamDemo {
  4
  
  5
  
  public static void main(String[] args) {
  6
  
  PipedOutputStream pos = new PipedOutputStream();
  7
  
  PipedInputStream pis = new PipedInputStream();
  8
  
  9
  
  try {
  10
  
  pos.connect(pis);
  11
  
  //pis.connect(pos); 二选一即可
  12
  
  13
  
  new Producer(pos).start();
  14
  
  new Consumer(pis).start();
  15
  
  } catch (IOException e) {
  16
  
  // TODO 自动生成 catch 块
  17
  
  e.printStackTrace();
  18
  
  }
  19
  
  }
  20
  
  21
  
  }
  22
  
  23
  
  /*
  24
  
  * 生产者线程
  25
  
  */
  26
  
  class Producer extends Thread {
  27
  
  28
  
  private PipedOutputStream pos;
  29
  
  30
  
  public Producer(PipedOutputStream pos) {
  31
  
  this.pos = pos;
  32
  
  }
  33
  
  34
  
  public void run() {
  35
  
  try {
  36
  
  pos.write("Hello, welcome you!".getBytes());
  37
  
  pos.close();
  38
  
  } catch (Exception e) {
  39
  
  e.printStackTrace();
  40
  
  }
  41
  
  }
  42
  
  43
  
  }
  44
  
  45
  
  /*
  46
  
  * 消费者线程
  47
  
  */
  48
  
  class Consumer extends Thread {
  49
  
  50
  
  private PipedInputStream pis;
  51
  
  52
  
  public Consumer(PipedInputStream pis) {
  53
  
  this.pis = pis;
  54
  
  }
  55
  
  56
  
  public void run() {
  57
  
  try {
  58
  
  byte[] buf = new byte[100];
  59
  
  int len = pis.read(buf);
  60
  
  System.out.println(new String(buf, 0, len));
  61
  
  pis.close(); // 关闭输入流
  62
  
  } catch (Exception e) {
  63
  
  e.printStackTrace();
  64
  
  }
  65
  
  }
  66
  
  67
  
  }
  68
  
  -------------------------------------------------- -----------------------------
  运行结果:输出Hello, welcome you!
  -------------------------------------------------- -----------------------------

你可能感兴趣的:(技术杂绘)