一.IO流概述
什么是IO流,其作用为?
- I ------ Input --> 输入 --> 读取
- O — Output --> 输出 --> 写出
常见应用:
- 文件复制
- 文件上传
- 文件下载
IO流的分类汇总:
- 字节流 (支持图片等格式的文件,直接用记事本打开文件是看不懂的乱码
- 字节缓冲区流 (字符缓冲输入流 b、c方式 可以读取中文,不会出现乱码)
- 转换流 (字符流) = 字节流 + 编码表
- 字符流 (字符流数据通过Windows自带的记事本软件打开是可以读懂里面内容的)
- 字符缓冲区流
- 字节流 (支持图片等格式的文件,直接用记事本打开文件是看不懂的乱码)
a1 InputStream 字节流输入超类
a1.1 FileInputStream 不建议读取中文,中文一般2-4字节,此方式会从中间截断,导致乱码
//指定输入流
//FileInputStream fis = new FileInputStream(new File("fis.txt"));//效果同下行代码
FileInputStream fis = new FileInputStream("fis.txt");
//a.一次读取一个字符
int by;
//如果fis.read不等于-1说明还有数据,则继续读文件
while ((by = fis.read()) != -1) {
System.out.print((char) by);//打印结果
}
//b.一次读取一个字符数组
byte[] bys = new byte[1024];//每次读取最大bys长度个字节存入数组,长度建议1024或1024的整数倍
int len;//代表有效个数
//将数据读取到数组中, 并用len记录读取到的有效字节个数
//fis.read(bys)=>读取一次bys长度内容写入bys(每次覆盖之前内容),如果剩余文件内容不足以写满bys,(长度1024,剩余1000字节)则bys中最后字节(24字节)保持上一次写入的内容 => 所以每次要截取new String(bys,0,len),避免读到上一次剩余的内容
while ((len = fis.read(bys)) != -1) {
System.out.print(new String(bys, 0, len));//打印结果
}
//释放资源
fis.close();
b1 字节缓冲区流 BufferedInputStream 字符缓冲输入流 b、c方式 可以读取中文,不会出现乱码
//字节流一次读写一个数组的速度比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果,java本身在设计的时候,也考虑到了这样的设计思想,所以提供了字节缓冲区流
//Q:为什么字节缓冲流的构造方法需要传入一个In/OutputStream
//A:字节缓冲区流仅仅提供缓冲区,而真正的底层的读写数据还得需要基本的流对象进行操作。
//指定输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("name.txt"));
//a.一次读取一个字符(不能读取中文,中文一般2-4字节,一个一个字节读会乱码)
int by;
while ((by = bis.read()) != -1) {
System.out.print((char) by);
}
//b.一次读取一个字符数组
byte[] bys = new byte[1024];
int len;
while ((len = bis.read(bys)) != -1) {
System.out.print(new String(bys, 0, len));
}
//释放资源
bis.close();
a2 OutPutStream 字节流输出超类
a2.1 FileOutputStream 不建议读取中文,中文一般2-4字节,此方式会从中间截断,导致乱码
//指定输出流
//FileOutputStream fos = new FileOutputStream(new File("fos.txt"));//效果同下行代码
//FileOutputStream fos = new FileOutputStream("fos.txt" , false);//false表示不追加文件->每次写入覆盖之前的内容
FileOutputStream fos = new FileOutputStream("fos.txt");
FileInputStream fis = new FileInputStream("fis.txt");
//a.一次写入一个字符(不能读取中文,中文一般2-4字节,一个一个字节读会乱码)
int by;
while ((by = fis.read()) != -1) {
System.out.print((char) by);//打印结果
}
//b.一次写入一个字符数组
byte[] bytes = new byte[1024];
int len;
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
//释放资源
fos.close();
fis.close();
b2 字节缓冲区流 BufferedOutputStream 字节缓冲输出流 可以读取中文,不会出现乱码
//字节流一次读写一个数组的速度比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果,java本身在设计的时候,也考虑到了这样的设计思想,所以提供了字节缓冲区流
//Q:为什么字节缓冲流的构造方法需要传入一个In/OutputStream
//A:字节缓冲区流仅仅提供缓冲区,而真正的底层的读写数据还得需要基本的流对象进行操作。
//指定输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bos.txt"));
//a.一次读取一个字符
int by;
while ((by = bis.read()) != -1) {
bos.write(by);//写入字符串
bos.flush();//刷新该流的缓冲,写入文件
}
//b.一次读取一个字符数组
byte[] bytes = new byte[1024];
int len;
while ((len = bis.read(bytes)) != -1) {
System.out.println(new String(bytes,0,len));
bos.write(bytes,0,len);//写入字符串
bos.flush();//刷新该流的缓冲,写入文件
}
//释放资源
bis.close();
bos.close();
- c 转换流 (字符流) = 字节流 + 编码表
//指定编码为UTF-8的字符输出流
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("source.txt"),"UTF-8");
//指定编码为UTF-8的字符输入流
InputStreamReader isr = new InputStreamReader(new FileInputStream("target.txt"),"UTF-8");
/*
常见的编码表:
ASCII : 美国标准信息交换码, 用一个字节的7位表示数据
ISO-8859-1 : 欧洲码表, 用一个字节的8位表示数据, 兼容ASCII
GB2312 : 中文码表的升级版, 融合了更多的中文文字符号, 兼容ASCII
UTF-8 : 是一种可变长度的字符编码, 用1-3个字节表示数据, 又称为万国码, 兼容ASCII用在网页上可以
统一页面中的中文简体繁体和其他语言的显示.
*/
-
d字符流 (字符流数据通过Windows自带的记事本软件打开是可以读懂里面内容的)
d1 Reader 字符流输入超类
d1.1 InputStreamReader 用 默认/指定 编码读数据
//指定输入流 目标文件和字符集 ,如果不指定字符集则按照默认编码表 (java7=GBK,java8=UTF-8)
InputStreamReader isr = new InputStreamReader(new FileInputStream(""),"GBK");
d1.1.1 FileReader ↓作为BufferedReader构造器的参数使用↓
//转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化我们的书写,转换流InputStreamReader提供了对应的子类InputStreamReader
/*
(子类)FileWriter:用来写入字符文件的便捷类
(父类)OutputStreamWriter: FileWriter + 默认编码表(java7=GBK,java8=UTF-8)
(子类)FileReader:用来读取字符文件的便捷类
(父类)InputStreamReader: FileReader + 默认编码表(java7=GBK,java8=UTF-8)
*/
//封装数据源
FileReader fr = new FileReader("source.txt");
//封装目的地
FileWriter fw = new FileWriter("target.txt");
e1 字符缓冲区流 BufferedReader 最常用
//指定输入流
BufferedReader br = new BufferedReader(new FileReader("source.txt"));
//指定输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("target.txt"));
//a.一次读取一个字符
int ch;
while ((ch = br.read()) != -1) {
//对应Unicode编码10进制的值 查询工具 =>
//http://www.mytju.com/classcode/tools/encode_gb2312.asp
System.out.println(ch);
}
//b.一次读取多个字符【注意 换行符也算字符】
char[] bytes = new char[1024];//一次取出1024个字符
int len;//代表有效个数
while((len = br.read(bytes)) != -1)
{
System.out.print(new String(chars, 0, len));//注意是print不是println
}
//c.读取一整行字符串【注意 不包括换行符,需要手动newLine()换行】
//String line = br.readLine();
String line;//代表一整行字符串
//按行读取整篇文章的内容
while((line = br.readLine()) != null)
{
System.out.println(line);
}
//释放资源
br.close();
bw.close();
d2 Writer 字符流输出超类
d2.1 PrintWriter
d2.2 OutputStreamWriter 用 默认/指定 编码写数据
//指定输出流 目标文件和字符集,如果不指定字符集则按照默认编码表 (java7=GBK,java8=UTF-8)
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("target.txt"),"GBK");
d2.2.1 FileWriter ↓作为BufferedWriter构造器的参数使用↓
//转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化我们的书写,转换流OutputStreamWriter提供了对应的子类FileWriter
/*
(子类)FileWriter:用来写入字符文件的便捷类
(父类)OutputStreamWriter: FileWriter + 默认编码表(java7=GBK,java8=UTF-8)
(子类)FileReader:用来读取字符文件的便捷类
(父类)InputStreamReader: FileReader + 默认编码表(java7=GBK,java8=UTF-8)
*/
//封装数据源
FileReader fr = new FileReader("source.txt");
//封装目的地
FileWriter fw = new FileWriter("target.txt");
e2 字符缓冲区流 BufferedWriter 最常用
//指定输入流
BufferedReader br = new BufferedReader(new FileReader("br.txt"));
//指定输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
//a.一次读取一个字符
int ch;
while ((ch = br.read()) != -1) {
bw.write(ch);//写入字符串
bw.flush();//刷新该流的缓冲,写入文件
}
//b.一次读取多个字符【注意 换行符也算字符】
char[] bytes = new char[1024];//一次取出1024个字符
int len;//代表有效个数
while((len = br.read(bytes)) != -1)
{
bw.write(new String(bytes, 0 , len));//写入字符串
bw.newLine();
bw.flush();//刷新该流的缓冲,写入文件
}
//c.读取一整行字符串【注意 不包括换行符,需要手动newLine()换行】
//String line = br.readLine();
String line;//代表一整行字符串
//按行读取整篇文章的内容
while((line = br.readLine()) != null)
{
bw.write(line);//写入字符串
bw.newLine();
bw.flush();//刷新该流的缓冲,写入文件
}
//释放资源
br.close();
bw.close();
二. 字节流
a.字节流 (支持图片等格式的文件,直接用记事本打开文件是看不懂的乱码)
InputStream 字节流输入超类
FileInputStream 不建议读取中文,中文一般2-4字节,此方式会从中间截断,导致乱码
b. 字节缓冲区流 BufferedInputStream 字符缓冲输入流 b、c方式 可以读取中文,不会出现乱码
OutPutStream 字节流输出超类
FileOutputStream 不建议读取中文,中文一般2-4字节,此方式会从中间截断,导致乱码
b 字节缓冲区流 BufferedOutputStream 字节缓冲输出流 可以读取中文,不会出现乱码
2.1 FOS与FIS
简写说明:
- FIS = FileInPutStream
- FOS = FileOutPutStream
字节流写数据:
- OutputStream:此抽象类是表示输出字节流的所有类的超类
- FileOutputStream:文件输出流是用于将数据写入 File
字符流读数据:
- OutputStream:此抽象类是表示输出字节流的所有类的超类
- FileOutputStream:文件输出流是用于将数据写入 File
构造方法:
//创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(String name)
字节流写数据的步骤:
- 创建字节输出流对象
- 调用写数据的方法 write(int);
- 释放资源 close()
代码:
package Java_study;
import java.io.FileOutputStream;
import java.io.IOException;
/**
*
* @author 只是甲
* @date 2021-07-19
* @remark 字节流FileOutputStream写出数据
*
*/
public class io1 {
public static void main(String[] args) throws IOException {
//创建直接输出流对象 throws FileNotFoundException
FileOutputStream fos = new FileOutputStream("a.txt");
//throws IOException (包含FileNotFoundException)
System.out.println("fos.write");
fos.write(65);//A
fos.write(66);//B
System.out.println("写入结束");
//关闭IO流,回收系统资源
fos.close();
}
}
2.2 FOS写数据的三种方式
方法摘要:
//a.写出数据的三个方法
//一次写一个字节
public void write(int b)
//一次写一个字节数组
public void write(byte[] b)
//一次写一个字节数组的一部分
public void write(byte[] b,int off,int len)
//b.String类中的方法
//将字符串转换为字节数组
byte[] getBytes()
代码:
package Java_study;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
*
* @author 只是甲
* @date 2021-07-19
* @remark 字节流FileOutputStream写数据的三种方式
* A.构造方法的三种方式:
* 1. FileOutputStream(String name)
* 2. FileOutPutStream(File file)
* 3. FileOutPutStream(new File(xxx))
* 4. FileOutputStream(xxx,true) //true=追加数据,默认为false,清空后重新写入数据
*
* B.写数据的三种方式: throws IOException
* 1. FileOutputStream.write(int b):一次写一个字节
* 2. FileOutputStream.write(byte[] b):一次写一个字节数组
* 3. FileOutputStream.write(byte[] b,inf off,int len):一次写一个字节数组的一部分
*
* 字节流写数据的步骤:
* a: 创建字节输出流对象 new FileOutPutStream(String name)
* b: 调用写数据的方法
* c: 释放资源 fos.close()
*
*/
public class io2 {
public static void main(String[] args) throws IOException{
//A1. FileOutputStream构造方式1 FileOutputStream(String name)
FileOutputStream fos1 = new FileOutputStream("b.txt");
//A2. FileOutputStream构造方式2 FileOutPutStream(File file)
File f2 = new File("c.txt");
FileOutputStream fos2 = new FileOutputStream(f2);
//A3. FileOutPutStream构造方式3 FileOutPutStream(new File(xxx))
FileOutputStream fos3 = new FileOutputStream(new File("d.txt"));
//B1. 写入数据方式1 FileOutputStream.write(int b):一次写一个字节
//throws IOException
fos1.write(65);
//B2. 写入数据方式2 FileOutputStream.write(byte[] b):一次写一个字节数组
byte[] bys = {65, 66, 67, 68, 69};
fos2.write(bys);
//B3. 写入数据方式3 FileOutputStream.write(byte[] b,inf off,int len):一次写一个字节数组的一部分
fos3.write("ABCDE".getBytes(), 0, 3);
File path = new File("");
System.out.println("文件路径:" + path.getAbsolutePath());
//释放资源
fos1.close();
fos2.close();
fos3.close();
}
}
2.3 FOS如何实现换行和追加写数据
FIS = FileInPutStream
不同的操作系统,针对换行的符号识别是不一样的:
- windows:\r\n
- linux:\n
- mac:\r
如何实现数据的追加写入?
- 用构造方法带第二个参数是true的情况即可
代码:
package Java_study;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
*
* @author 只是甲
* @date 2021-07-19
* @remark 字节流FileOutputStream写数据换行、追加
*
*/
public class io3 {
public static void main(String[] args) throws IOException{
//先清空文件
FileOutputStream clear = new FileOutputStream("b.txt");
clear.write("".getBytes());
//如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处(默认为false)
FileOutputStream fos = new FileOutputStream("b.txt", true);
//玄幻写入三次hello和换行
for (int i = 0; i < 3; i++) {
fos.write("hello".getBytes());
fos.write("\r\n".getBytes());
}
System.out.println("文件路径为:" + new File("").getAbsolutePath());
//释放资源
fos.close();
}
}
2.4 FOS写数据加入异常处理
FIS = FileInPutStream
try…catch.finally
//格式
try{
可能发生问题的代码
}catch(){
处理异常代码
}finally{
一定会被执行的代码. // 通常用于释放资源, 做善后的动作
}
代码:
package Java_study;
import java.io.FileOutputStream;
import java.io.IOException;
/**
*
* @author 只是甲
* @date 2021-07-19
* @remark 字节流FileOutputStream写数据加入异常处理
*
*/
public class io4 {
public static void main(String[] args) {
//fos放在外面是为了在finally中可以关闭
FileOutputStream fos = null;
try {
fos = new FileOutputStream("d.txt");
fos.write("hello".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
//释放资源
try {
fos.close();
} catch (IOException e) {
System.out.println("fos关闭失败");
}
}
}
}
}
2.5 FIS读数据方式1一次读取一个字节
FIS = FileInPutStream
字节流读数据的步骤:
- A : 创建字节输入流对象
- B : 调用读数据的方法
- C : 释放资源
代码:
package Java_study;
import java.io.FileInputStream;
import java.io.IOException;
/**
*
* @author 只是甲
* @remark 字节流FileInputStream读数据方式1
*
*/
public class io5 {
public static void main(String[] args) throws IOException {
System.out.println("读取数据方式1: 一次读取一个字节");
//创建字节输入流对象
FileInputStream fis1 = new FileInputStream("b.txt");//刚才在b.txt写入了3行hello
for (int i = 0; i < 20; i++) {
System.out.println(fis1.read());
}
System.out.println("改进为循环方式打印");
FileInputStream fis2 = new FileInputStream("b.txt");//刚才在b.txt写入了3行helloWorld
int by;
//如果fis.read不等于-1说明还有数据,则继续读文件
while ((by = fis2.read()) != -1) {
System.out.println((char) by);
}
}
}
测试记录:
读取数据方式1: 一次读取一个字节
104
101
108
108
111
13
10
104
101
108
108
111
13
10
104
101
108
108
111
13
改进为循环方式打印
h
e
l
l
o
h
e
l
l
o
h
e
l
l
o
2.6 FIS读数据方式2一次读取一个字节数组
方法摘要:
/*从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中
返回值是读入缓冲区的字节总数,也就是实际的读取个数
如果因为已经到达文件末尾而没有更多的数据,则返回 -1。*/
public int read(byte[] b):
代码:
package Java_study;
import java.io.FileInputStream;
import java.io.IOException;
/**
*
* @author 只是甲
* @remark FileInputStream读数据方式2
*
*/
public class io6 {
public static void main(String[] args) throws IOException{
System.out.println("----读取数据方式2: 一次读取一个直接数组-----");
FileInputStream fis1 = new FileInputStream("b.txt");//刚才在b.txt写入了3行hello
//标准代码字符缓冲区bys1长度应为1024或1024的整数倍,这里先用8演示读取的原理
byte[] bys1 = new byte[8];
//第一次读取
int len1 = fis1.read(bys1);
System.out.println(len1);//8
System.out.println("第一次读取: " + new String(bys1));
//第二次读取
len1 = fis1.read(bys1);
System.out.println(len1);//8
/*
第二次读取: ello
he
*/
System.out.println("第二次读取: " + new String(bys1));
// 第三次读取
len1 = fis1.read(bys1);
System.out.println(len1);//5 => 只读取了5个字符,就返回了5
/*
第三次读取: llo
he
*/
/* 解析:
文件内容为
hello\r\n
hello\r\n
hello\r\n
第一次读取8个字节为 [h] [e] [l] [l] [o] [\r][\n] [h]
第二次读取8个字节为 [e] [l] [l] [o] [\r][\n] [h] [e]
第三次读取8个字节为 [l] [l] [o] [\r][\n]
但数组写入方式是每次覆盖前一次的,所以第二次写入的还保留着
bys[5] = \r
bys[6] = h
bys[7] = e
所以第三次数组内容为 [l] [l] [o] [\r][\n][\n] [h] [e]
所以才会打印出以上内容
*/
System.out.println("第三次读取: " + new String(bys1));
//第四次读取
len1 = fis1.read(bys1);
System.out.println(len1);//-1 => 表示没有数据了
System.out.println("-----改进为循环读取文件-----");
//创建字节流输入对象
FileInputStream fis2 = new FileInputStream("b.txt");
byte[] bys2 = new byte[1024];//1024或者1024的整数倍
int len2;
//将数据读取到数组中, 并用len记录读取到的有效字节个数
while ((len2 = fis2.read(bys2)) != -1 ) {
//只读取到len的长度,否则会出现
System.out.print(new String(bys2, 0, len2));
}
System.out.println("\r\n读取结束");
fis2.close();
}
}
测试记录:
----读取数据方式2: 一次读取一个直接数组-----
8
第一次读取: hello
h
8
第二次读取: ello
he
5
第三次读取: llo
he
-1
-----改进为循环读取文件-----
hello
hello
hello
读取结束
2.7 字节流练习之复制文本文件
需求:
- 拷贝文本文件
分析:
- 第一步: 创建输入输出流对象关联数据源和数据目的
- 第二步: 定义字节数组,为了提高效率
- 第三步: 将数据通过while循环不断读取到字节数组中
- 第四步: 将数据从字节数组中取出并写出
- 第五步: 释放资源
待拷贝的文本文件(d:\窗里窗外.txt):
《窗里窗外》是林青霞近5年所写的46篇散文的结集,虽是旧作,但该书记录她19岁以《窗外》成名后多方面的人生经历,字字真实深刻。《窗里窗外》共分为六个章节:“戏”里说的是她的出道故事、拍戏的甘苦、对于作品的内心话;“亲”谈她的家人亲情;“友”则书写她与挚友的交往,细谈她与三毛、黄霑、张国荣、龙应台、琼瑶、徐克等人的往来互动;“趣”是她的生活记趣,有旅行见闻,也有她与影迷的邂逅;“缘”则书写她一生难忘的相遇,像是和记者的友谊,和季羡林的会面之缘;“悟”里记录了她对人生的体悟和感动,以及她向圣严法师求道的故事。此外,书中还完整收录了林青霞一些未公开的照片。
第1节:人生小语(1)…
代码:
package Java_study;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
*
* @author 只是甲
* @remark 直接流复习之复制文本文件
*
*/
public class io7 {
public static void main(String[] args) throws IOException{
//封装数据源
FileInputStream fis = new FileInputStream("d:" + File.separator + "窗里窗外.txt");
//封装目的地(目标文件,追加true清空重写false)
FileOutputStream fos = new FileOutputStream("d:" + File.separator + "杜兰特.txt", false);
//a.一次写入一个字符
int by;
while ((by = fis.read()) != -1 ) {
fos.write(by);
}
//b.一次写入一个字符数组
byte[] bys = new byte[1024];
int len;
while ((len = fis.read(bys)) != -1 ) {
fos.write(bys, 0, len);
}
//释放资源
fos.close();
fis.close();
}
}
2.8 字节流练习之复制图片
思路:
- 同理2.7案例
代码:
package Java_study;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
*
* @author 只是甲
* @date 2021-07-20
* @remark 直接流复习之复制文本文件
*
*/
public class io8 {
public static void main(String[] args) throws IOException{
//封装数据源
FileInputStream fis1 = new FileInputStream("d:" + File.separator + "字节流.bmp");
FileInputStream fis2 = new FileInputStream("d:" + File.separator + "字节流.bmp");
//封装目的地
FileOutputStream fos1 = new FileOutputStream("d:" + File.separator + "copy1.bmp");
FileOutputStream fos2 = new FileOutputStream("d:" + File.separator + "copy2.bmp");
//读取数据
int by;
//方式1: 一次读取一个直接
//如果fis.read不等于-1说明还有数据,则继续读文件
while ((by = fis1.read()) != -1 ) {
fos1.write(by);
}
//方式2: 一次读取一个字节数组
byte[] bys = new byte[1024];
int len;
while ((len = fis2.read(bys)) != -1) {
fos2.write(bys, 0, len);
}
//释放资源
fis1.close();
fis2.close();
fos1.close();
fos2.close();
}
}
三. 字节缓冲区流
a.字节流 (支持图片等格式的文件,直接用记事本打开文件是看不懂的乱码)
- InputStream 字节流输入超类
- FileInputStream 不建议读取中文,中文一般2-4字节,此方式会从中间截断,导致乱码
b. 字节缓冲区流 BufferedInputStream 字符缓冲输入流 b、c方式 可以读取中文,不会出现乱码 - OutPutStream 字节流输出超类
FileOutputStream 不建议读取中文,中文一般2-4字节,此方式会从中间截断,导致乱码
b 字节缓冲区流 BufferedOutputStream 字节缓冲输出流 可以读取中文,不会出现乱码
3.1 概述
作用:
- 字节流一次读写一个数组的速度比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果
- java本身在设计的时候,也考虑到了这样的设计思想,所以提供了字节缓冲区流
字节缓冲流:
- BufferedOutputStream : 字节缓冲输出流
- BufferedInputStream : 字节缓冲输入流
为什么字节缓冲流的构造方法需要传入一个OutputStream:
- 字节缓冲区流仅仅提供缓冲区,而真正的底层的读写数据还得需要基本的流对象进行操作
代码:
package Java_study;
import java.io.*;
/**
*
* @author 只是甲
* @date 2021-07-20
* @remark 字节缓冲流
*
*/
public class io9 {
public static void main(String[] args) throws IOException{
//指定字符缓冲输出流
// FileOutputStream fos = new FileOutputStream("a.txt");
// BufferedOutputStream bos = new BufferedOutputStream(fos);
// 上面的两句等价于下面的这一句
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("a.txt"));
byte[] bytes = "hello".getBytes();
bos.write(bytes);
bos.close();
//指定字符缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
//方式1: 一次读取一个字节
int by;
while ((by = bis.read()) != -1) {
System.out.println((char) (by));
}
//方式2: 一次读取一个直接数组
byte[] bys = new byte[1024];
int len;
while ((len = bis.read(bys)) != -1) {
System.out.println(new String(bys, 0, len));
}
//释放资源
bos.close();
bis.close();
}
}
3.2 四种方式复制图片效率测试
方法摘要:
//返回以毫秒为单位的当前时间。
public static long currentTimeMillis()
代码:
package Java_study;
import java.io.*;
/**
* @author GroupiesM
* @date 2021/04/27
* @introduction 字节流&字节缓冲区流四种方式复制AVI并测试效率
*
* 源文件: d:\\复制视频.avi
* 大小: 34904KB
*
* method1: 基本字节流,一次读取一个字节 => method1.avi => 198001毫秒
* method2: 基本字节流,一次读写一个字节数组 => method2.avi => 278毫秒
* method3: 缓冲字节流,一次读取一个字节 => method3.avi => 384毫秒
* method4: 缓冲字节流,一次读写一个字节数组 => method4.avi => 190毫秒
*
* 结论: method4 > method2 > method3 > method1
*/
public class io10 {
public static void main(String[] args) throws IOException {
//记录method1时间
long start1 = System.currentTimeMillis();
method1();//method1共耗时198001毫秒
long end1 = System.currentTimeMillis();
System.out.println("method1共耗时" + (end1 - start1) + "毫秒");
//记录method2时间
long start2 = System.currentTimeMillis();
method2();//method2共耗时278毫秒
long end2 = System.currentTimeMillis();
System.out.println("method2共耗时" + (end2 - start2) + "毫秒");
//记录method3时间
long start3 = System.currentTimeMillis();
method3();//method3共耗时384毫秒
long end3 = System.currentTimeMillis();
System.out.println("method3共耗时" + (end3 - start3) + "毫秒");
//记录method4时间
long start4 = System.currentTimeMillis();
method4();//method4共耗时190毫秒
long end4 = System.currentTimeMillis();
System.out.println("method4共耗时" + (end4 - start4) + "毫秒");
}
//method1: 基本字节流,一次读取一个字节 => method1.avi
private static void method1() throws IOException {
//封装数据源
FileInputStream fis = new FileInputStream("d:\\复制视频.avi");
//封装目的地
FileOutputStream fos = new FileOutputStream("d:\\method1.avi");
int by;
while ((by = fis.read()) != -1) {
fos.write(by);
}
//释放资源
fis.close();
fos.close();
}
//method2: 基本字节流,一次读写一个字节数组 => method2.avi
private static void method2() throws IOException {
//封装数据源
FileInputStream fis = new FileInputStream("d:\\复制视频.avi");
//封装目的地
FileOutputStream fos = new FileOutputStream("d:\\method2.avi");
byte[] bys = new byte[1024];
int len;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
//释放资源
fis.close();
fos.close();
}
//method3: 缓冲字节流,一次读取一个字节 => method3.avi
private static void method3() throws IOException {
//封装数据源
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("d:\\复制视频.avi"));
//封装目的地
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d:\\method3.avi"));
int by;
while ((by = bis.read()) != -1) {
bos.write(by);
}
//释放资源
bis.close();
bos.close();
}
//method4: 缓冲字节流,一次读写一个字节数组 => method4.avi
private static void method4() throws IOException {
//封装数据源
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("d:\\复制视频.avi"));
//封装目的地
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d:\\method4.avi"));
byte[] bys = new byte[1024];
int len;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
//释放资源
bis.close();
bos.close();
}
}
四. 转换流
c. 转换流 (字符流) = 字节流 + 编码表
转换流出现的原因:
- 由于字节流操作中文不是特别方便,所以,java就提供了转换流
- 转换流 = 字节流 + 编码表
字节流读数据可能出现问题:
- 字节流一次读取一个字节的方式读取带有汉字的文件是有问题的,因为你读取到一个字节后就转为字符在控制台输出了,而汉字是由2个字节组成的,所以这里会出问题。
- 文件复制的时候,字节流读取一个字节,写入一个字节,这个没有出现问题,是因为最终底层会根据字节做拼接,得到汉字。
- 汉字存储的规则
左边的字节数据肯定是负数,右边的字节数据可能是负数,也可能是正数,大部分情况下是负数。
代码:
package Java_study;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
/**
* @author 只是甲
* @date 2021-07-20
* @remark 转换流出现的原因
*
*/
public class io11 {
public static void main(String[] args) throws IOException{
//基本字节流一次读取一个字节
FileInputStream fis = new FileInputStream("a.txt");
int by;
while ((by = fis.read()) != -1 ) {
System.out.print((char) by);
}
//释放资源,刷新缓冲区
fis.close();
System.out.println("");
String s = "你";
byte[] bys = s.getBytes("GBK");
/*常见的编码表测试 中文"你"转换为字节数组
UTF-8 => [-28, -67, -96] => JDK8中不指定编码则默认为 UTF-8
GBK/GB2312 => [-60, -29] => JDK7中不指定编码则默认为 GBK/GB2312
ISO-8859-1 => [63]
ASCII => [63]
UNICODE/UTF-16 => [-2, -1, 79, 96] => UNICODE 默认使用的是UTF-16的实现方式
*/
System.out.println(Arrays.toString(bys));
}
}
测试记录:
hi
????
[-60, -29]
4.1 什么是编码表
编码表
- 由字符及其对应的数据组成的一张表
ASCII
‘a’ 97
‘A’ 65
‘0’ 48
常见的编码表:
- ASCII : 美国标准信息交换码, 用一个字节的7位表示数据;(ASCII 0-126)
- ISO-8859-1 : 欧洲码表, 用一个字节的8位表示数据, 兼容ASCII;
- GB2312/GBK : 中文码表的升级版, 融合了更多的中文文字符号, 兼容ASCII;
- UTF-8 : 使用一到四个字节来编码一个码点。, 兼容ASCII;用在网页上可以统一页面中的中文简体繁体和其他语言的显示;
- UNICODE : 为世界上所有字符都分配了一个唯一的数字编号,又称万国码;有多种实现方案(UTF-32 、UTF-16 、UTF-8)。
乱码问题:
-
针对同一个数据, 采用的编码和解码不一致导致
image.png
代码:
package Java_study;
/**
*
* @author 只是甲
* @date 2021-07-21
* @remark 遍历编码表_int转char
*
*/
public class io12 {
public static void main(String[] args) {
int count = 0;
for (int i = 8; i < 127; i++) {
//每打印5个就换行一次
if (count == 5) {
System.out.println("");
count = 0;
}
//13换行一次,否则CR归位键会回到行最左侧位置,导致控制台打印的10-12被吞掉
if (i == 13) {
System.out.println("");
}
char ch = (char) i;
System.out.print("[" + ch + " = " + i + "]\t");
count++;
}
}
}
测试记录:
[ = 8] [ = 9] [
= 10] [� = 11] [ = 12]
[
= 13] [� = 14] [� = 15] [� = 16] [� = 17]
[� = 18] [� = 19] [� = 20] [� = 21] [� = 22]
[� = 23] [� = 24] [� = 25] [� = 26] [� = 27]
[� = 28] [� = 29] [� = 30] [� = 31] [ = 32]
[! = 33] [" = 34] [# = 35] [$ = 36] [% = 37]
[& = 38] [' = 39] [( = 40] [) = 41] [* = 42]
[+ = 43] [, = 44] [- = 45] [. = 46] [/ = 47]
[0 = 48] [1 = 49] [2 = 50] [3 = 51] [4 = 52]
[5 = 53] [6 = 54] [7 = 55] [8 = 56] [9 = 57]
[: = 58] [; = 59] [< = 60] [= = 61] [> = 62]
[? = 63] [@ = 64] [A = 65] [B = 66] [C = 67]
[D = 68] [E = 69] [F = 70] [G = 71] [H = 72]
[I = 73] [J = 74] [K = 75] [L = 76] [M = 77]
[N = 78] [O = 79] [P = 80] [Q = 81] [R = 82]
[S = 83] [T = 84] [U = 85] [V = 86] [W = 87]
[X = 88] [Y = 89] [Z = 90] [[ = 91] [\ = 92]
[] = 93] [^ = 94] [_ = 95] [` = 96] [a = 97]
[b = 98] [c = 99] [d = 100] [e = 101] [f = 102]
[g = 103] [h = 104] [i = 105] [j = 106] [k = 107]
[l = 108] [m = 109] [n = 110] [o = 111] [p = 112]
[q = 113] [r = 114] [s = 115] [t = 116] [u = 117]
[v = 118] [w = 119] [x = 120] [y = 121] [z = 122]
[{ = 123] [| = 124] [} = 125] [~ = 126]
4.2 String类的编解码
方法摘要:
编码 : 把看得懂的变成看不懂的
//使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException
解码 : 把看不懂的变成看得懂的
//通过使用指定的 charset解码指定的 byte 数组,构造一个新的 String。
public String(byte[] bytes, String charsetName)
重点强调: 编码和解码的方式需要一致
常见的编码表测试 中文"你"转换为字节数组
UTF-8 => [-28, -67, -96] => JDK8中不指定编码则默认为 UTF-8
GBK/GB2312 => [-60, -29] => JDK7中不指定编码则默认为 GBK/GB2312
ISO-8859-1 => [63]
ASCII => [63]
UNICODE/UTF-16 => [-2, -1, 79, 96] => UNICODE 默认使用的是UTF-16的实现方式
代码:
package Java_study;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
/**
*
* @author 只是甲
* @date 2021-07-21
* @remark String 类的编解码
*
*/
public class io13 {
public static void main(String[] args) throws UnsupportedEncodingException {
//定义一个字符串
String s = "你好";
//a.编码 getBytes => throws UnsupportedEncodingException 不支持的编码异常
byte[] encodeGBK = s.getBytes();
System.out.println(Arrays.toString(encodeGBK));//[-60, -29, -70, -61]
byte[] encodeUTF = s.getBytes("UTF-8");
System.out.println(Arrays.toString(encodeUTF));//[-28, -67, -96, -27, -91, -67]
//b.解码
byte[] bytesGBK = {-60, -29, -70, -61};
String decodeGBK = new String(bytesGBK);
//Java8默认编解码字符集为UTF8 用UTF8解码 GBK编码的字节码文件就会出现乱码
System.out.println(decodeGBK);
String decodeGBKAgain = new String(bytesGBK, "GBK");
//指定用GBK解码
System.out.println(decodeGBKAgain);//你好
byte[] bytesUTF = {-28, -67, -96, -27, -91, -67};
//不指定解码字符集,Java8环境默认使用UTF8字符集进行编解码,刚好和字节数组匹配
String decodeUTF = new String(bytesUTF);
System.out.println(decodeUTF);//你好
}
}
测试记录:
[-60, -29, -70, -61]
[-28, -67, -96, -27, -91, -67]
你好
你好
浣犲ソ
4.3 字符流Stream的编解码(写入文件)
OutputStreamWriter 字符输出流
//根据【默认编码】把字节流的数据转换为字符流
public OutputStreamWriter(OutputStream out)
//根据【指定编码】把字节流数据转换为字符流
public OutputStreamWriter(OutputStream out,String charsetName)
InputStreamReader 字符输入流
//用【默认编码】读数据
public InputStreamReader(InputStream in)
//用【指定编码】读数据
public InputStreamReader(InputStream in,String charsetName)
IDEA设置文件编码
image.png
image.png
代码:
package Java_study;
import java.io.*;
/**
*
* @author 只是甲
* @date 2021-07-21
* @remark String 类的编解码
*
*/
public class io14 {
public static void main(String[] args) throws IOException{
//指定输出流 目标文件和字符集
OutputStreamWriter oswGBK = new OutputStreamWriter(new FileOutputStream("osw.txt"), "GBK");
//指定输入流 目标文件和字符集
InputStreamReader isrGBK = new InputStreamReader(new FileInputStream("osw.txt"), "GBK");
InputStreamReader isrUTF = new InputStreamReader(new FileInputStream("osw.txt"), "utf-8");
//调用写数据的方法
oswGBK.write("你好");
oswGBK.flush();//刷新缓冲流(执行一次写入)
//用GBK解码GBK文本
int byGBK;
while ((byGBK = isrGBK.read()) != -1) {
System.out.print((char) byGBK);//你好
}
System.out.println("");
//用UTF-解码GBK文本
int byUTF;
while ((byUTF = isrUTF.read()) != -1) {
System.out.print((char) byUTF);//乱码
}
//释放资源
oswGBK.close();
isrGBK.close();
isrUTF.close();
}
}
测试记录:
你好
???
五. 字符流
image.png5.1 复制Java文件
需求:
把项目目录下的io1.java内容复制到项目目录下的Copy.java中
三种方式:
- InputStreamReader & OutputStreamWriter (字符流方式 见5.1) 379毫秒
- FileReader & FileWriter (字符流方式 见5.1) 297毫秒
- BufferedReader & BufferedWriter (字符缓冲区流方式 见6.2) 533毫秒
代码:
package Java_study;
import java.io.*;
/**
*
* @author 只是甲
* @date 2021-07-21
* @remark 字符流 复制Java文件
*
*/
public class io15 {
public static void main(String[] args) throws IOException {
long start1 = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
method1("io1.java", "Copy.java");//method1共耗时2153毫秒
}
long end1 = System.currentTimeMillis();
System.out.println("method1共耗时"+ (end1 - start1) + "毫秒");
long start2 = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
method1("io1.java", "Copy.java");
}
long end2 = System.currentTimeMillis();
System.out.println("method1共耗时"+ (end2 - start2) + "毫秒");
}
public static void method1(String source, String target) throws IOException {
//封装数据源
InputStreamReader isr = new InputStreamReader(new FileInputStream(source));
//封装目的地
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(target));
char[] chArr = new char[1024];
int len;
while ((len = isr.read(chArr)) != -1) {
osw.write(chArr, 0, len);
}
//释放资源
osw.close();
isr.close();
}
public static void method2(String source, String target) throws IOException{
//封装数据源
FileReader fr = new FileReader(source);
//封装目的地
FileWriter fw = new FileWriter(target);
char[] chArr = new char[1024];
int len;
while ((len = fr.read(chArr)) != -1) {
fw.write(chArr,0,len);
}
//释放资源
fw.close();
fr.close();
}
}
测试记录:
method1共耗时379毫秒
method1共耗时297毫秒
5.2 OutputStreamWriter写数据的6种方式
方法摘要:
/* @introduction 写一个字符
* @param c 要写入的字符
*/
public void write(char c)
/* @introduction 写一个字符
* @param c 要写入的字符对应码表中int值
*/
public void write(int c)
/* @introduction 写一个字符数组
* @param cbuf 要写入的字符数组
*/
public void write(char[] cbuf)
/* @introduction 写一个字符数组的一部分
* @param cbuf 要写入的字符数组
* @param off 起始索引
* @param len 从起始索引起,写入字符数组长度
*/
public void write(char[] cbuf,int off,int len)
/* @introduction 写一个字符串
* @param str 要写入的字符串
*/
public void write(String str)
/* @introduction 写一个字符串的一部分
* @param str 要写入的字符串
* @param off 起始索引
* @param len 从起始索引起,写入字符串长度
*/
public void write(String str,int off,int len)
代码:
package Java_study;
import java.io.*;
/**
*
* @author 只是甲
* @date 2021-07-21
* @remark OutputStreamWriter写数据的6种方式
*
*/
public class io16 {
public static void main(String[] args) throws IOException{
//创建字符输出流对象 (同时创建文件)
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("target.txt"));
//a. public void write(char c); 写一个字符
methodA(osw);//写入一个字符a
osw.write('\r');//换行
//b. public void write(int c); 写一个字符
methodB(osw);//写入一个字符b
osw.write('\r');//换行
//c. public void write(char[] cbuf); 写一个字符数组
methodC(osw);//写入abcde
osw.write('\r');//换行
//d. public void write(char[] cbuf,int off,int len); 写一个字符数组的一部分
methodD(osw);//写入c
osw.write('\r');//换行
//e. public void write(String str); 写一个字符串
methodE(osw);//写入hello
osw.write('\r');//换行
//f. public void write(String str,int off,int len); 写一个字符串的一部分
methodF(osw);//写入lo
osw.write('\r');//换行
//释放资源
osw.close();//关闭此流,关闭前将缓冲区(内存)字符刷新(flush=>写入硬盘)
}
public static void methodA(OutputStreamWriter osw) throws IOException {
osw.write('a');
}
public static void methodB(OutputStreamWriter osw) throws IOException {
osw.write(98);
}
public static void methodC(OutputStreamWriter osw) throws IOException {
char[] chs = {'a', 'b', 'c', 'd', 'e'};
osw.write(chs);//写入 abcde
}
public static void methodD(OutputStreamWriter osw) throws IOException {
char[] chs = {'a', 'b', 'c', 'd', 'e' };
osw.write(chs, 2, 1);//写入bcd
}
public static void methodE(OutputStreamWriter osw) throws IOException {
String s = "hello";
//e. public void write(String str); 写一个字符串
osw.write(s);//写入hello
//void flush():刷新该流的缓冲
//osw.flush();
}
public static void methodF(OutputStreamWriter osw) throws IOException {
String s = "hello";
//f. public void write(String str,int off,int len); 写一个字符串的一部分
osw.write(s, 3, 2);
//void flush():刷新该流的缓冲
//osw.flush();
}
}
5.3 InputStreamReader读数据的2种方式
方法摘要
//一次读取一个字符
public int read()
//一次读取一个字符数组
public int read(char[] cbuf)
代码:
package Java_study;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
/**
*
* @author 只是甲
* @date 2021-07-21
* @remark InputStreamReader读数据的2种方式
*
*/
public class io17 {
public static void main(String[] args) throws IOException{
//创建字符流输入对象
InputStreamReader isrA = new InputStreamReader(new FileInputStream("a.txt"));
InputStreamReader isrB = new InputStreamReader(new FileInputStream("a.txt"));
//a. public int read(); 一次读取一个字符
methodA(isrA);
System.out.println("\r\n==========================");
//b. public int read(char[] cbuf); 一次读取一个字符数组
methodB(isrB);
//释放资源
isrA.close();
isrB.close();
}
public static void methodA(InputStreamReader isr) throws IOException{
int ch;
while ((ch = isr.read()) != -1) {
System.out.print((char) ch);
}
}
public static void methodB(InputStreamReader isr) throws IOException{
char[] chs = new char[1024];
int len;
while ((len = isr.read(chs)) != -1) {
System.out.println(new String(chs, 0, len));
}
}
}
六. 字符缓冲区流
image.png6.1 概述
BufferedWriter
- 将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
- 可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
- 构造方法
BufferedWriter(Writer out)
BufferedReader
- 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
- 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
- 构造方法
BufferedReader(Reader in)
代码:
package Java_study;
import java.io.*;
/**
*
* @author 只是甲
* @date 2021-07-21
* @remark 字符缓冲区流概述
*
*/
public class io18 {
public static void main(String[] args) throws IOException{
//创建字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
//调用写数据的方法
bw.write("hello");
//释放资源
bw.close();
//创建字符缓冲输入流对象
BufferedReader br1 = new BufferedReader(new FileReader("io1.java"));
BufferedReader br2 = new BufferedReader(new FileReader("io1.java"));
//方式1:一次读取一个字符
method1(br1);
//方式2:一次读取一个字符数组
method2(br2);
//释放资源
br1.close();
br2.close();
}
public static void method1(BufferedReader br) throws IOException{
int ch;
while((ch=br.read()) != -1) {
System.out.print((char)ch);
}
}
public static void method2(BufferedReader br) throws IOException{
char[] chs = new char[1024];
int len;
while ((len = br.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}
}
}
6.2 复制文本文件
需求:
- 把项目目录下的a.txt内容复制到项目目录下的b.txt中
- 数据源
a.txt—读数据—字符流—InputStreamReader—FileReader—BufferedReader - 目的地
b.txt—写数据—字符流—OutputStreamWriter—FileWriter—BufferedWriter
代码:
package Java_study;
import java.io.*;
/**
*
* @author 只是甲
* @date 2021-07-21
* @remark 字符缓冲区流 复制文本文件
*
*/
public class Io19 {
public static void main(String[] args) throws IOException{
//封装数据源
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
//封装目的地
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
//读写数据
char[] chs = new char[1024];
int len;
while ((len = br.read(chs)) != -1 ) bw.write(chs, 0, len);
//释放资源
bw.close();
br.close();
}
}
6.3 复制Java文件
需求:
把项目目录下的io1.java内容复制到项目目录下的Copy.java中
三种方式:
- InputStreamReader & OutputStreamWriter (字符流方式 见5.1) 379毫秒
- FileReader & FileWriter (字符流方式 见5.1) 297毫秒
- BufferedReader & BufferedWriter (字符缓冲区流方式 见6.2) 533毫秒
代码:
package Java_study;
import java.io.*;
/**
*
* @author 只是甲
* @date 2021-07-21
* @remark 字符缓冲区流 字符缓冲区流复制Java文件
*
*/
public class Io20 {
public static void main(String[] args) throws IOException {
long start3 = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
method3("io1.java", "Copy.java");
}
long end3 = System.currentTimeMillis();
System.out.println("method3共耗时"+ (end3 - start3) + "毫秒");
}
public static void method3(String source,String target) throws IOException {
//封装数据源
BufferedReader br = new BufferedReader(new FileReader(source));
//封装目的地
BufferedWriter bw = new BufferedWriter(new FileWriter(target));
//读写数据
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
}
}
6.4 字符缓冲区流的特殊功能
BufferedWriter
//写入一个行分隔符,这个行分隔符是由系统决定的
void newLine()
BufferedReader
//包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
String readLine()
代码:
package Java_study;
import java.io.*;
/**
*
* @author 只是甲
* @date 2021-07-21
* @remark 字符缓冲区流 字符缓冲区流复制Java文件
*
*/
public class Io21 {
public static void main(String[] args) throws IOException{
//创建字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
//写数据
for (int x = 0; x < 3; x++) {
bw.write("hello");
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
//创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("bw.txt"));
//创建line对象接收每一行数据
String line;
//b. String readLine():包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
while ((line = br.readLine()) != null) {
System.out.println(line);
}
//释放资源
br.close();
}
}
网友评论