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

  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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值