Java IO流

Java IO即Java输入输出系统。在Java IO中,流是一个核心的概念。流的本质是一组有序的数据集合。既可以从流中读取数据,也可以往流中写数据。在Java IO中流既可以是字节流(以字节为单位进行读写),也可以是字符流(以字符为单位进行读写)。

流的分类:

1.按照流的方向:

  • 输入流:InputStream和Reader(读取外部数据(文件、磁盘,网络等)到程序中)
  • 输出流:OutputStream和Writer(将程序内的数据(内存)输出到磁盘光盘等设备)

2.按照流的操作单元:

  • 字节流:InputStream和OutputStream
  • 字符流:Reader和Writer

3.按照角色划分:

  • 节点流(介质流):数据从/向一个介质(磁盘、鼠标、屏幕)读/写的流称为节点流。也称之为低级流
  • 处理流(高级流):和节点流直接相连接的流

下表清晰的区分了字符流,字节流,输入流,输出流:

字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter

字节流,字符流的特点

字节流:inputStram,outputStram
1.二进制数据:将数据解释成原始的二进制数
2.byte数据:读写均为字节数据
3.效率高:二进制数不需要编码和解码,比文本I/O效率高
4.可移植:与主机的编码无关

字符流:reader , writer
1.字符数据:字符流将原始数据解释成字符序列
2.依赖编码方式:文本数据存储依赖文件编码方式,字符流的输入和输出需要进行编码和解码

字节流字符流的区别:

  • 存储的方式不同:
    字节流:存储的数据是0101形式
    字符流:存储的是字符
  • 读写的单元不同:
    字节流:以字节(8bit)为单位
    字符流:以字符为单位,跟比码表映射字符,一次可以读取多个字节
  • 处理的对象不同
    字节流:能处理所有类型的数据(比如:图片,AVI视频)
    字符流:只能处理字符类型的数据
  • 处理效率
    字节流效率较高,直接进行读取
    字符流效率较低,涉及到编码解码的过程
  • 可移植性
    字节流可移植行高,和平台无关
    字符流可移植性低,要考虑编码解码过程,编码和解码的码表需要保持一致

节点流和处理流区别:

  • 节点流直接和介质相连接
  • 处理流直接和节点流相连接

下图是具体的Java IO类的集成关系:
在这里插入图片描述
下面,对字节,字符流基类的操作步骤及其常用方法做以简单的介绍:

  • InputStream 字节输入流基类

    操作步骤:
    1.打开字节输入流,可能会抛出FileNotFoundException异常
    FileInputStream inputStream = new FileInputStream(path);

    2.读取数据操作,-1表示读取结束,可能会抛出IOException异常
    int read = inputStream.read();

    3.关闭流,可能会抛出IOException异常
    inputStream.close();

    读操作介绍:
    每次读取一个字节,返回的结果为对应字节的数据:
    int read = inputStream.read();

    批量读取数据,将数据读入到arr的byte数组中,返回值为int类型,表示读取的有效数据的个数:
    inputStream.read(byte[] arr);

    批量读取数据,b[] 表示的是数据读入到的缓存地址,off表示读入的缓存起始位置,len表示从起始位置开始写入的数量,read方法返回值表示读取有效数据个数:
    int read(byte b[], int off, int len);

    InputStream实例:

    //用字节流读文件
    public static void inToFile() throws IOException {
        String path = new String("d:/helllo hcy.txt");
        File file = new File(path);
        byte[] b = new byte[(int) file.length()];
        //因为是用字节流来读媒介,所以对应的是InputStream
        //又因为媒介对象是文件,所以用到子类是FileInputStream
        FileInputStream ips = new FileInputStream(file);
        int size = ips.read(b);
        String s = new String(b);
        System.out.println("文件大小:"+size+"    文件内容:"+s);
        ips.close();
    }
  • OutputStream 字节输出基类

    操作步骤:
    1.打开字节输出流,可能会抛出FileNotFoundException异常
    FileOutputStream outputStream = new FileOutputStream(path);
    写操作时,文件不存在,会自动创建文件,并写入数据,当文件目录路径不合法时则会抛出异常

    2.写操作,可能会抛出IOException异常
    void write(int b) 每次写入一个字节

    3.关闭流,可能会抛出IOException异常
    outputStream.close();

    写操作介绍:
    void write(int b) 每次写入一个字节

    void write(byte b[]) 批量写入,写入类型为byte[]

    void write(byte b[], int off, int len) 批量写入,可以自定义从byte数组的起始和读取长度

    void flush(); 刷新缓存

    OutputStream 实例:

    //用字节流写文件
    public static void outToFile() throws IOException {
        String path = new String("d:/helllo hcy.txt");
        String s = new String("hello hcy!");
        byte[] b = s.getBytes();
        File file = new File(path);
        //因为是用字节流来写媒介,所以对应的是OutputStream
        //又因为媒介对象是文件,所以用到子类是FileOutputStream
        FileOutputStream ops = new FileOutputStream(file);
        ops.write(b);
        ops.close();
    }
  • Reader字符输入流基类

    操作步骤
    1.打开字符读操作流,可能会抛出FileNotFoundException异常
    FileReader reader = new FileReader(path);

    2.读操作,可能会抛出IOException异常
    reader.read();

    3.关闭字符读操作流
    reader.close();

    读操作介绍:
    int read()
    每次读取一个字符,读操作结束的返回值-1,返回值就是字符对应的ASCII码的数字

    int read(char cbuf[])
    批量读取数据,读操作结束的返回值-1,数据读取到char []数组中,返回值表示读取有效数据个数

    int read(char cbuf[], int offset, int length)
    批量读取数据,读操作结束的返回值-1,数据读取到char []数组中,可以指定读取数据的起始和大小,返回值表示读取有效数据个数

    Reader实例:

    //用字符流读文件
    public static void ReToFile() throws IOException {
        String path = new String("d:/helllo hcy.txt");
        File file = new File(path);
        char[] b = new char[(int)file.length()];
        //因为是用字符流来读媒介,所以对应的是Reader
        //又因为媒介对象是文件,所以用到子类是FileReader
        Reader reader = new FileReader(file);
        int size = reader.read(b);
        String s = new String(b);
        System.out.println("文件大小:"+size+"    文件内容:"+s);
        reader.close();
    }
  • Writer字符输出流基类

    操作步骤
    1.打开字符写操作流,可能会抛出IOException异常
    FileWriter writer = new FileWriter(path,true);
    构造函数 FileWriter(String fileName, boolean append) 第二个参数表示数据是否追加, true:追加的形式写入 false:覆盖原内容的形式写入 ,默认是false

    2.写操作,可能会抛出IOException异常
    writer.write(99);

    3.关闭写操作流,可能会抛出IOException异常
    writer.close();

    写操作介绍:
    void write(int c) 写入单个的字符

    void write(char cbuf[]),批量的写入字符,数据写入类型是char []

    void write(char cbuf[], int off, int len)批量的写入字符,自定义起始和长度

    void write(String str),直接写入字符串

    void write(String str, int off, int len)直接写入字符串,自定义写入字符串子集

    writer.append(“append”);追加数据,构造函数时append参数设置为true起作用

    writer.flush();刷新缓存
    Writer实例:

    //用字符写文件
    public static void WiToFile() throws IOException {
        String path = new String("d:/helllo hcy.txt");
        File file = new File(path);
        String s = new String("hello hcy!");
        //因为是用字符流来读媒介,所以对应的是Writer
        //又因为媒介对象是文件,所以用到子类是FileWriter
        Writer writer = new FileWriter(file,true);//表示允许数据追加
        writer.write(s);
        //追加数据
        writer.append("Here we are");
        writer.close();
    }

