JAVA的I/O操作(二)

流式I/O

  以byte为单位进行操作


流(Stream)分为两类:
节点流:以节点为单位录入或者输出
过滤流:通过对已经存在的流过滤得到,必须从已经存在的流对象构造。
当然,Stream区分为输入、输出两类,这是一个很容易混淆的概念,必须依照以下的话来区分:
可以从中读出一系列字节的对象称为输入流;能向其中写入一系列字节的对象称为输出流;
我把它简单地称为“输入流读出,输出流写入"
最基本的两个流类是InputStream和OutputStream,由此派生出一系列功能各异的流式类,它们重写或者继承了这两个类的方法,并加入各自独立的新方法,构成了完成不同的功能。

InputStream
常用方法列表:
 abstract int read(),读取下一个字节的数据,并返回读到的数据的一个int型的值,如果返回了-1,则表示读到了输入流的结尾。这是一个虚函数,在不同的类中一般有这个类的重写,如system.in,这个类就重写了这个方法,该方法会读出所有字节中的数据直到末尾。

   int read(byte[] b),将数据读入一个byte类型的数组,返回实际读取的数据个数,如果返回-1,则表示读到了数据的末尾
  
   int read(byte[] b,int off,int len),将数据读入一个byte类型的数组,返回实际读取的数据个数,如果返回-1,则表示读到了数据的末尾,off指定读取的数据从b数组中的何处开始存放,它的范围是数组的下标的范围;len指定一次读取的数据长度,即读取多少byte位。

   Long skip(long n),在输入流中跳过n个字节,并返回实际跳过的字节数
   Int available(),在不发生阻塞情况下可以读取的字节数
   Void close(),关闭于当前流相关的资源
   Void mark(int readlimited),在流的当前位置放置一个标记,如果读取的字节数多于readlimited,则忽略这个标记;
   Void reset(),返回到上一个标记;
   Boolean markSupported(),测试当前的流是否支持mark和reset方法。
注意:并不是所有的InputStream流都支持mark()和reset()方法,这两个方法是空,需要重写。

OutputStream
常用方法列表
  Abstract int write(int b),写入一个字节,一般会重写,如System.out重写了这个方法,是写入所有数据直到末尾
  Void write(byte[] b),写入b数组中的所有数据
  Void write(byte[] b,int off,int len),从数组b中的off指定位置开始写入长度为len个字节的数据
  Void close(),关闭与当前流相关资源
  另,在某些OutputStream的子类里,实现了缓冲输入的,有一个flush()方法,强制写入当前缓存中的所有数据而不是等到缓存满。
---------------------------------------------
一个简单的从标准输入设备(键盘)获得数据并显示在标准输出设备(显示器)上的程序
class SystemInuOutTest
{
 public static void main(String[] args) throws Exception
 {
    int data;
    while((data=System.in.read())!=-1)
    {
     System.out.write(data);
    }
 }
}
这个程序会运行直到你按下ctrl+C才会停止
---------------------------------------------
这里要介绍byte类型和string类型的转换。当我们要将一个String类型的数组写入流中怎么办?答案是java.lang.String类提供了byte[] getBytes()方法,将一个string类型转变为一个byte类型的数组。而byte数组转换为String类型的方法是调用String的构造函数String(byte[] b),类似的构造函数有很多,不一一列举。
---------------------------------------------
InputStream和OutputStream类的几个派生类
   1.FileInputStream和FileOutputStream
   节点流,用于从文件中读取数据(向文件中写入数据),如果在构造FileOutputStream时,文件已经存在,则这个文件会被覆盖;
   2.BufferedInputStream和BufferedOutputStream
   过滤流,需要通过已经存在的流来构造,提供带缓存的读写,提高了读写的效率,类BufferedOutputStream会用到前面提到过的flush()方法,强制缓存中的数据写入。
  3.DataInputStream和DataOutputStream
   过滤流,提供java中基本的数据类型的读出和写入。
  4.PipedInputStream和PipedOutputStream
   称为“管道流”,一般成对存在才有意义,用于线程之间的通信,如一个线程的PipedInputStream从另一个线程的PipedOutputStream获得数据。
