Java基础09-IO流

IO流使用总结

  1. 流对象太多开发时不知应该使用哪个流对象
  2. 根据四个明确即可确定开发时使用哪个流对象
  3. 四个明确
    1. 明确源和目的地
      1. 源: InputStream Reader
      2. 目的地:OutputStream Writer
    2. 明确数据是否是纯文本数据
      1. 源:是纯文本数据 Reader
      2. 不是纯文本数据 InputStream
      3. 目的地:是纯文本数据 Writer
      4. 不是纯文本数据 OutputStream
      5. 此时可以明确使用哪个流体系
    3. 明确具体的设备
      1. 源设备:
        1. 键盘:System.in
        2. 硬盘:File
        3. 内存:数组
        4. 网络:Socket流
      2. 目的地设备:
        1. 硬盘:File
        2. 键盘:System.out
        3. 内存:数组
        4. 网络:Socket流
    4. 是否需要额外的功能:
      1. 是否需要高效(缓冲区)
        1. 加Buffered
    5. 什么时候使用转换流呢?
      1. 提高对文本操作的便捷
      2. 操作文本涉及到指定编码时,必须使用转换流。

输入输出流(按方向分)

image

处理数据输入输出流的方式就是IO技术

  1. IO流用来处理设备之间的数据传输
  2. Java对数据的操作是通过流的方式
  3. Java用于操作流的对象都在IO包中
  4. 流按照操作数据分为两种:字节流与字符流
  5. 流按流向分为:输入流,输出流
  6. 读(输入),写(输出)
  7. 输入流和输出流是相对于内存设备而言。
    1. 将外设中的数据读取到内存中:输入
    2. 将内存中的数据写入到外设中:输出。

字节流,字符流(按内容分)

  1. 国际标准码表Unicode
  2. GBK和Unicode两张码表的编码方式不一样
  3. 字符流的由来:字节流读取文字字节数据后,不直接操作而是先查指定的编码表,获取对应的文字,然后再对这个文字进行操作。简单说:字节流+编码表

IO流常用基类

  1. 字节流的抽象基类:
    InputStream 、 OutputStream
  2. 字符流的抽象基类:
    Reader 、 Writer
  3. 注:由这四个类派生出来的子类,名称都是以其父类名作为子类名的后缀。
    如:InputStream的子类FileInputStream。
    如:Reader的子类FileReader

Demo,创建文件写入文件内容

需求:将一些文字存储到硬盘一个文件中
记住:如果要操作文字数据,建议优先考虑字符流
要将数据从内存写到硬盘上,要使用字符流中的输出流:Writer
硬盘中的数据基本体现是文件,希望找到一个可以操作文件的Writer(FileWriter)

package com.gaopeng.IO;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class Demo01 {
    public static void main(String[] args) throws IOException {
        /*
        * 创建一个可以往文件中写入字符数据的字符输出流对象
        * 既然是往一个文件中写入文字数据,那么在创建对象时,就必须明确该文件(用于存储数据的地方)
        * 如果文件不存在,自动创建文件
        * 如果文件存在,则文件会被覆盖
        * */
        FileWriter file = new FileWriter("demo.txt");
        //写入数据
        //数据写入到了临时存储缓冲区中
        file.write("哈哈");
        //刷新该流的缓冲,将数据写入到目标文件中
        file.flush();
        //关闭流之前会先进行刷新操作
        file.close();
    }
}

换行和续写

public class Demo02 {
    //获取运行系统的换行符
    private static final String LINE_SEPARATOR = System.getProperty("line.separator");

    public static void main(String[] args) throws IOException {
        FileWriter file = new FileWriter("demo.txt");
        file.write("abcwer"+LINE_SEPARATOR+"haha");
        file.flush();
        file.close();
        //对文件进行续写
        FileWriter file1 = new FileWriter("demo.txt",true);
        file1.write("这是一个续写");
        file1.close();
    }
}

读取单个字符(效率低)
读取字符到数组(效率高一些)
image