下图是Java IO中各类所负责的媒介:
在这里插入图片描述

使用流的规律:

1.明确是读操作还是写操作
读:InputStream/Reader
写:OutputStream/Writer
2.明确是操作字节还是字符(明确操作基类)
读:

  • 字节:InputStream
  • 字符:Reader

写:

  • 字节:OutputStream
  • 字符:Writer

3.操作的具体介质(明确操作的具体类)

读:

  • 文件:File
  • 内存:char,array,double
  • 网络:Socket
  • 键盘:Sysem.in

写:

  • 文件:File
  • 内存:char,array
  • 网络:Socket
  • 屏幕:System.out

4.是否需要额外操作
缓冲区:BufferXXX
转换:InputStreamReader、OutputStreamWriter
随机访问文件类:RandomAccessFile

  • 随机读取File文件:
    有时候我们希望读取文件的一部分,或者是说随机的读取文件,那么我们就可以利用RandomAccessFile。RandomAccessFile提供了seek()方法,用来定位将要读写文件的指针位置,我们也可以通过调用getFilePointer()方法来获取当前指针的位置,具体看下面的例子:
    //随机读取文件
    public static void randomAccessRead() throws IOException {
        String path = new String("d:/helllo hcy.txt");
        byte[] bytes = new byte[5];
        //创建一个RandomAccessFile对象
        RandomAccessFile raf = new RandomAccessFile(path,"rw");
        //通过seek()方法来移动读写位置的指针
        raf.seek(5);
        //获取当前指针的位置
        long pointerStart = raf.getFilePointer();
        //读文件
        raf.read(bytes);
        long pointerEnd = raf.getFilePointer();
        String s = new String(bytes);
        System.out.println("pointerStart:"+pointerStart+"pointerEnd:"+pointerEnd);
        System.out.println("读取内容:"+s);
        raf.close();
    }
  • 随机写入File文件:
    //用字符写文件
    public static void WiToFile() throws IOException {
        String path = new String("d:/helllo hcy.txt");
        File file = new File(path);
        String s = new String("hello hcy!");
        //因为是用字符流来读媒介,所以对应的是Writer
        //又因为媒介对象是文件,所以用到子类是FileWriter
        Writer writer = new FileWriter(file,true);//表示允许数据追加
        writer.write(s);
        //追加数据
        writer.append("Here we are");
        writer.close();
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值