字符流
字符流概述
字符流 : 只能操作计算机中的字符文件
//文件复制案例 : 不管文件类型,全用字节流!
//操作字符文件时,字节流会不方便,所以推荐使用字符流
//字符文件 : 拿windows自带的记事本工具打开
字符流的本质 : 底层还是字节流,只不过做了高度封装! //字符流是包装流,字符流带缓冲区
字符流 = 字节流 + 编码格式;
//字符输出流输出内容需要刷新缓冲区 !!
字符流的根节点 : Reader/Writer -> 抽象类
普通字符流 : FileWriter/FileReader -> 不常用,效率低
高效字符流 : BufferedWriter/BufferedReader -> 常用,效率高
FileWriter/FileReader
FileWriter/FileReader : 普通字符流
FileWriter : 文件字符输出流
构造方法 :
FileWriter(String fileName) //目标文件
FileWriter(File file)
//带追加写 : FileOutputStream/FileWriter
FileWriter(String fileName, boolean append)
FileWriter(File file, boolean append)
写的方法 :
一次写一个字符 : void write(int ch)
一次写一个字符数组 : void write(char[] chs)
一次写一个字符数组的一部分 : void write(char[] chs,int offset,int length)
一次写一个字符串 : void write(String str)
一次写一个字符串的一部分 : void write(String str,int offset,int length)
FileReader : 文件字符输入流
构造方法 :
FileReader(String fileName) //源文件
FileReader(File file) //源文件
读的方法 :
一次读一个字符 : int read()
一次读一个字符数组 : int read(char[] chs)
一次读一个字符数组的一部分 : int read(char[] chs,int offset,int length)
//没有一次读一个字符串的方法
标准代码
普通字符流一次一个字符复制字符文件:
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class 普通字符流一次一个字符复制字符文件 {
public static void main(String[] args) throws IOException {
//创建流
FileWriter fw = new FileWriter("目标文件地址");
FileReader fr = new FileReader("源文件地址");
//循环读写
int ch;//存储每次读到的一个字符
while((ch = fr.read()) != -1){
//读一个字符,写一个字符
fw.write(ch);
//手动刷新
fw.flush();
}
//关流
fw.close();
fr.close();
}
}
普通字符流一次一个字符数组复制字符文件:
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class 普通字符流一次一个字符数组复制字符文件 {
public static void main(String[] args) throws IOException {
//创建流
FileWriter fw = new FileWriter("目标文件地址");
FileReader fr = new FileReader("源文件地址");
//循环读写
char[] chs = new char[1024];
int len;//统计每次读到的字符个数
while ((len = fr.read(chs)) != -1){
//读了多少写多少
fw.write(chs,0,len);
//刷新
fw.flush();
}
//关流
fw.close();
fr.close();
}
}
BufferedWriter/BufferedReader
BufferedWriter/BufferedReader : 高效字符输出/字符输入流 (自动刷新的缓冲区)
构造方法 :
BufferedWriter(Writer writer)
BufferedReader(Reader reader)
常规读写方法 :
写的方法:
一次写一个字符 : void write(int ch)
一次写一个字符数组 : void write(char[] chs)
一次写一个字符数组的一部分 : void write(char[] chs,int offset,int length)
一次写一个字符串 : void write(String str)
一次写一个字符串的一部分 : void write(String str,int offset,int length)
读的方法 :
一次读一个字符 : int read()
一次读一个字符数组 : int read(char[] chs)
一次读一个字符数组的一部分 : int read(char[] chs,int offset,int length)
//没有一次读一个字符串的方法
标准代码
高效字符流一次一个字符复制字符文件:
import java.io.*;
public class 高效字符流一次一个字符复制字符文件 {
public static void main(String[] args) throws IOException {
//创建流
BufferedWriter bw = new BufferedWriter(
new FileWriter("目标文件地址"));
BufferedReader br = new BufferedReader(
new FileReader("源文件地址"));
//循环读写
int ch;//存储每次读到的一个字符
while((ch = br.read()) != -1){
//读一个字符,写一个字符
bw.write(ch);
}
//关流
bw.close();
br.close();
}
}
高效字符流一次一个字符数组复制字符文件:
import java.io.*;
public class 高效字符流一次一个字符数组复制字符文件 {
public static void main(String[] args) throws IOException {
//创建流
BufferedWriter bw = new BufferedWriter(new FileWriter("目标文件地址"));
BufferedReader br = new BufferedReader(new FileReader("源文件地址"));
//循环读写
char[] chs = new char[1024];
int len;//统计每次读到的字符个数
while ((len = br.read(chs)) != -1){
//读了多少写多少
bw.write(chs,0,len);
}
//关流
bw.close();
br.close();
}
}
高效字符流一次一行复制字符文件:
import java.io.*;
public class 高效字符流一次一行复制字符文件 {
public static void main(String[] args) throws IOException {
//创建流
BufferedWriter bw = new BufferedWriter(
new FileWriter("目标文件地址"));
BufferedReader br = new BufferedReader(
new FileReader("源文件地址"));
//循环读写
String line;//来存储每次读到的一行数据
while((line = br.readLine()) != null){
//读一行写一行
bw.write(line);
//补上换行符
bw.newLine();
}
//关流
bw.close();
br.close();
}
}
编码格式
编码和解码
码 : 二进制码(010101011100011) -> 硬盘中的字节 -> 文件 (字符文件)
编码 : 编写二进制码 (文字 --> 二进制码) --> 看得懂的到看不懂的
解码 : 解析二进制码 (二进制码 --> 文字) --> 看不懂的到看得懂的
文件乱码的问题
编码 : 编写二进制码 (文字 -(以何种方式编)-> 二进制码) --> 看得懂的到看不懂的
解码 : 解析二进制码 (二进制码 -(以何种方式解)-> 文字) --> 看不懂的到看得懂的
以何种方式编/以何种方式解 : 编码格式(编码表)
乱码产生的根本原因 : 编码和解码的方式不一致
文件乱码的解决方案 : 修改文件的编码格式和平台的编码格式一致!!!
编码表
编码表 : 字节和文字转换之间的 "密码本" ; //如果编码和解码的"密码本"不一致就会乱码!
字符集 : 一个字符集中有多套编码表;
最基础的字符集 : ASCII (美国标准信息交换码表) -> 只能解决英文环境下的语言编码问题
//英文字母,数字 是不会乱码的,所有的编码表的前128位都是ASCII
中文字符集 : GB系列 (国标系列)
GB2312 : 早期的中文编码表
GBK : 现在最常用的中文编码表
//GBK 是使用2个字节表示一个中文汉字的
"国际统一组织" : 统一了 万维网上的 编码格式
设计了一个字符集 : Unicode 字符集
UTF-8 编码表 : 互联网数据的统一编码格式;
//UTF-8 编码表 是使用3个字节表示一个中文汉字
UTF-16
UTF-32
ANSI : 它不是一种编码表--> 本地字符集 : windows系统会根据时区和系统语言自动的切换ANSI本地字符集所代表的编码格式;
ANSI = 当前电脑的默认字符集;
String的编码和解码方法
String的编码 : String -> byte[] -> 二进制码
成员方法
1. byte[] getBytes() : 把调用方法的字符串对象转换成byte[] //按照平台默认的编码格式
2. byte[] getBytes(String charsetName) : 把调用方法的字符串对象转换成byte[] //按照传入的编码格式
String的解码 :二进制码 -> byte[] -> String
构造方法
String(byte[] bys) : 按照平台默认的编码格式对字节数组进行解码操作
String(byte[] bys,String charsetName) : 按照指定的编码格式对字节数组进行解码操作
String(byte[] bys,int offset,int length) : 按照平台默认的编码格式对字节数组进行解码操作
String(byte[] bys,int offset,int length,String charsetName) : 按照指定的编码格式对字节数组进行解码操作
例:
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class Demo {
public static void main(String[] args) throws UnsupportedEncodingException {
//定义一个字符串
String str = "我爱你";
//编码操作
byte[] bys1 = str.getBytes();
byte[] bys2 = str.getBytes("GBK");
System.out.println("Arrays.toString(bys1) = " + Arrays.toString(bys1));
System.out.println("Arrays.toString(bys2) = " + Arrays.toString(bys2));
//解码
String str1 = new String(bys1);
String str2 = new String(bys2,"gbk");
System.out.println("str1 = " + str1);
System.out.println("str2 = " + str2);
}
}