-----------------------------------------------
代码:1.FileInputStream和FileOutputStream
import java.io.*;
class StreamTest
{
 public static void main(String[] args) throws Exception
 {
  FileOutputStream fops=new FileOutputStream("hello.txt");
  fops.write("hello,world".getBytes());
  //String类型转换为一个bytes数组
  FileInputStream  fips=new FileInputStream("hello.txt");
  byte[] by=new byte[100];
  fips.read(by,0,15);
  System.out.println(new String(by));
  //如何将byte类型作为String输出
 }
}

加入.BufferedInputStream和BufferedOutputStream后提供了带缓存的读写

  import java.io.*;
class StreamTest
{
 public static void main(String[] args) throws Exception
 {
  FileOutputStream fops=new FileOutputStream("hello.txt");
  BufferedOutputStream bops=new BufferedOutputStream(fops);
  bops.write("hello,world".getBytes());
  //String类型转换为一个bytes数组
  bops.flush();
  //flush强制缓存中的数据写入
  bops.close();
  FileInputStream  fips=new FileInputStream("hello.txt");
  BufferedInputStream bips=new BufferedInputStream(fips);
  byte[] by=new byte[100];
  bips.read(by,0,15);
  System.out.println(new String(by));
  //如何将byte类型作为String输出
  bips.close(); //只需要关闭最顶端的流
 }
}

DataInputStream和DataOutputStream


import java.io.*;
public class IoTest {

 public static void main(String[] args) throws IOException
 {
  FileOutputStream fops=new FileOutputStream("hello.txt");
  DataOutputStream dops=new DataOutputStream(fops);
  boolean b=true;
  byte bb=1;
  double d=1.234;
  float f=1.23f;
  String s="hello,world";
  dops.writeBoolean(b);
  dops.writeByte(bb);
  dops.writeDouble(d);
  dops.writeFloat(f);
  dops.writeChars(s);
  dops.close();
  FileInputStream  fips=new FileInputStream("hello.txt");
  DataInputStream dips=new DataInputStream(fips);
  System.out.println(dips.readBoolean());
  System.out.println(dips.readByte());
  System.out.println(dips.readDouble());
  System.out.println(dips.readFloat());
  byte[] by=new byte[100];
  dips.read(by,0,30);
  System.out.println(new String(by));
  dips.close();
  //读出和写入的顺序必须一直才能得到正确的结果
 }
}

PipedInputStream和PipedOutputStream
   大体的机制是这样,在某两个线程中,一个定义管道输入对象,另一个定义管道输出对象。在这两个线程类的外部,可以使用某两个成对(connect())的管道对像对线程中对应的管道赋值,然后可以实现这两个线程的通信。简单代码如下:
import java.io.*;
public class ThreadPipedStreamTest
{
 public static void main(String[] args) throws Exception
 {
  PipedOutputStream pos=new PipedOutputStream();
  PipedInputStream pis=new PipedInputStream();
  pos.connect(pis);
   //管道的输入输出流成对存在才有意义,此函数对其进行链接
  try
  {
   new Producer(pos).start();
   new Comsumer(pis).start();
  }
  catch(Exception e)
  {
   e.printStackTrace();
  }
    
 }
}
class Producer extends Thread
{
 private PipedOutputStream pos;
    Producer(PipedOutputStream pos)
 {
   this.pos=pos;
 }
 public void run()
 {
  try
  {
    byte[] b="hello,world".getBytes();
    pos.write(b,0,b.length);
  }
  catch(IOException e)
  {
   e.printStackTrace();
  }
 }
}
class Comsumer extends Thread
{
 private PipedInputStream pis;
 private byte[] b=new byte[40];
    Comsumer(PipedInputStream pis)
 {
   this.pis=pis;
 }
 public void run()
 {
  
  try
  {
   pis.read(b,0,30);
      System.out.println(new String(b));
  }
  catch(IOException e)
  {
   e.printStackTrace();
  }
 }

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值