IO流(字符流)

字符流

1.概念
2.写入与读取
3.文本文件的拷贝
4.使用字符流的情况
5.使用BufferedReader和BufferedWriter
6.装饰设计模式
7.不同码表读取字符的转换

1.概念

字符流:直接读取字符的IO
字符流读取字符,先读取字节然后转换为字符,写入时将字符转化为字节后写入

2.写入与读取

  • 读取(FileReader)
    在这里插入图片描述
    FileReader的用法和我们上一节内容FileInputStream相似,一下是用法案例:
try {
    FileReader fileReader = new FileReader("student.txt");
    int x;
    while ((x = fileReader.read()) != -1) {
        System.out.print((char) x);
    }
    fileReader.close();
} catch (Exception e) {
    e.printStackTrace();
}

读出文件中的内容
如何识别字符
GBK码表中,在系统未升级之前,中文字符的码值都是以负数形式存在的,系统升级之后,中文的第一个字节的码值为负数,当读取到第一个字节为负值时,GBK读取时就读取两个字节。通过项目默认的码表依次读取一个字符。

  • 写入(File Writer)
    与读取的规则相同,在读取文件之前必须保证文件存在,在往文件中写数据之前只需要保证路径存在无误即刻
    注意事项:
    在这里插入图片描述只传入一个参数时,文件中原来的内容会清空。
FileWriter fileWriter = null;
try {
    fileWriter = new FileWriter("student.txt");
    fileWriter.write("热爱学习!!!");
    fileWriter.close();
} catch (Exception e) {
    e.printStackTrace();
}

3.文件的拷贝

  • 1.一个一个读取
FileReader fileReader = null;
try {
    fileReader = new FileReader("student.txt");
    FileWriter fileWriter = new FileWriter("newstudent,txt");
    int x;
    while ((x = fileReader.read()) != -1) {
        fileWriter.write(x);
    }
    fileReader.close();
    fileWriter.close();
} catch (Exception e) {
    e.printStackTrace();
}

注意事项:
输出流一定要关闭,在底层使用了缓存区,如果不关流,可能不能写入成功,内容一直在缓存区中,关闭流可以使缓存区的数据写入文件中。

  • 2.自定义小数组的文件拷贝(效率更高)
public static void main(String[] args) throws IOException {
    // write your code here
    FileReader fileReader = new FileReader("student.txt");
    FileWriter fileWriter = new FileWriter("bulala.txt");
    int x;
    char[] chars = new char[1024]; //读取的是字符所以用char 而不是字节!!
    while ((x = fileReader.read(chars)) != -1) {
        fileWriter.write(chars,0,x);
    }
    fileReader.close();
    fileWriter.close();
}

使用字符流的情况

  • 当只进行读取和写入操作时,可以使用字符流。
  • 但是在拷贝文本文件时不推荐使用字符流,底层会进行字符与字节的转化,(读取时将字节转化为字符,当写入时将字符转化为字节)计算机内部都是使用字节存储,直接使用字符流更好。
  • 字符流不能拷贝非纯文本文件,比如视频、照片之类的文件。

原因:当字符流拷贝非纯文本文件时,会将字节转化为字符(根据字节在对应的码表中找对应的字符,但是在字节拼接找字符的过程中可能出现错误,写出的时候会将字符转化为字节写出去,此时会将"?"也写出,写入也是乱的)

使用BufferReader和BufferWriter

在使用小数组之后我们就可以想到一个更节省空间的方法,使用缓冲区

BufferedReader bufferedReader = new BufferedReader(new FileReader("student.txt"));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("newnewstudent.txt"));
int x;
while ((x = bufferedReader.read()) != -1) {
    bufferedWriter.write(x);
}
bufferedReader.close();
bufferedWriter.close();
  • 一行一行读取
    在这里插入图片描述
    在这里插入图片描述
    读取之后不会包括换行
BufferedReader bufferedReader = new BufferedReader(new FileReader("student.txt"));
String line;
while ((line = bufferedReader.readLine()) != null) {
    System.out.println(line);
}
bufferedReader.close();
  • 一行一行的写入(写入换行)
    在这里插入图片描述
    在这里插入图片描述
BufferedReader bufferedReader = new BufferedReader(new FileReader("student.txt"));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("xxx.txt"));
String line;
while ((line = bufferedReader.readLine()) != null) {
    bufferedWriter.write(line);
    bufferedWriter.newLine();
}
bufferedReader.close();
bufferedWriter.close();
  • newLine()和“\r\n”的区别

newLine()可以跨平台,而“\r\n”只适应windows系统。

  • 加行号读取(类LineNumberReader)
LineNumberReader lineNumberReader = new LineNumberReader(new FileReader("student.txt"));
String s;
//lineNumberReader.setLineNumber(n);行号从n+1开始,原来的第一行,现在是n+1行
while ((s = lineNumberReader.readLine()) != null) {
    System.out.println(lineNumberReader.getLineNumber() + s);
}
lineNumberReader.close();

在这里插入图片描述

装饰设计模式

  • 步骤:(1)获取装饰类的对象(2)构造函数中传入装饰类的对象(3)对原有的功能进行升级
  • BufferedReader等类即采用这种设计模式
interface Style {
    public abstract void code();
}
class Student implements Style{
    
    @Override
    public void code() {
        System.out.println("学习挖掘机");
    }
}
class GStudent implements Style {
    //步骤一
    private Student student;
    //步骤二
    public GStudent(Student student) {
        this.student = student;
    }

    @Override
    public void code() {
        student.code();
        System.out.println("学习java");
    }
}

不同码表的读写

常使用类 InputStreamReader 和 OutputStreamWriter

  • 一般直接转化会出现问题:在UTF-8码表中中文为三个字节,在JBK码表中中文是两个字节,在转化时会出现乱码问题。
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("student.txt"),"GBK");
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("newstudent.txt"),"UTF-8");
int x;
while ((x = inputStreamReader.read()) != -1) {
    outputStreamWriter.write(x);
}
inputStreamReader.close();
outputStreamWriter.close();

建议增加缓冲区,进行进一步优化

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("student.txt"),"GBK"));
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("newstudent,txt"),"UTF-8"));
int x;
while ((x = bufferedReader.read()) != -1) {
    bufferedWriter.write(x);
}
bufferedReader.close();
bufferedWriter.close();

图解理解:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值