JAVA——IO流 之 字节流与字符流(1)

来源:互联网 发布:四川广电网络客服电话 编辑:程序博客网 时间:2024/06/05 15:40

1. 【转载】java学习之IO流使用技巧浅谈

  • 首先,通过转载百度经验中的一篇介绍Java流使用经验的文章作为开始,来学习和总结Java中的IO流问题。
  • 原文出处:https://jingyan.baidu.com/article/ca00d56c6b4397e99febcf70.html
  • 学习和使用IO流的步骤:
  • 第一步,首先,明确IO流中有两个主要的体系,即字节输入流(InputStream)、字节输出流(OutputStream)和字符输入流(Reader)、字节输出流(Writer)。其次,明确数据的来源和数据将要到达的目的地。

  • 第二步,明确将要操作的数据是否是纯文本数据。如果数据源是纯文本数据选Reader;数据源不是纯文本数据选择InputStream。如果数据目的地是纯文本数据就选择Writer;如果不是则选择OutputStream。

  • 第三步,明确具体的设备。即数据源是从哪个设备来的:是硬盘就加File;是键盘用System.in(是一个InputStream对象);是内存用数组;是网络用Socket流。同样目的是哪个设备:是硬盘就加File;是键盘用System.out(是一个OutoutStream对象);是内存用数组;是网络用Socket流。

  • 第四步,明确是否还需要其他额外功能呢,例如①是否需要较高的效率,即是否需要使用缓冲区,是就加上Buffered;②是否需要转换,是,就使用转换流,InputStreamReader 和OutputStreamWriter。

  • 通过上面的四步走基本就可以确定该用哪个类了。如果小伙们看了上面讲解,还是有点似懂非懂,那么,接下来大家可以看看下面的例子。把上面的四步走带入走一遍,应该就可以相当清楚了。例子如图所示。
    这里写图片描述
    这里写图片描述

2. 与流有关的类

  • 流的概念:流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

2.1 与流有关的类、字节流与字符流的区别

(1)File类
- File类是IO包中唯一能代表磁盘文件的对象,File类定义了一些与平台无关的方法来操作文件,通过调用File类提供的各种方法,我们能够创建、删除文件,重命名文件,判断文件的读写权限是否存在,设置和查询文件的最近修改时间。
(2) RandomAccessFile类
(3) InputStream抽象类、OutputStream抽象类
- IO流主要用于硬板、内存、键盘等处理设备上得数据操作,根据处理数据的数据类型的不同可以分为:字节流(抽象基类为InPutStream和OutPutStream)和字符流(抽象基类为Reader和Writer)。
- 程序可以从连续读取字节的对象叫输入流,用InputStream类完成。程序能向其中连续写入字节的对象叫输出流,用OutputStream类完成。
(4) Reader抽象类、Writer抽象类
- 专门用来处理字符流的抽象类。

2.2 字节流与字符流的区别

  • (1)字节流读取的时候,读到一个字节就返回一个字节; 字符流使用字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8码表中是3个字节)时;其本质是基于字节流读取时,去查了指定的码表。先去查指定的编码表,将查到的字符返回。
  • (2)字节流可以处理所有类型数据,如:图片,MP3,AVI视频文件,而字符流只能处理字符数据。只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流。

3. Java流的结构

“Java流类图结构”来源:http://www.cnblogs.com/oubo/archive/2012/01/06/2394638.html
这里写图片描述

4. 字节流

4.1 字节输入流InputStream

  • InputStream 是所有的输入字节流的父类,它是一个抽象类。继承自InputStream的流都是用于向程序中输入数据,且数据的单位为字节(8bit)。
  • ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。
  • ObjectInputStream和所有FilterInputStream 的子类都是处理流。
  • PipedInputStream是从与其它线程共用的管道中读取数据。
  • SequenceInputStream的功能:将两个或多个InputStream 对象转换成单一InputStream 。
  • FilterInputStream抽象类的子类有四个:DataInputStream, PushbackInputStream, BufferedInputStream, LineNumberInputStream。
  • InputStream的基本方法:
InputStream的基本方法:(1)int read() throws IOException //从输入流中读取一个字节并以整数的形式返回(返回的是下一个输入字节的整数表示(0~255)),如果返回-1表示已到输入流的末尾。该方法抛出了IO异常。(2)int read(byte[] b) throws IOException  //读入b.length个字节放到b中并返回实际读入的字节数。(3)void close() throws IOException //在操作完一个流后,要使用此方法将其关闭,系统就会释放与这个流相关的资源。(4... ...[还有很多方法,可参考API文档阅读]

这里写图片描述

  • 例子:利用FileInputStream读出某一指定文件的内容,并打印输出。注意:打印输出的英文字符能够正常显示,但是中文字符被显示为问号,要解决这个问题就是后面会讲到的FileReader类。