public class Demo04 {
    public static void main(String[] args) throws IOException {
        /*
        * 1.创建读取字符数据的流对象
        * 2.创建流对象时,必须要确定流对象是存在的,
        * 3.用一个读取流关联一个已存在文件
        * */
        FileReader fileReader = new FileReader("demo.txt");

        //按单个字符读取文件
//        int chr=0;
//        while((chr=fileReader.read())!=-1){
//            System.out.println((char)chr);
//        }

        //读取字符到数组,单个的从硬盘中取字符,一个一个的存到数组中
        //一般给予数组空间的大小位1024的整数被,1024个字节为1k
        char[] chr2 = new char[1024];
        int num=0;
        while((num=fileReader.read(chr2))!=-1){
            System.out.println(new String(chr2,0,num));
        }

        //关闭流
        fileReader.close();
    }
}

复制文件的操作
image

package com.gaopeng.IO;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Demo05 {
    public static void main(String[] args) throws IOException {
        //需求:复制文件
        //1.读取源数据 2.写入目的地文件 3.关闭流
        FileReader fileReader = new FileReader("demo.txt");
        FileWriter fileWriter = new FileWriter("demo01.txt");
        //创建临时容器存储字符
        char[] temp=new char[1024];
        //创建变量存储,读取到的字符个数
        int num=0;
        while ((num=fileReader.read(temp))!=-1){
            fileWriter.write(temp,0,num);
        }
        fileReader.close();
        fileWriter.close();
    }
}

字符流缓冲区

  1. 缓冲区的出现提高了对数据的读写效率
  2. 对应类
    1. BufferedWriter
    2. BufferedReader
  3. 缓冲区要结合流才可以使用
  4. 在流的基础上对流的功能进行增强
    使用缓冲区写入文件
package com.gaopeng.IO;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class Demo06 {
    public static void main(String[] args) throws IOException {
        FileWriter fileWriter = new FileWriter("demo.txt");
        //创建缓冲区对象,需要和被缓冲的流相关联
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        //建立了关联之后,写入-刷新-关闭,都使用buffer对象就ok
        bufferedWriter.write("hahaha");
        //换行操作
        bufferedWriter.newLine();
        bufferedWriter.write("hahaha");
        bufferedWriter.flush();
        bufferedWriter.close();
    }
}

缓冲区读文件图解及readLine()实现原理
image

public class Demo07 {
    public static void main(String[] args) throws IOException {
        FileReader fileReader = new FileReader("demo.txt");
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        String line=null;
        while((line=bufferedReader.readLine())!=null){
            System.out.println(line);
        }
        bufferedReader.close();
    }
}

缓冲区实现文件复制

package com.gaopeng.IO;

import java.io.*;

public class Demo08 {
    public static void main(String[] args) throws IOException {
        //使用缓冲区实现文件复制
        FileReader fileReader = new FileReader("demo.txt");
        FileWriter fileWriter = new FileWriter("demo02.txt");
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        String line=null;
        while((line=bufferedReader.readLine())!=null){
            bufferedWriter.write(line);
            bufferedWriter.newLine();
            bufferedWriter.flush();
        }
        //关闭流
        bufferedReader.close();
        bufferedWriter.close();
    }
}

自定义缓冲区

package com.gaopeng.IO;

import java.io.FileReader;
import java.io.IOException;

public class MyBufferedReader {
    //获取操作对象
    //定义缓冲区
    //定义缓冲区存在字符个数
    //定义缓冲区指针位置
    private FileReader reader;
    private char[] chrArr=new char[1024];
    private int pos=0;
    private int count=0;
    MyBufferedReader(FileReader reader){
        this.reader=reader;
    }
    public int myRead() throws IOException {
        //如果count等于0,就要读取数据存入缓冲区中
        if (count==0){
            int num = reader.read(chrArr);
            if (num==-1){
                return -1;
            }
            count=num;
            //每次存完之后就将指针置为零
            pos=0;
        }
        int re=chrArr[pos];
        pos++;
        count--;
        return re;
    }
    public String myReadLine() throws IOException {
        //因为是返回一个字符串,可以将缓冲区定义为StringBuilder
        StringBuilder sb = new StringBuilder();
        pos=0;
        count=0;
        //调用单个字符读取方法
        int num=0;
        while((num=myRead())!=-1){
            if ((char)num=='\r'){
                continue;
            }
            if((char)num=='\n'){
                return sb.toString();
            }
            //将字符添加到sb中
            sb.append((char)num);
        }
        //判断是否为空
        if (sb.length()!=0){
            return sb.toString();
        }
        return null;
    }

    public void close() throws IOException {
        reader.close();
    }
}
posted @ 2021-09-28 23:08  争取做百分之一  阅读(29)  评论(0)    收藏  举报