IO流概述
IO流也称为输入、输出流,就是用来读写数据的。
I表示intput,是数据从硬盘文件读入到内存的过程,称之输入,负责读。
O表示output,是内存程序的数据从内存到写出到硬盘文件的过程,称之输出,负责写。
流的四大类:
字节输入流:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流称为字节输入流。
字节输出流:以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流称为字节输出流。
字符输入流:以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流称为字符输入流。
字符输出流:以内存为基准。把内存中的数据以字符写出到磁盘文件或者网络介质中去的流称为字符输出流。
案例——文件拷贝
需求:把某个视频复制到其他目录下的“b.avi”
思路:1.根据数据源创建字节输入流对象
2.根据目的地创建字节输出流对象
3.读写数据,复制视频
4.释放资源
package d4_byte_stream;
import java.io.*;
public class CopyDemo {
public static void main(String[] args) throws Exception {
try {
//1.创建一个字节输入流管道与原视频接通
InputStream is = new FileInputStream("F:\\resource\\视频\\美好的一天从敲代码开始.avi");
//2.创建一个字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("F:\\resource\\视频\\new.avi");
//3.定义一个字节数组转移数据
byte[] buffer = new byte[1024];
int len;//记录每次读取的字节数
while ((len = is.read(buffer)) != -1){
os.write(buffer,0,len);
}
System.out.println("复制成功!");
//4.关闭流
os.close();
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
文字字符输入流:Reader
作用:以内存为基准,把磁盘文件中的数据以字符的形式读取到内存中去。
文件字符输入流:FileReader
作用:以内存为基准,把磁盘文件中的数据以字符的形式读取到内存中去。
文件字符输出流( Filewriter)写数据出去的API:Write
流的关闭与刷新:
flush () 刷新流,还可以继续写数据
close() 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据
缓冲流概述
缓冲流也称为高效流、或者高级流。之前学习的字节流可以称为原始流。
作用:缓冲流自带缓冲区、可以提高原始字节流、字符流读写数据的性能
字节缓冲流性能优化原理:
字节缓冲输入流自带了8KB缓冲池,以后我们直接从缓冲池读取数据,所以性能较好。
字节缓冲输出流自带了8KB缓冲池,数据就直接写入到缓冲池中去,写数据性能极高了。
字节缓冲流
字节缓冲输入流: BufferedInputStream,提高字节输入流读取数据的性能,读写功能上并无变化。
字节缓冲输出流: BufferedoutputStream,提高字节输出流读取数据的性能,读写功能上并无变化。
package d1_byte_buffer;
import java.io.*;
public class ByteBufferDemo {
public static void main(String[] args) {
try (
// 这里面只能防置资源对象,用完会自动调用资源对象的close方法关闭资源(即使出现异常也会做关闭操作)
//1.创建一个字节输入流管道与原视频接通
InputStream is = new FileInputStream("F:\\resource\\视频\\美好的一天从敲代码开始.avi");
//a.把原始的字节输入流包装成高级的缓冲字节输入流
InputStream bis = new BufferedInputStream(is);
//2.创建一个字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("F:\\resource\\视频\\new.avi");
//b.把字节输出流管道包装成高级的缓冲字节输出流管道
OutputStream bos = new BufferedOutputStream(os);
){
//3.定义一个字节数组转移数据
byte[] buffer = new byte[1024];
int len;//记录每次读取的字节数
while ((len = is.read(buffer)) != -1){
os.write(buffer,0,len);
}
System.out.println("复制成功!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
分别使用不同的方式复制大视频观察性能情况
需求:
分别使用低级字节流和高级字节缓冲流拷贝大视频,记录耗时。
分析:
1.使用低级的字节流按照一个一个字节的形式复制文件。
2.使用低级的字节流按照一个一个字节数组的形式复制文件。
3.使用高级的缓冲字节流按照一个一个字节的形式复制文件。
4.使用高级的缓冲字节流按照一个一个字节数组的形式复制文件。
package d2_byte_buffer_time;
import java.io.*;
public class ByteBufferTimeDemo {
private static final String SRC_FILE = "F:\\resource\\视频\\美好的一天从敲代码开始.avi";
private static final String DESL_FILE = "F:\\resource\\";
public static void main(String[] args) {
copy1();//使用低级的字节流按照一个一个字节的形式复制文件:非常的慢,被淘汰!
copy2();//使用低级的字节流按照一个一个字节数组的形式复制文件:比较慢,还能接受
copy3();//使用缓冲的字节流按照一个一个字节的形式复制文件:很慢,不建议使用
copy4();//使用缓冲的字节流按照一个一个字节数组的形式复制文件:飞快,推荐使用
}
/**
* 使用低级的字节流按照一个一个字节的形式复制文件
*/
private static void copy1() {
long startTime = System.currentTimeMillis();
try (
//1.创建低级的字节输入流与源文件接通
InputStream is = new FileInputStream(SRC_FILE);
//2.创建低级的字节输出流与目标文件接通
OutputStream os = new FileOutputStream(DESL_FILE + "video1.avi");
){
//3.定义一个变量记录每次读取的字节(一个一个字节的复制)
int b;
while ((b = is.read()) != -1){
os.write(b);
}
} catch (Exception e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("使用低级的字节流按照一个一个字节的形式复制文件耗时:" + (endTime - startTime)/1000.0 + "s");
}
/**
* 使用低级的字节流按照一个一个字节数组的形式复制文件
*/
private static void copy2() {
long startTime = System.currentTimeMillis();
try (
// 这里面只能防置资源对象,用完会自动调用资源对象的close方法关闭资源(即使出现异常也会做关闭操作)
//1.创建低级的字节输入流与源文件接通
InputStream is = new FileInputStream(SRC_FILE);
//2.创建低级的字节输出流与目标文件接通
OutputStream os = new FileOutputStream(DESL_FILE + "video1.avi");
){
//3.定义一个字节数组转移数据
byte[] buffer = new byte[1024];
int len;//记录每次读取的字节数
while ((len = is.read(buffer)) != -1){
os.write(buffer,0,len);
}
System.out.println("复制成功!");
} catch (Exception e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("使用低级的字节流按照一个一个字节数组的形式复制文件耗时:" + (endTime - startTime)/1000.0 + "s");
}
/**
* 使用缓冲的字节流按照一个一个字节的形式复制文件
*/
public static void copy3(){
long startTime = System.currentTimeMillis();
try (
//1.创建低级的字节输入流与源文件接通
InputStream is = new FileInputStream(SRC_FILE);
//a.把原始的字节输入流包装成高级的缓冲字节输入流
InputStream bis = new BufferedInputStream(is);
//2.创建低级的字节输出流与目标文件接通
OutputStream os = new FileOutputStream(DESL_FILE + "video1.avi");
//b.把字节输出流管道包装成高级的缓冲字节输出流管道
OutputStream bos = new BufferedOutputStream(os);
){
//3.定义一个变量记录每次读取的字节(一个一个字节的复制)
int b;
while ((b = is.read()) != -1){
bos.write(b);
}
} catch (Exception e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("使用缓冲的字节流按照一个一个字节的形式复制文件耗时:" + (endTime - startTime)/1000.0 + "s");
}
/**
* 使用缓冲的字节流按照一个一个字节数组的形式复制文件
*/
private static void copy4() {
long startTime = System.currentTimeMillis();
try (
//1.创建低级的字节输入流与源文件接通
InputStream is = new FileInputStream(SRC_FILE);
//a.把原始的字节输入流包装成高级的缓冲字节输入流
InputStream bis = new BufferedInputStream(is);
//2.创建低级的字节输出流与目标文件接通
OutputStream os = new FileOutputStream(DESL_FILE + "video1.avi");
//b.把字节输出流管道包装成高级的缓冲字节输出流管道
OutputStream bos = new BufferedOutputStream(os);
){
//3.定义一个字节数组转移数据
byte[] buffer = new byte[1024];
int len;//记录每次读取的字节数
while ((len = is.read(buffer)) != -1){
bos.write(buffer,0,len);
}
} catch (Exception e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println("使用缓冲的字节流按照一个一个字节的形式复制文件耗时:" + (endTime - startTime)/1000.0 + "s");
}
}
总结:使用低级的字节流按照一个一个字节的形式复制文件:非常的慢,被淘汰!
使用低级的字节流按照一个一个字节数组的形式复制文件:比较慢,还能接受
使用缓冲的字节流按照一个一个字节的形式复制文件:很慢,不建议使用
使用缓冲的字节流按照一个一个字节数组的形式复制文件:飞快,推荐使用
字符缓冲输入流
字符缓冲输入流:BufferedReader。
作用:提高字符输入流读取数据的性能,除此之外多了按照行读取数据的功能。
新增方法:readLing() 读取一行数据返回,如果读取没有完毕,无行可读返回null
package d3_char_buffer;
import java.io.*;
import java.nio.Buffer;
public class BufferedReaderDemo1 {
public static void main(String[] args) {
try (
//1.创建一个文件字符输入流与原文件接通
Reader fr = new FileReader("io-app/src/data1.txt");
//a.把低级的字符输入流包装成高级的缓冲字符输入流
BufferedReader br = new BufferedReader(fr);
){
String line;
while ((line = br.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符缓冲输出流
字符缓冲输出流:Bufferedwriter。
作用:提高字符输出流写取数据的性能,除此之外多了换行功能
新增方法:newLine() 换行操作
package d3_char_buffer;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class BufferedWriterDemo2 {
public static void main(String[] args) throws IOException {
//1.创建一个字符输出流管道与目标文件接通
Writer fw = new FileWriter("io-app/src/out2.txt",true);//覆盖管道,每次启动都会清空文件之前的数据
BufferedWriter bw = new BufferedWriter(fw);
//写一个字符出去
bw.write(98);
bw.write('a');
bw.write('徐');
bw.newLine();// <==> bw.write("/r/n"); //换行
//写一个字符串出去
bw.write("hhh你真厉害啊");
bw.newLine();// <==> bw.write("/r/n"); //换行
//写一个字符数组出去
char[] chars = "hhh你真厉害啊".toCharArray();
bw.write(chars);
bw.newLine();// <==> bw.write("/r/n"); //换行
//写字符串的一部分出去
bw.write("hhh你真厉害啊",0,5);
bw.newLine();// <==> bw.write("/r/n"); //换行
//写字符串的一部分出去
bw.write(chars,3,5);
bw.write("\r\n");//换行
//fw.flush();//刷新后流可以继续使用
bw.close();//关闭包含刷新,关闭后流不能使用
}
}
案例——拷贝出师表到另一个文件,恢复顺序
需求:把《出师表》的文章顺序进行恢复到一个新文件中。
分析:
1.定义一个缓存字符输入流管道与源文件接通。
2.定义一个List集合存储读取的每行数据。
3.定义一个循环按照行读取数据,存入到List集合中去。
4.对List集合中的每行数据按照首字符编号升序排序。
5.定义一个缓存字符输出管道与目标文件接通。
6.遍历List集合中的每个元素,用缓冲输出管道写出并换行。
字符输入转换流
字符输入转换流: InputStreamReader,可以把原始的字节流按照指定编码转换成字符输入流。
package d4_transfer_stream;
import java.io.*;
public class inputStreamReaderDemo1 {
public static void main(String[] args) throws Exception {
//1.提取GBK文件的原始字节流
InputStream is = new FileInputStream("F:\\resource\\data.txt");
//2.把原始字节流转换成字符输入流
Reader isr = new InputStreamReader(is,"GBK");//以指定的GBK编码转换成字符输入流
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null){
System.out.println(line);
}
}
}
字符输出转换流
字符输入转换流:OutputStreamWriter,可以把字节输出流按照指定编码转换成字符输出流。
package d4_transfer_stream;
import java.io.*;
public class OutputStreamWriterDemo2 {
public static void main(String[] args) throws Exception {
//1.定义一个字节输出流
OutputStream os = new FileOutputStream("io-app2/src/out3.txt");
//2.把原始的字节输出流转换成字符输出流
Writer osw = new OutputStreamWriter(os,"GBK");
//3.把低级的字符输出流包装成高级的缓冲字符输出流
BufferedWriter bw = new BufferedWriter(osw);
bw.write("hhh牛!");
bw.write("hhh牛!");
bw.write("hhh牛!");
bw.close();
}
}