字符流
字节数组读取中文问题无法保证读取是完整的内容,可能读取你好a就乱码
解决方案:使用字符流中是3个字符-按照字符为单位进行读取的原理 你好a在字符流中是3个字符
java.io.Reader close(): read(): 读取一个字符,返回对应的int数字(字符对应的int数字)
read(char[] chs): 读取一些字符,返回对应的int数字(字符的个数)
参数: char[] chs: 用来存储读取到的多个字符的内容
返回值类型: int: 读取到的字符的个数
FileReader类: 文件字符输入流,以字符的方式读取文件内容,读进来,源文件
构造方法: FileReader(File/String path类型的文件路径)
使用步骤:
1.创建文件字符输入流FileReader类的对象fr,绑定源文件
2.文件字符输入流FileReader类的对象fr调用read方法,以字符的方式读取文件内容
3.文件字符输入流FileReader类的对象fr调用close方法,关闭流,释放资源
补充: String的构造方法String(char[] chs): 把构造方法参数,按照平台默认编码表,转换成字符串
##使用Reader读取单个字符
public class Demo02Reader {
public static void main(String[] args) throws IOException {
//1.创建文件字符输入流FileReader类的对象fr,绑定源文件
FileReader fr = new FileReader("day12_sw\\f1.txt");
//2.文件字符输入流FileReader类的对象fr调用read方法,以字符的方式读取文件内容
//定义int变量,保存每次读取到的一个字符的内容
int ch = 0;
//从fr关联的文件中读取一个字符,返回对应的int数字,存储到ch中
//最后判断ch的值是否等于-1
while((ch = fr.read())!=-1) {
System.out.println((char)ch);
}
//3.文件字符输入流FileReader类的对象fr调用close方法,关闭流,释放资源
fr.close();
}
}
### 使用Reader读取字符数组
public class Demo02Reader {
public static void main(String[] args) throws IOException {
//1.创建文件字符输入流FileReader类的对象fr,绑定源文件
FileReader fr = new FileReader("day12_sw\\f1.txt");
//2.文件字符输入流FileReader类的对象fr调用read方法,以字符的方式读取文件内容
//定义int变量,保存每次读取到的字符的个数
int len = 0;
//定义字符数组,保存每次读取到的多个字符的内容
char[] chs = new char[2];
//从fr关联的文件中读取一些字符,存储到字符数组chs中,
//返回读取到的字符的数量存储到len中
//最后判断len的值是否等于-1
while ((len = fr.read(chs)) != -1) {
System.out.println(new String(chs,0,len));
}
//3.文件字符输入流FileReader类的对象fr调用close方法,关闭流,释放资源
fr.close();
}
}
字符串的编码和解码方法
WriterFileWirter写数据到文件
String的编码和解码?
问题1: 编码
如何获取字符串(String)指定编码表对应的字节数组(byte[])
String s = "你好";
//获取UTF-8编码
byte[] bs = s.getBytes();
//获取GBK编码
byte[] bs2 = s.getBytes("GBK");
问题2: 解码
如何把字节数组(byte[])按照指定编码表,转换成对应的字符串(String)呢?
//按照构造方法参数指定的编码表(GBK)解码
String s3 = new String(bs2, "GBK");
System.out.println(s3);
//编码和解码的规则不统一: 乱码
String s4 = new String(bs, "GBK");
System.out.println(s4);
你好 UTF-8编码: [-28, -67, -96, -27, -91, -67]
你好 GBK编码: [-60, -29, -70, -61]
java.io.Writer类: 字符输出流顶层抽象父类,以字符的方式写出内容,写出去
close(): 关闭流,释放资源
write(int ch): 写出一个字符
write(char[] chs): 写出一个字符数组
write(char[] chs,int startIndex,int len): 写出一个字符数组的一部分
参数: char[] chs: 字符数组 int startIndex: 起始索引 int len: 写出字节的数量
write(String str): 写出一个字符串
write(String str,int startIndex,int len): 写出一个字符串的一部分
参数: String str: 字符串
构造方法: FileWriter(File/String path类型的文件路径,boolean append)
参数: File/String 类型的文件路径 boolean append:
true: 续写/追加写 false: 重新写,覆盖写,不写此参数默认就是false
换行: 也是一个字符串 windows: \r\n linux/unix: \n
*/
使用步骤:
1.创建文件字符输出流FileWriter类的对象fw,绑定目标文件
2.文件字符输出流FileWriter类的对象fw调用write方法,以字符的方式写出内容到文件
3.文件字符输出流FileWriter类的对象fw调用close方法,关闭流,释放资源
Writer写数据的5个方法
public class Demo02Writer {
public static void main(String[] args) throws IOException {
//1.创建文件字符输出流FileWriter类的对象fw,绑定目标文件
FileWriter fw = new FileWriter("day12_sw\\fw.txt",true);
//2.文件字符输出流FileWriter类的对象fw调用write方法,以字符的方式写出内容到文件
//写出一个字符
fw.write(65);//文件中显示A
fw.write('a');//文件中显示a
fw.write("好");//文件中显示好
//写出一个字符数组
char[] chs = {'好','好','学','习','天','天','向','上'};
fw.write(chs);
//写出换行符
fw.write("\r\n");
//写出一个字符数组的一部分: 学习天天 重新写一遍
fw.write(chs,2,4);
//写出一个字符串
String s = "今天工作不努力,明天努力找工作";
fw.write(s);
//写出一个字符数组的一部分: 工作不努力,明天努力 重新写一遍
fw.write(s,2,10);
//3.文件字符输出流FileWriter类的对象fw调用close方法,关闭流,释放资源
fw.close();
}
}
flush和close的区别
flush方法之后,可以继续调用write方法写出数据
close方法之后,不能继续调用write方法写出数据
记住一句话: io流对象,使用完毕,务必关闭流对象
public class Demo04FlushVSClose {
public static void main(String[] args) throws IOException {
/*
//1.字节流内部没有缓冲区,只要调用write方法,就是写出到目的地,所以不关流,也不会丢失数据
FileOutputStream fos = new FileOutputStream("day12_sw\\fos.txt");
fos.write("你好".getBytes());
*/
FileWriter fw = new FileWriter("day12_sw\\fw3.txt");
for (int i = 0; i < 2; i++) {
fw.write("你好");
//刷新
//fw.flush();
fw.write("大家好");
}
int a = 1;
//死循环
while(a == 1) {
}
//关闭流,释放资源
fw.close();
//fw.write("大家好");//错误了,流已经被关闭
}
}
字符输出缓冲流
/* public BufferedWriter(Writer w):
参数: Writer w 字符输出流抽象类 传递子类FileWriter对象
特有方法: public void newLine() : 写入一个自适应平台的换行符
使用步骤:
1.创建Writer类的子类FileWriter对象fw,绑定目标文件
2.创建高效字符输出流BufferedWriter对象bw,传递Writer类的子类FileWriter对象
3.高效字符输出流BufferedWriter对象bw调用write方法,写出字符
4.关闭流
*/
public class Demo01BufferedWriter {
public static void main(String[] args) throws IOException {
//1.创建Writer类的子类FileWriter对象fw,绑定目标文件
FileWriter fw = new FileWriter("day12_xw\\bw.txt");
//2.创建高效字符输出流BufferedWriter对象bw,传递Writer类的子类FileWriter对象
BufferedWriter bw = new BufferedWriter(fw);
//3.高效字符输出流BufferedWriter对象bw调用write方法,写出字符
bw.write("犯错,就得被惩罚~~");
//写入使用操作系统的换行符
bw.newLine();
bw.write("犯错,不讲理由~~");
//4.关闭流
bw.close();
}
}
字符输入缓冲流使用
public BufferedReader(Reader r):
参数: Reader r 字符输入流抽象类 传递子类FileReader对象
read(): 读取一个字符 read(char[] chs):
读取一些字符,把读取到的一些字符存入到方法参数字符数组chs中
返回的是读取的字符的数量
特有方法: String readLine() : 读取一行文本 遇到文件结束标志: 返回null
读取到一行文本中,不包含换行符
使用步骤:
1.创建Reader类的子类FileReader对象fr,绑定源文件
2.创建高效字符输入流BufferedReader对象br,传递Reader类的子类FileReader对象
3.高效字符输入流BufferedReader对象br调用readLine方法,读取一行字符
4.关闭流
public class Demo02BufferedReader {
public static void main(String[] args) throws IOException {
//1.创建Reader类的子类FileReader对象fr,绑定源文件
FileReader fr = new FileReader("day12_xw\\bw.txt");
//2.创建高效字符输入流BufferedReader对象br,传递Reader类的子类FileReader对象
BufferedReader br = new BufferedReader(fr);
//3.高效字符输入流BufferedReader对象br调用readLine方法,读取一行字符
//定义String变量,用来接收每次读取到的一行字符串的内容
String line = null;
while((line = br.readLine())!=null){
System.out.print(line);
}
//4.关闭流
br.close();
}
}
练习: 把文本文件中的内容,以行为单位,按照每行前面的数字,从小到大排序
步骤:
1.创建List集合对象,泛型: String
2.创建BufferedReader类的对象br,绑定源文件
3.按行循环读取源文件
4.把读取到的每行存储到List集合对象中
5.调用Collections工具类中sort方法,对List集合对象排序(String排序规则: 按照第一个不相同的字母的ASCII码值,从小到大排序)
6.创建BufferedWriter类的对象bw,绑定目标文件
7.遍历List集合对象
8.把获取到的当前行,写出到目标文件
9.写入换行符
10.关闭资源
*/
public class Demo03TxtSort {
public static void main(String[] args) throws IOException {
//1.创建List集合对象,泛型: String
List<String> list = new ArrayList<>();
//2.创建BufferedReader类的对象br,绑定源文件
BufferedReader br =
new BufferedReader(new FileReader("day12_xw\\csb_no_sort.txt"));
//3.按行循环读取源文件
String line = null;
while ((line = br.readLine()) != null) {
//4.把读取到的每行存储到List集合对象中
list.add(line);
}
//5.调用Collections工具类中sort方法,对List集合对象排序
//(String排序规则: 按照第一个不相同的字母的ASCII码值,从小到大排序)
//Collections.sort(list);
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.charAt(0)-o2.charAt(0);
}
});
//6.创建BufferedWriter类的对象bw,绑定目标文件
BufferedWriter bw =
new BufferedWriter(new FileWriter("day12_xw\\csb_sort.txt"));
//7.遍历List集合对象
for (String s : list) {
//8.把获取到的当前行,写出到目标文件
bw.write(s);
//9.写入换行符
bw.newLine();
}
//10.关闭资源
br.close();
bw.close();
}
}
字符流乱码问题 原因: 文件中存储数据的编码表 和 读取文件时流对象使用的编码表不统一
/*
java.io.InputStreamReader类: 是一个字符流,以字符的方式读取内容
构造方法: InputStreamReader(InputStream in, String charsetName)
参数: InputStream in: 字节输入流抽象父类,传递子类FileInputStream类的对象
String charsetName: 编码表,常用GBK和UTF-8
java.io.OutputStreamWriter类: 是一个字符流,以字符的方式写出内容
OutputStreamWriter(OutputStream out, String charsetName)
参数:
OutputStream out: 字节输出流抽象父类,传递子类FileOutputStream类的对象
public class Demo03InputStreamReader {
public static void main(String[] args) throws Exception {
readUTF8();
}
//读取UTF8文件
private static void readUTF8() throws IOException {
//1.创建InputStream类的子类FileInputStream类的对象fis
//2.创建InputStreamReader类的对象isr,传递fis并指定编码表
InputStreamReader isr = new InputStreamReader(new FileInputStream("day12_xw\\utf8_1.txt"), "UTF-8");
//3.InputStreamReader类的对象isr调用read方法,读取文件内容
int len = 0;
char[] chs = new char[2];
while ((len = isr.read(chs)) != -1) {
System.out.println(new String(chs,0,len));
}
//4.InputStreamReader类的对象isr调用close方法,关闭流释放资源
isr.close();
}
}
public class Demo04OutputStreamWriter {
public static void main(String[] args) throws IOException {
writeUTF8();
return;
}
//写出UTF-8内容到文件
private static void writeUTF8() throws IOException {
//1.创建OutputStream类的子类FileOutputStream类的对象fos
//2.创建OutputStreamWriter类的对象osr,传递fos并指定编码表
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day12_xw\\utf8_2.txt"),"UTF-8");
//3.创建OutputStreamWriter类的对象osr调用write方法,写出字符到文件
osw.write("好好学习天天向上");
//4.创建OutputStreamWriter类的对象osr调用close方法,关闭流释放资源
osw.close();
}
}
##编码转换练习
将GBK编码的文本文件,转换为UTF-8编码的文本文件
*/
public class Demo05FromGBK2UTF8 {
public static void main(String[] args) throws Exception {
//1.创建InputStreamReader类的对象,绑定源文件,指定编码表GBK
InputStreamReader isr =
new InputStreamReader(new FileInputStream("day12_xw\\csb_gbk.txt"), "GBK");
//2.创建OutputStreamWriter类的对象,绑定目标文件,指定编码表UTF-8
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day12_xw\\csb_utf8.txt"), "UTF-8");
//3.字符数组循环读(源文件)写(目标文件)
int len = 0;
char[] chs = new char[1024];
while ((len = isr.read(chs)) != -1) {
osw.write(chs,0,len);
}
//4.关闭流
isr.close();
osw.close();
}
}
能否使用字符缓冲输入输出流,实现此案例呢? InputStream --> BufferedReader
是可以的因为是文本文件
public class Demo06FromGBK2UTF8 {
public static void main(String[] args) throws Exception {
//1.创建InputStreamReader类的对象,绑定源文件,指定编码表GBK
InputStreamReader isr = new InputStreamReader(new FileInputStream("day12_xw\\csb_gbk.txt"), "GBK");
//把 InputStreamReader --> BufferedReader
BufferedReader br = new BufferedReader(isr);
//2.创建OutputStreamWriter类的对象,绑定目标文件,指定编码表UTF-8
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day12_xw\\csb_utf8.txt"), "UTF-8");
//把 OutputStreamWriter --> BufferedWriter
BufferedWriter bw = new BufferedWriter(osw);
//3.循环按行读(源文件)写(目标文件)
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
//写出换行
bw.newLine();
}
//4.关闭流
br.close();
bw.close();
}
}