import java.io.*;public class TestFileInputStream{    public static void main(String[] args)    {        FileInputStream fis = null;        long num = 0;        int b = 0;        try        {            fis = new FileInputStream("D:\\JavaProject\\demo13\\TestFileInputStream.java");        }        catch (FileNotFoundException e)        {            System.out.println("找不到指定文件");             System.exit(-1);        }        try        {            while((b=fis.read()) != -1)            {               System.out.print((char)b);               num++;            }            fis.close();            System.out.println();            System.out.println("共读取了 "+num+" 个字节");        }        catch (IOException e)        {            System.out.println("文件读取错误");             System.exit(-1);        }    }}

4.2 字节输出流OutputStream

  • OutputStream 是所有的输出字节流的父类,它是一个抽象类。
  • ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组和本地文件中写入数据。
  • PipedOutputStream 是向与其它线程共用的管道中写入数据。
  • ObjectOutputStream 和所有FilterOutputStream 的子类都是处理流。

  • 例子:把指定的某一文件进行复制到另一个位置的指定文件中去。分析:这时就首先需要FileInputStream类来读出该文件的内容,然后通过FileOutputStream类向文件写入。

import java.io.*;public class TestFileOutputStream{    public static void main(String[] args)    {        int b = 0;        FileInputStream in = null;        FileOutputStream out = null;        try        {            in = new FileInputStream("D:\\JavaProject\\demo13\\TestFileOutputStream.java");            out = new FileOutputStream("D:\\JavaProject\\demo13\\CopyTestFileOutputStream.java");            while((b=in.read()) != -1)            {                out.write(b);            }            in.close();            out.close();        }        catch (FileNotFoundException e)        {            System.out.println("找不到指定文件");            System.exit(-1);        }        catch (IOException e)        {            System.out.println("文件复制错误");            System.exit(-1);        }        System.out.println("文件已成功复制");    }}
  • OutputStream的基本方法:
    这里写图片描述

4.3 字节输出流与输入流对应的关系

这里写图片描述
来源:http://www.cnblogs.com/oubo/archive/2012/01/06/2394638.html

5. 字符流

5.1 Reader

  • Reader 是所有的输入字符流的父类,它是一个抽象类。
  • CharReader、StringReader 是两种基本的介质流,它们分别将Char 数组、String中读取数据。PipedReader 是从与其它线程共用的管道中读取数据。
  • BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它Reader 对象。
  • FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号。
  • InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader 可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream 转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。后面会有Reader 与InputStream 的对应关系。
  • 基本方法:
    这里写图片描述

  • 示例:

import java.io.*;public class TestFileReader{    public static void main(String[] args)    {        FileReader fis = null;        long num = 0;        int b = 0;        try        {            fis = new FileReader("D:\\JavaProject\\demo13\\TestFileInputStream.java");        }        catch (IOException e)        {            System.out.println("找不到指定文件");             System.exit(-1);        }        try        {            while((b=fis.read()) != -1)            {               System.out.print((char)b);               num++;            }            fis.close();            System.out.println();            System.out.println("共读取了 "+num+" 个字节");        }        catch (IOException e)        {            System.out.println("文件读取错误");             System.exit(-1);        }    }}

5.2 Writer

  • Writer 是所有的输出字符流的父类,它是一个抽象类。
  • CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据。PipedWriter 是向与其它线程共用的管道中写入数据,
  • BufferedWriter 是一个装饰器为Writer 提供缓冲功能。
  • PrintWriter 和PrintStream 极其类似,功能和使用也非常相似。
  • OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类(具体可以研究一SourceCode)。功能和使用和OutputStream 极其类似,后面会有它们的对应图。
  • 基本方法:
    这里写图片描述
  • 示例:
import java.io.*;public class TestFileWriter{    public static void main(String[] args)     {        FileWriter fw = null;        try        {            fw = new FileWriter("D:\\JavaProject\\demo13\\WriteFilewRiter.java");            //如果文件不存在,会自动的创建一个。            for(int c=0;c<5000;c++)            {                fw.write(c);            }            fw.close();            //fw.flush();            /*如果把fw.close();语句注释掉以后编译运行,在WriterFilewRiter.java文件没有            写入的字符串;而将fw.close();语句替换成fw.flush();会发现WriterFilewRiter.java文件            写入了字符串,这就是缓冲区的原因。            */        }        catch (IOException e)        {            e.printStackTrace();            System.out.println("文件写入错误");            System.exit(-1);        }        System.out.println("文件写入成功!");    }}  

5.3 字符输出流与输入流对应的关系

这里写图片描述
来源:http://www.cnblogs.com/oubo/archive/2012/01/06/2394638.html

1 0