JAVA输入\输出流

来源:互联网 发布:电击棍淘宝没有卖吗 编辑:程序博客网 时间:2024/04/25 19:49
I/O流(Input/Output)
–Java IO流是实现输入/输出的基础,它可以方便地实现数据的输入/输出操作。
–流(stream)是从源(source)到接收目的地(destination)的有序数据。流代表任何有能力产出数据的数据源对象,或者有能力接收数据的接收端对象
–Java中把不同的输入/输出源(键盘、文件、网络连接等)抽象表述为“流”,通过流的方式允许Java程序使用相同的方式来访问不同的输入/输出源。

“流屏蔽了实际的I/O设备中处理数据的细节”

 

流可以从以下几个方面进行分类
–从流的方向划分
输入流
输出流
–从流的内容划分
字节流
字符流
–从流的分工划分
节点流
处理流

 

输入流
–为了从信息源获取信息,程序打开一个输入流,程序可从输入流读取信息,keyboard/Image scanner/mouse/disk file/running program/Internet

输出流

–当程序需要向目标位置写信息时,便需要打开一个输出流,程序通过输出流向这个目标位置写信息,monitor/disk file/running program/Internet

 

字节流
–操作的最小数据单元是8位的字节
–主要由InputStream和OutputStream作为基类
 
字符流
–操作的最小数据单位是16位的字符
–主要由Reader和Writer作为基类
–Reader和Writer提供兼容Unicode与面向字符的I/O功能

 

节点流
–可以从/向一个特定的IO设备(如磁盘、网络)读/写数据的流。节点流也被称为低级流

 

处理流
–用于对一个已存在的流进行连接或封装,通过封装后的流来实现数据读/写功能的流。处理流也被称为高级流

 

lJavaIO流有40多个类,都是从4个抽象基类派生出来的:
–InputStream/Reader:所有输入类的基类,前者是字节输入流,后者是字符输入流
–OutputStream/Writer:所有输出流的基类,前者是字节输出流,后者是字符输出流

对于InputStreamReader而言,它们把输入设备抽象成一个“水管”,这个水管里的每个“水滴”依次排列。从上图可以看出,字节流和字符流的处理方式非常相似,只是它们处理的最小输入/输出单位不同而已。输入流使用隐式的记录指针来表示当前正准备从哪个“水滴”开始读取,每当程序从InputStreamReader里取出一个或多个“水滴”后,记录指针自动向后移动。

    对于OutputStreamWriter而言,它们同样把输出设备抽象成一个“水管”,只是这个水管里没有任何水滴。当我们执行输出时,程序相当于依次把“水滴”放入到输出流的水管中,输出流同样采用隐式的记录指针来标识当前水滴即将放入的位置,每当程序向OutputStreamWriter里输出一个或多个“水滴”后,记录指针自动向后移动

 

InputStream
–int read(): 从输入流中读取单个字节,返回所读取的字节数据(字节数据可直接转换为int类型)。
–int read(byte[] b): 从输入流中读取最多b.length个字节的数据,并将其存储在字节数组b中,返回实际读取的字节数。
–int read(byte[] b, int off, intlen): 从输入流中读取最多len字节的数据,并将其存储在数组b中,放入b数组中时,并不是从数组起点开始,而是从offset位置开始,返回实际读取的字节数。
 
Reader
–int read(): 从输入流中读取单个字符,返回所读取的字符数据(字符数据可直接转换为int类型)。
–int read(char[] cbuf): 从输入流中读取最多cbuf.length个字符的数据,并将其存储在字符数组cbuf中,返回实际读取的字符数。
–int read(char[] cbuf, int off, intlen): 从输入流中读取最多len字符的数据,并将其存储在数组cbuf中,放入cbuf数组中时,并不是从数组起点开始,而是从offset位置开始,返回实际读取的字符数。
 
InputStream和Reader
–对比InputStream和Reader所提供的方法,不难发现这两个基类的功能基本是一样的。它们都是将输入数据抽象成“水管”,通过read方法来读取“水滴”。当使用数组作为read方法的参数是,可以把数组理解成“竹筒”从输入流中取出一筒“水滴”,再把“水滴”转换成相应的数据;程序多次重复这个“取水”过程,直到read方法返回-1。
InputStream和Reader都是抽象类,本身不能创建实例
 

public class FileReaderTest

  public static void main(String args[]) {

      FileReaderfr = null;

      try  {       

          fr = new FileReader("myFile.txt");

          char[] cbuf = new char[32];

          inthasRead =0;

          while ((hasRead = fr.read(cbuf)) > 0 {

             System.out.print(new String(cbuf, 0, hasRead));

          }

       }

       catch (IOExceptionioe)  {

          ioe.printStackTrace();

       }

          finally{

           if( fr != null)  {

               try  {

                      fr.close();

               }

               catch (IOExceptionioe)  {

                      ioe.printStackTrace();

               }

            }

        }

    }

}

IO异常
–多数IO方法在遇到错误时会抛出异常,因此调用这些方法时必须
在方法头声明抛出IOException异常
或者在try块中执行IO,然后捕获IOException
 
lOutputStream
–void write(int c): 将指定的字节/字符输出到输出流中,其中c既可以代表字节,也可以代表字符。
–void write(byte[]/char[] buf): 将字节/字符数组中的数据输入到指定输出流中。
–void write(byte[]/char[] buf, int off, intlen): 将字节/字符数组中从off位置开始,长度为len的字节/字符输出到输出流中。
 
