14_IO_字符流

文章目录

  • IO 字符流
    • 字符是怎么存储在计算机中的
    • 编码表
    • 编解码
  • 字符输出流
    • 抽象基类 writer
    • OutputStreamWriter转换流
    • FileWriter简化流
    • BufferedWriter缓冲流
  • 字符串输入流
    • 抽象基类Reader
    • InputStreamReader转换流
    • FileReader简化流
    • BufferedReader缓冲流
  • 字符流的文件复制

IO 字符流

  • 使用字节流读取英文数字
    • 没有问题
  • 使用字节流读取中文
    • 可能有问题

字符流的本质:字节流 + 编码表

字符是怎么存储在计算机中的

基于某个编码表. 每个字符对应这一个整数值(编码值), 计算机存的就是这个整数值

编码表

  • ASCII:美国标准信息交换码。
    一个字节的7位可以表示。0000 0000 - 0111 1111

  • ISO8859-1:拉丁码表。欧洲码表
    一个字节的8位表示。 0000 0000 - 1111 1111

  • GB2312:中国的中文编码表。

  • GBK:中国的中文编码表升级,融合了更多的中文文字符号。2个字节表示一个中文

  • GB18030:GBK的取代版本

  • BIG-5码 :通行于台湾、香港地区的一个繁体字编码方案,俗称“大五码

  • Unicode:国际标准码,融合了多种文字。

  • UTF-8:可变长度来表示一个字符。

    • UTF-8不同,它定义了一种“区间规则”,这种规则可以和ASCII编码保持最大程度的兼容
  • UTF-16:jvm使用的编码表,用2个字节来编解码

常用的

  • ASCII --> 1个字节的低7位(0 ~ 127128个字符
  • ISO8859-1 --> 1个字节
  • GBK --> 2个字节表示一个中文字符
  • UTF-8 --> 3个字节表示一个中文字符

编解码

默认的编码表

  • idea: Utf-8
  • Win: GBK (ANSI 默认的)

获取编码表

        System.out.println(Charset.defaultCharset());

eg:

// 编码
String s = "你好";

// getBytes()
// 使用平台的默认字符集将此 String 编码为 byte 序列,
// 并将结果存储到一个新的 byte 数组中。
byte[] bytes = s.getBytes();
System.out.println(Arrays.toString(bytes));

// getBytes(String charsetName)
// 使用指定的字符集将此 String 编码为 byte 序列,
// 并将结果存储到一个新的 byte 数组中。
byte[] gbks = s.getBytes("GBK");
System.out.println(Arrays.toString(gbks));

// 解码
// 利用String的构造方法
// String(byte[] bytes)
// 通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
String s1 = new String(bytes);
System.out.println(s1);

// 利用指定的字符集
// String(bytes[] b, String charsetName)
String s2 = new String(gbks,"GBK");
System.out.println(s2);

乱码问题

  • 产生的原因: 编码解码不一致
  • 解决: 使其一致

字符输出流

抽象基类 writer

写入字符流的抽象类

继承关系

14_IO_字符流_第1张图片

成员方法

14_IO_字符流_第2张图片
注意

  • 字节流里不能操纵字符串,但是字符流里可以操纵字符串

OutputStreamWriter转换流

OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

构造方法

OutputStreamWriter(OutputStream out)        
// 创建使用默认字符编码的 OutputStreamWriter。

OutputStreamWriter(OutputStream out, String charsetName)        
// 创建使用指定字符集的 OutputStreamWriter。

成员方法

  • 父类中的5个write方法
    • 3个跟字符相关的方法
    • 2个跟字符串相关的方法

eg:

// 1. 创建输出流对象
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("a.txt"));

// 2. write
// 2.1 write(int c) 写单个字符
out.write(97);
out.write(System.lineSeparator());

// 2.2 write(char[] c) 写字符数组
String s = "hello world";
char[] charArray = s.toCharArray();
out.write(charArray);
out.write(System.lineSeparator());

// 2.3 write(char[] c, int off ,int len)
out.write(charArray,0,3);

// 2.4 write(String s)
out.write(s);
out.write(System.lineSeparator());

// 2.5 write(String s, int off ,int len)
out.write(s,0,3);

// 3. flush
out.flush();

// 4. close
out.close();

FileWriter简化流

用来写入字符文件的便捷类

简化流是转化流的直接子类

构造方法


FileWriter(File file)        
// 根据给定的 File 对象构造一个 FileWriter 对象。

FileWriter(File file,  boolean append)       
// 根据给定的 File 对象构造一个 FileWriter 对象。

FileWriter(String fileName)        
// 根据给定的文件名构造一个 FileWriter 对象。

FileWriter(String fileName,  boolean append)       
// 根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造  FileWriter 对象。

构造方法

5个write
其中:3个跟字符相关的,2个跟字符串相关的

