Java学习日志(二十一)
- 缓冲流
- 原理
- 字节缓冲输出流:BufferedOutputStream
- 字节缓冲输入流:BufferedInputStream
- 字符缓冲输出流:BufferedWriter
- 字符缓冲输入流:BufferedReader
- 文件复制
- 文件排序
- 转换流
- 原理
- 字符转换输出流:OutputStreamWriter
- 字符转换输入流:InputStreamReader
- 转换文件编码
缓冲流
原理
字节缓冲输出流:BufferedOutputStream
java.io.BufferedOutputStream extends OutputStream
BufferedOutputStream:字节缓冲输出流
继承自父类OutputStream中的成员方法:
-
void write(int b)
写一个字节 -
void write(byte[] b)
写一个字节数组 -
void write(byte[] b, int off, int len)
写字节数组的一部分,off数组的开始索引,len写的字节个数 -
void flush()
刷新此输出流并强制写出任何缓冲的输出字节。 -
void close()
关闭此输出流并释放与此流关联的所有系统资源。
构造方法:
BufferedOutputStream(OutputStream out)
创建新的缓冲输出流以将数据写入指定的基础输出流。BufferedOutputStream(OutputStream out, int size)
创建新的缓冲输出流,以使用指定的缓冲区大小将数据写入指定的基础输出流。
参数:
OutputStream out:字节输出流,可以传递FileOutputStream,BufferedOutputStream就会给FileOutputStream增加一个缓冲区(数组),提高FileOutputStream写入数据的效率。
int size:指定的缓冲区的大小
字节缓冲输出流的使用步骤:
- 创建字节缓冲输出流BufferedOutputStream对象,构造方法中传递FileOutputStream对象
- 使用BufferedOutputStream对象中的方法write,把数据写入到内存缓冲区
- 使用BufferedOutputStream对象中的方法flush,把内存缓冲区中的数据刷新到文件中
- 释放资源
代码示例:
public class Demo01 {
public static void main(String[] args) throws IOException {
//1. 创建字节缓冲输出流BufferedOutputStream对象,构造方法中传递FileOutputStream对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day10\\bu.txt"));
//2. 使用BufferedOutputStream对象中的方法write,把数据写入到内存缓冲区
bos.write("把数据写入到缓冲区中".getBytes());
//3. 使用BufferedOutputStream对象中的方法flush,把内存缓冲区中的数据刷新到文件中
bos.flush();
//4. 释放资源
bos.close();
}
}
字节缓冲输入流:BufferedInputStream
java.io.BufferedInputStream extends InputStream
BufferedInputStream:字节缓冲输入流
继承自父类InputStream中的成员方法:
-
public void close()
:关闭此输入流并释放与此流相关联的任何系统资源。 -
public abstract int read()
: 读取一个字节,并返回 -
public int read(byte[] b)
: 读取多个字节,存储到数组中返回
构造方法:
BufferedInputStream(InputStream in)
创建一个 BufferedInputStream并保存其参数,即输入流 in ,供以后使用。BufferedInputStream(InputStream in, int size)
创建具有指定缓冲区大小的 BufferedInputStream ,并保存其参数(输入流 in )供以后使用。
参数:
InputStream in:字节输入流
int size:指定缓冲区的大小(数组的大小)
字节缓冲输入流的使用步骤:
- 创建BufferedInputStream对象,构造方法中传递FileInputStream对象
- 使用BufferedInputStream对象中的方法read,读取文件
- 释放资源
代码示例:
public class Demo02 {
public static void main(String[] args) throws IOException {
//1. 创建BufferedInputStream对象,构造方法中传递FileInputStream对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("day10\\6.txt"));
//2. 使用BufferedInputStream对象中的方法read,读取文件
//public abstract int read() : 读取一个字节,并返回
// int len = 0;
// while ((len = bis.read()) != -1){
// System.out.println(len);
// }
//public int read(byte[] b) : 读取多个字节,存储到数组中返回
byte[] bytes = new byte[1024];
int len = 0;
while ((len = bis.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, len));
}
//3. 释放资源
bis.close();
}
}
字符缓冲输出流:BufferedWriter
java.io.BufferedWriter extends Writer :字符缓冲输出流
继承自父类Writer的共性成员方法:
-
public abstract void close()
:关闭此输出流并释放与此流相关联的任何系统资源。 -
public abstract void flush()
:刷新此输出流并强制任何缓冲的输出字符被写出。 -
public void write(int c)
:写出一个字符。 -
public void write(char[] cbuf)
:将 b.length字符从指定的字符数组写出此输出流。 -
public abstract void write(char[] b, int off, int len)
:从指定的字符数组写出 len字符,从偏移量 off开始输出到此输出流。 -
public void write(String str)
:写出一个字符串。 -
public void write(String str, int off, int len)
写一个字符串的一部分。
构造方法:
BufferedWriter(Writer out)
创建使用默认大小的输出缓冲区的缓冲字符输出流。BufferedWriter(Writer out, int sz)
创建一个使用给定大小的输出缓冲区的新缓冲字符输出流。
参数:
Writer out:字符输出流,可以传递FileWriter,BufferedWriter就会给FileWriter增加一个缓冲区,提高FileWriter写数据的效率
int sz:手动指定缓冲区的大小
特有的成员方法:void newLine()
写一个行分隔符。
System.out.println();//调用的就是newLine()方法;
屏蔽了系统直接的不同,在不同的系统会获取不同的换行符
windows:\r\n
linux:/n
mac:/r
使用步骤:
- 创建BufferedWriter对象,构造方法中传递FileWriter对象
- 使用BufferedWriter对象中的方法write,把数据写到内存缓冲区中
- 释放资源(会调用flush)
代码示例:
public class Demo01 {
public static void main(String[] args) throws IOException {
//System.out.println();//调用的就是newLine()方法;
//1.创建BufferedWriter对象,构造方法中传递FileWriter对象
BufferedWriter bw = new BufferedWriter(new FileWriter("day11\\1.txt"));
//2.使用BufferedWriter对象中的方法write,把数据写到内存缓冲区中
for (int i = 0; i < 10; i++) {
bw.write("你好");
//bw.write("\r\n");
bw.newLine();
}
//3.释放资源(会调用flush)
bw.close();
}
}
字符缓冲输入流:BufferedReader
java.io.BufferedReader extends Reader:字符缓冲输入流
继承自父类Reader的共性成员方法:
-
public void close()
:关闭此流并释放与此流相关联的任何系统资源。 -
public int read()
: 一次读取一个字符,并返回;读取到文件结尾返回-1 -
public int read(char[] cbuf)
: 一个读取多个字符,存储到数组中,返回的是每次读取的有效字符个数
构造方法:
BufferedReader(Reader in)
创建使用默认大小的输入缓冲区的缓冲字符输入流。BufferedReader(Reader in, int sz)
创建使用指定大小的输入缓冲区的缓冲字符输入流。
参数:
Reader in:字符输入流
int sz:指定的缓冲区大小
特有的成员方法:String readLine()
读一行文本。
一行被认为是由换行符(’\ n’),回车符(’\ r’),回车符后紧跟换行符或到达文件结尾的任何一个终止(EOF)。
返回:包含行内容的字符串,不包括任何行终止字符;如果在未读取任何字符的情况下到达流末尾,则返回null
使用步骤:
- 创建BufferedReader对象,构造方法中传递FileReader
- 使用BufferedReader对象中的方法read/readline,读取文件
- 释放资源
代码示例:
public class Demo02 {
public static void main(String[] args) throws IOException {
//1.创建BufferedReader对象,构造方法中传递FileReader
BufferedReader br = new BufferedReader(new FileReader("day11\\1.txt"));
//2.使用BufferedReader对象中的方法read/readline,读取文件
/*
循环优化,结束条件为null
*/
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
//3.释放资源
br.close();
}
}
文件复制
模拟右键复制粘贴: Java文件复制,模拟右键复制
文件排序
文件排序案例: Java文件排序(Map集合,字符缓冲流)
转换流
作用:指定查询的编码表
原理
GBK编码表:1个中文=2个字节
UTF-8编码表:1个中文=3个字节
FileReader:字符输入流,它有个缺陷,读取GBK格式的文件会出现乱码,只能读取IDE默认编码格式的文件(UTF-8)
字符转换输出流:OutputStreamWriter
java.io.OutputStreamWriter extends Writer:字符转换输出流
作用:OutputStreamWriter是从字符流到字节流的桥接器:使用指定的charset将写入其中的字符编码为字节。
继承自父类Writer的共性成员方法:
-
public abstract void close()
:关闭此输出流并释放与此流相关联的任何系统资源。 -
public abstract void flush(
) :刷新此输出流并强制任何缓冲的输出字符被写出。 -
public void write(int c)
:写出一个字符。 -
public void write(char[] cbuf)
:将 b.length字符从指定的字符数组写出此输出流。 -
public abstract void write(char[] b, int off, int len)
:从指定的字符数组写出 len字符,从偏移量 off开始输出到此输出流。 -
public void write(String str)
:写出一个字符串。 -
public void write(String str, int off, int len)
写一个字符串的一部分。
构造方法:
OutputStreamWriter(OutputStream out)
创建使用默认字符编码的OutputStreamWriter。OutputStreamWriter(OutputStream out, String charsetName)
创建使用指定charset的OutputStreamWriter。
参数:
OutputStream out:字节输出流,把转换流转换之后的字节写入到文件中
String charsetName:指定的编码表名称,不区分大小写,GBK/gbk,UTF-8/utf-8/utf8;不写默认使用IDE编码UTF-8
使用步骤:
1. 创建OutputStreamWriter对象,构造方法中绑定字节输出流对象和指定的编码表名称
2. 使用OutputStreamWriter对象中的方法write,把数据写入到内存缓冲区中(字符->字节)
3. 使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的数据刷新到文件中(使用字节流写字节)
4. 释放资源
代码示例:
- 创建一个UTF-8编码的文件
/*
使用OutputStreamWriter写一个UTF-8编码格式的文件
*/
private static void write_utf8() throws Exception {
//1. 创建OutputStreamWriter对象,构造方法中绑定字节输出流对象和指定的编码表名称
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day11\\utf8.txt"),"UTF-8");
//2. 使用OutputStreamWriter对象中的方法write,把数据写入到内存缓冲区中(字符->字节)
osw.write("你好");
//3. 使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的数据刷新到文件中(使用字节流写字节)
osw.flush();
//4. 释放资源
osw.close();
}
- 创建一个GBK编码的文件
private static void write_GBK() throws Exception {
//1. 创建OutputStreamWriter对象,构造方法中绑定字节输出流对象和指定的编码表名称
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day11\\GBK.txt"),"GBK");
//2. 使用OutputStreamWriter对象中的方法write,把数据写入到内存缓冲区中(字符->字节)
osw.write("你好");
//3. 使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的数据刷新到文件中(使用字节流写字节)
osw.flush();
//4. 释放资源
osw.close();
}
字符转换输入流:InputStreamReader
java.io.InputStreamReader extends Reader:字符转换输入流
作用:InputStreamReader是从字节流到字符流的桥接器:它使用指定的charset读取字节并将其解码为字符。
继承自父类Reader的共性成员方法:
-
public void close()
:关闭此流并释放与此流相关联的任何系统资源。 -
public int read()
: 一次读取一个字符,并返回;读取到文件结尾返回-1 -
public int read(char[] cbuf)
: 一个读取多个字符,存储到数组中,返回的是每次读取的有效字符个数
构造方法:
InputStreamReader(InputStream in)
创建一个使用默认字符集的InputStreamReader。InputStreamReader(InputStream in, String charsetName)
创建一个使用指定charset的InputStreamReader。
参数:
InputStream in:字节输入流,读取文件中保存的字节
String charsetName:指定的编码表名称,不区分大小写,GBK/gbk,UTF-8/utf-8/utf8;不写默认使用IDE编码UTF-8
使用步骤:
- 创建InputStreamReader对象,构造方法中绑定字节输入流和指定的编码表名称
- 使用InputStreamReader对象中的方法read,读取文件
- 释放资源
注意:
构造方法中指定的编码表名称,必须与文件的编码相同,否则会发生乱码
代码示例:
- 读取UTF-8编码的文件
private static void read_utf8() throws Exception {
//1.创建InputStreamReader对象,构造方法中绑定字节输入流和指定的编码表名称
InputStreamReader isr = new InputStreamReader(new FileInputStream("day11\\utf8.txt"),"UTF-8");
//2.使用InputStreamReader对象中的方法read,读取文件
int len = 0;
while((len = isr.read())!= -1){
System.out.println((char)len);
}
//3.释放资源
isr.close();
}
- 读取GBK编码的文件
private static void read_GBK() throws Exception {
//1.创建InputStreamReader对象,构造方法中绑定字节输入流和指定的编码表名称
InputStreamReader isr = new InputStreamReader(new FileInputStream("day11\\GBK.txt"),"GBK");
//2.使用InputStreamReader对象中的方法read,读取文件
int len = 0;
while((len = isr.read())!= -1){
System.out.println((char)len);
}
//3.释放资源
isr.close();
}
转换文件编码
需求:将GBK编码的文本文件,转化为UTF-8编码的文本文件
分析:
- 指定GBK编码的转换流,读取文本文件
- 使用UTF-8编码的转化流,写出文本文件
什么时候使用便捷的字符流FileReader和FileWriter:操作文件的编码固定,就是IDE默认编码UTF-8
优势:使用起来简单,不用传递编码表,不用创建字节流
什么时候使用转换字符流InputStreamReader和 OutputStreamWriter:操作文件的编码不是IDE默认编码UTF-8
代码示例:
public class Demo03test {
public static void main(String[] args) throws Exception {
//创建字符转换输入流InputStreamReader对象
InputStreamReader isr = new InputStreamReader(new FileInputStream("day11\\GBK编码文件"),"GBK");
//创建字符转换输出流OutputStreamWriter对象
//OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day11\\UTF-8编码文件"),"UTF-8");
FileWriter fw = new FileWriter("day11\\UTF-8编码文件");
//读取文件
char[] chars = new char[1024];
int len = 0;
while ((len = isr.read(chars))!=-1){
//写
fw.write(chars,0,len);
}
//释放资源
fw.close();
isr.close();
}
}