目录
1:什么是IO流
IO流是一组有顺序,有起点和终点的字节集合,是对数据传输的总称和抽象。。在java中把不同的输入/输出源(键盘,文件,网络连接等)抽象表述为“流”(stream)。通过流的形式允许java程序使用相同的方式来访问不同的输入/输出源。
IO流的分类:
根据处理数据类型的不同分为:字符流和字节流
根据数据流向不同分为:输入流和输出流
刘结构图如下:
抽象类:
抽象类用abstract修饰,里边有通用方法和抽象方法也是abstract修饰,通过继承,要求不同的子类,对抽象方法有不同的实现,体现了多态,对于普通方法,不用重写,直接复用
2:字节流(byte流)
字节流是万能的数据流,专注于处理字节,适用于所有类型的文件,但是处理字符的时候没有字符流速度快,其他的情况完美
1:InputStream和OutputStream也是两个抽象类,里边定义了read、close和write、flush等各种抽象方法和公共方法,便于不同的实现继承
2:读取的时候尽量设置一个字节数组读取数据,不要逐个字节读取,8位2进制为一个字节,
3:尽量使用在缓冲区的BufferedInputStream,防止多次与硬盘交互,影响速度。
4:字节流可以操作任何数据
2.1:字节输入流(InputStream)
InputStream(抽象类:表示所有字节输入流的父类)
|-FileInputStream(主要用于图像数据之类的原始字节流)
|-FilterInputStream(简单的重写InputStream方法)
|-BufferedInputStream(提供缓冲等功能)
|-PipedInputStream(主要用于多线程)
2.2:字节输出流(OutputStream)
OutputStream(抽象类:表示所有字节输出流的父类)
|-FileOutputStream(主要用于图像数据之类的原始字节流)
|-FilterOutputStream(简单的重写OutputStream方法)
|-BufferedOutputStream(提供缓冲等功能)
|-PrintStream(打印各种数据值得表示形式)
|-PipedOutputStream(主要用于多线程)
https://www.cnblogs.com/yhc20091116/p/4312661.html
2.3:字节流验证
主要验证了原始字节流和buffer的字节流,buffer字节流带有缓冲区。
方法1、方法2、方法3,从InputStream 过度到BufferedInputStream,效率原来越高
//方法一:使用InputStream逐个字节读取,速度超级慢
private static void copy() {
System.out.println("---copy开始---");
// TODO Auto-generated method stub
InputStream inputStream=null;
OutputStream outputStream=null;
long start=System.currentTimeMillis();
try {
outputStream=new FileOutputStream(new File("G:\\io\\stream\\input1\\2.jpg"));
inputStream=new FileInputStream(new File("G:\\io\\stream\\input1\\1.jpg"));
int i=0;
while ((i=inputStream.read())!=-1) {
outputStream.write(i);
}
long end=System.currentTimeMillis();
System.out.println("结束耗时毫秒:"+(end-start));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("结束");
}
//方法二:使用InputStream一次性读取1024个字节读取,速度变快
private static void copy1() {
System.out.println("---copy开始---");
// TODO Auto-generated method stub
InputStream inputStream=null;
OutputStream outputStream=null;
long start=System.currentTimeMillis();
try {
outputStream=new FileOutputStream(new File("G:\\io\\stream\\input1\\4.jpg"));
inputStream=new FileInputStream(new File("G:\\io\\stream\\input1\\1.jpg"));
System.out.println("-----读取过程中------");
byte[] bytes=new byte[1024];
while (inputStream.read(bytes)!=-1) {
outputStream.write(bytes);
}
long end=System.currentTimeMillis();
System.out.println("结束耗时毫秒:"+(end-start));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//方法三:使用带有缓冲区的BufferedInputStream,默认缓冲8K
//一次性读取1024个字节读取,速度很快
private static void copy2() {
System.out.println("---copy开始---");
// TODO Auto-generated method stub
InputStream inputStream=null;
OutputStream outputStream=null;
BufferedInputStream bStream=null;
BufferedOutputStream bufferedOutputStream=null;
long start=System.currentTimeMillis();
try {
outputStream=new FileOutputStream(new File("G:\\io\\stream\\input1\\444.jpg"));
inputStream=new FileInputStream(new File("G:\\io\\stream\\input1\\1.jpg"));
//初始化读取和写入缓冲区
bStream=new BufferedInputStream(inputStream,8192);
bufferedOutputStream=new BufferedOutputStream(outputStream);
System.out.println("-----读取过程中------");
byte[] bytes=new byte[1024];
int a=0;
while ((a=bStream.read(bytes))!=-1) {
bufferedOutputStream.write(bytes, 0, a);
}
//bufferedOutputStream.flush();
long end=System.currentTimeMillis();
System.out.println("结束耗时毫秒:"+(end-start));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
bStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
bufferedOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
3:字符流
(抽象类用abstract修饰,里边有通用方法和抽象方法也是abstract修饰,通过继承,要求不同的子类,对抽象方法有不同的实现,体现了多态,对于普通方法,不用重写,直接复用)
数据在计算机以字节存在,但是我们想要把这些字节转换成我们认识的文字,这个时候我们就需要一种规范一种编码规则,把不同的字节码转换成统一的文字,规范里边有详细的字节到文字对照关系,这就是码表。但是世界上是一种规范解决不了全部问题,或者是其他的人有自己的编码规范。这些不同的规范会导致同一个文字,例如"你好"在不同的码表中对照成不同的编码,所有输入输出的编码规范很重要,规范不同可能会导致乱码。
字符流:字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串。字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的。字符流操作的是缓冲区(当我们对文件进行读写操作时如果不调用close() 或 flush()方法时不能看到数据的变化)。
1:输入流Reader:Reader里边有通用的抽象方法read()和close()。给不同的继承类实现。
2:输出流Writer:Writer里边有通用的抽象方法write()、close()和flush()。给不同的继承类实现。
3:字符流只用来用来读取字符文本,不能操作视频等其他数据。
3.1:字符输入流(Reader)
3.2:字符输出流(Writer)
3.3:字符流验证
bufferWrite和bufferRead的初始化字符集合缓冲区大小是构造函数中的:
private static int defaultCharBufferSize = 8192;
第一步:单纯FileWrite和FileRead读取写入,逐个字符读取,while循环需要很多
// FileReader直接读取,逐个字符读取
private static void FileReader2() {
// TODO Auto-generated method stub
Reader reader = null;
Writer writer = null;
try {
writer = new FileWriter(new File("G:\\io\\字符流\\22.txt"));
reader = new FileReader(new File("G:\\io\\字符流\\1.txt"));
System.out.println("开始");
int a;
// 逐个字符读取,会循环次数很多,效率超级低
while ((a = reader.read()) != -1) {
// 加锁方法,其他线程无法写入 writer.write((char)a);
writer.write(a);
}
writer.flush();
System.out.println("结束");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
第二步:单纯FileWrite和FileRead读取写入,字符数组1024读取写入,while循环变少
// FileReader直接读取
private static void FileReader() {
Reader reader = null;
Writer writer = null;
try {
writer = new FileWriter(new File("G:\\io\\字符流\\2.txt"));
reader = new FileReader(new File("G:\\io\\字符流\\1.txt"));
System.out.println("开始");
// 字节流缓冲区配合缓冲数组
char[] cbuf = new char[1024];
int a1;
// 从缓冲区读取每次1024个字符
reader.read(cbuf);
while ((a1 = reader.read(cbuf)) != -1) {
System.out.println("---读取次数--" + a1);
writer.write(cbuf, 0, a1);
}
writer.flush();
System.out.println("结束");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
第三步:引入bufferWrite和bufferRead读取写入,默认缓冲区8192
// FileReader直接读取
private static void BufferedReader() {
// TODO Auto-generated method stub
BufferedReader reader = null;
BufferedWriter writer = null;
String str = null;
try {
// 构造参数默认缓冲区大小为CharBufferSize:8192
reader = new BufferedReader(new FileReader("G:\\io\\字符流\\1.txt"));
writer = new BufferedWriter(new FileWriter("G:\\io\\字符流\\3.txt"));
//逐行读取,适用于格式规范的文件
while ((str = reader.readLine()) != null) {
System.out.println("---行数---");
System.out.println(str);
writer.write(str);
writer.newLine();
}
// 没有fluash清除缓冲区之前,数据不在文件中
writer.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
第四步:引入bufferWrite和bufferRead读取写入,默认缓冲区8192 ,并且引入字符数组1024
// FileReader直接读取
private static void BufferedReader1() {
// TODO Auto-generated method stub
BufferedReader reader = null;
BufferedWriter writer = null;
try {
// 构造参数默认缓冲区大小为CharBufferSize:8192
reader = new BufferedReader(new FileReader("G:\\io\\字符流\\1.txt"));
writer = new BufferedWriter(new FileWriter("G:\\io\\字符流\\4.txt"));
// reader=new BufferedReader( new InputStreamReader(new FileInputStream(new
// File("G:\\io\\字符流\\1.txt"))));
char[] cbuf = new char[1024];
int a = 0;
while ((a = reader.read(cbuf)) != -1) {
writer.write(cbuf, 0, a);
}
// 没有fluash清除缓冲区之前,数据不在文件中
writer.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
这四种方法,读取速度在逐渐变快