eg:


/*
使用简化流写数据FileWriter
 */
 
// 1. 创建输出流对象
FileWriter fw = new FileWriter("a.txt");

// 2. write
fw.write("hello world");

// 3. flush
fw.flush();

// 4. close
fw.close();

BufferedWriter缓冲流

将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了

构造方法


BufferedWriter(Writer out)       
// 创建一个使用默认大小输出缓冲区的缓冲字符输出流。默认缓冲区大小是16KB

BufferedWriter(Writer out,  int sz)      
// 创建一个使用给定大小输出缓冲区的新缓冲字符输出流。缓冲区大小size

成员方法

14_IO_字符流_第3张图片

  • 5 + 1:
    • 5常规的write

    • 1独有的方法

    • newLine() 写入一个行分隔符。

eg:

/*
使用缓冲流进行读写数据
 */
 
// 1. 创建输出流对象
BufferedWriter bw =
        new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt")));
BufferedWriter bw1 =
        new BufferedWriter(new FileWriter("a.txt"));

// 2. write
bw.newLine();
bw.write("hello hi");

// 3. flush
bw.flush();

// 4. close
bw.close();
bw1.close();

字符串输入流

抽象基类Reader

用于读取字符流的抽象类

成员方法


read()
// 返回值为int 
// 读取单个字符。作为整数读取的字符,范围在 0 到 65535 之间 (0x00-0xffff),
// 如果已到达流的末尾,则返回 -1   用readData 读取到的字符值

read(char[] cbuf)
// 返回值为int        
// 将字符读入数组。读取的字符数,
// 如果已到达流的末尾,则返回 -1 用readCount表示 读取到的字符的个数

read(char[] cbuf,  int off, int len)       
// 返回值为int,并且是抽象方法
// 将字符读入数组的某一部分。

InputStreamReader转换流

构造方法


InputStreamReader(InputStream in)        
// 创建一个使用默认字符集的 InputStreamReader。

InputStreamReader(InputStream in, String charsetName)        
// 创建使用指定字符集的 InputStreamReader。

成员方法

3个read方法


read()

read(char[] c)

read(char[] c ,int off, int len)

eg:


// 1. 创建输入流对象
InputStreamReader in = new InputStreamReader(new FileInputStream("a.txt"));

// 2.1 read() 读取单个字符
int readData = in.read();
System.out.println(((char) readData));

// 2.2 read(char[] c) 批量读取
char[] chars = new char[1024];
int readCount = in.read(chars);
String s = new String(chars, 0, readCount);
System.out.println(s);

// 3. close
in.close();

FileReader简化流

构造方法


FileReader(File file)        
// 在给定从中读取数据的 File 的情况下创建一个新 FileReader。

FileReader(String fileName)        
// 在给定从中读取数据的文件名的情况下创建一个新 FileReader。

成员方法

3个read

eg:

/*
使用FileReader读取数据
 */

// 1. 创建输入流对象
FileReader fr = new FileReader("a.txt");

// 2. read
char[] chars = new char[1024];
int readCount = fr.read(chars);
System.out.println(new String(chars,0,readCount));

// 3. close
fr.close();

转换流VS简化流

  • 使用角度, 简化流简单, 转换流麻烦
  • 继承关系, 转换流是简化流的父类
  • 核心区别, 简化流不能指定字符集(使用默认的字符集), 转化流可以指定的字符集

BufferedReader缓冲流

从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了

构造方法


BufferedReader(Reader in)       
// 创建一个使用默认大小输入缓冲区的缓冲字符输入流。

BufferedReader(Reader in,  int sz)      
// 创建一个使用指定大小输入缓冲区的缓冲字符输入流。

成员方法
14_IO_字符流_第4张图片

  • 3+1:
    • 3个常规read

    • 1个独有的方法(readLine() 读取一个文本行。如果已到达流末尾,则返回 null

eg:

/*
使用缓冲的字符流读写数据
 */

// 1. 创建输入流对象
BufferedReader bufferedReader = 
        new BufferedReader(new FileReader("a.txt"));

// 2. read
char[] chars = new char[1024];
int readCount = bufferedReader.read(chars);
System.out.println(new String(chars,0,readCount));

// 3. close
bufferedReader.close();


字符流的文件复制

eg:

构造字符流的Utils包

// 单字符流进行复制
public static void copy3(Reader reader, Writer writer) throws IOException{
    int readData;
    while((readData = reader.read()) != -1){
        writer.write(readData);
    }
}

// 字符数组方式进行复制
public static void copy4(Reader reader, Writer writer) throws IOException{
    int readCount;
    char[] chars = new char[1024];
    while((readCount = reader.read(chars)) != -1){
        writer.write(chars,0,readCount);
    }
}

你可能感兴趣的:(JavaSE,java)