–void write(String str): 将str字符串里包含的字符输出到指定的输出流中。
void write(String str, int off, intlen): 将str字符串从off位置开始,长度为len的字符输出到指定输出流中

public class FileOutputStreamTest {

  public static void main(String args[]){

    FileInputStreamfis = null;

    FileOutputStreamfos = null;

    try {

             fis = new FileInputStream("myFile.txt");

             fos = new FileOutputStream("nextFile.txt");

             byte[] bbuf = new byte[32];

             inthasRead =0;            

             while ((hasRead = fis.read(bbuf)) > 0 ) {

                     fos.write(bbuf, 0, hasRead);

             }

     }

     catch (IOExceptionioe) {

          ioe.printStackTrace();

     }

    finally {

            if( fis != null) {

            try {

                      fis.close();

                   }

             catch(IOExceptionioe) {

                        ioe.printStackTrace();

              }

        }

       if( fos != null) {

              try {

                      fos.close();

               }

               catch(IOExceptionioe) {

                        ioe.printStackTrace();

               }

           }

        }

    }

}

 

练习 1

请问以下哪些是定义在java.io包中的抽象类(不定选题)

   A. InputStream

   B. PrintStream

   C. Reader

   D. FileInputStream

   E. FileWriter
AC。本题考查的核心是java.io包中的抽象类。在io包中,主要分为两种类,输入/输出流类和读/写类。这两种类的顶层类分别为InputStream/OutputStream、Reader/Writer,均为抽象类。PrintStream是OutputStream的间接子类,FileInputStream和FileWriter分别是InputStream和Writer的直接子类。这些子类都是抽象父类的具体实现,因此并不是抽象类
 
输入输出流体系
通常来说,我们认为字节流的功能比字符流功能强大,因为计算机里所有的数据都是二进制的,而字节流可以处理所有二进制文件——但问题是如果我们使用字节流来处理文本文件时,我们需要使用合适的方式把这些字节换成字符,这就增加了编程的复杂度。所以通常有一个规则:如果需要进行输入/输出的内容是文本内容,则应该考虑使用字符流;如果需要进行输入/输出的二进制内容,则应该考虑使用字节流。
 
输入/输出流体系里提供了2个转换流,这两个转换流用于实现将字节流转换成字符流,其中InputStreamReader将字节输入流转换成字符输入流,OutputStreamWriter将字节输出流转换成字符输出流。
 

public class KeyinTest {

  public static void main(String args[]){

    BufferedReaderbr = null;

    try {

             InputStreamReader reader  = new InputStreamReader(System.in);

             br = new BufferedReader(reader);

             String buffer = null;

             while ((buffer = br.readLine()) != null) {

                   System.out.println(“输入内容为:”+ buffer);

              }

     }

     catch (IOExceptionioe) {

          ioe.printStackTrace();

     }

     finally {

            if( br != null) {

              br.close();

            }

      }

   }

}

 
System.in
–程序启动时由Java系统自动创建的流对象,它是原始的字节流,不能直接从中读取字符,需要对其进行进一步的处理
InputStreamReader(System.in)
–以System.in为参数创建一个InputStreamReader流对象,相当于字节流和字符流之间的一座桥梁,读取字节并将其转换为字符
BufferedReader(isr)
–对InputStreamReader处理后的信息进行缓冲,以提高效率
 
处理流
–不直接与数据源或目标相连,而是基于另一个流来构造
–从流读写数据的同时对数据进行处理
–InputStreamReader和BufferedReader都属于处理流
lInputStreamReader读取字节并转换为字符
lBufferedReader对另一个流产生的数据进行缓冲

用一行表达式实现:

BufferedReaderstdin = new BufferedReader ( new InputStreamReader(System.in) );

FileReader
–从文本文件中读取字符
–节点流
BufferedReader
–读文本文件的缓冲器类
–具有 readLine()方法,可以对换行符进行鉴别,一行一行地读取输入流中的内容
–处理流
 

Note:当我们使用处理流来包装底层节点流之后,关闭输入/输出流资源时,只要关闭最上层的处理流即可。关闭最上层的处理流时,系统会自动关闭被该处理流包装的节点流。

 
标准输入输出流对象
–System类的静态成员变量
–包括
System.in: InputStream类型的,代表标准输入流,这个流是已经打开了的,默认状态对应于键盘输入。
System.out:PrintStream类型的,代表标准输出流,默认状态对应于屏幕输出
System.err:PrintStream类型的,代表标准错误信息输出流,默认状态对应于屏幕输出
 
标准I/O重新导向
–setIn(InputStream): 设置标准输入流
–setOut(PrintStream):设置标准输出流
–setErr(PrintStream):设置标准错误输出流
 

public class RedirectOut {

  public static void main(String[] args){

  PrintStreamps = null;

  try {

        ps = new PrintStream(new FileOutputStream("out.txt"));

        System.setOut(ps);

        System.out.println("普通字符串");

        System.out.println(new RedirectOut());

  }

  catch(IOExceptionioe) {

        ioe.printStackTrace();

  }

  finally{

        if(ps != null){

             ps.close();

        }

  }

 }

}