(二)字节流
1.IO流概述和分类
IO流概述:
- IO:输入/输出(Input/Output)
- 流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流的本质是数据传输
- IO流就是用来处理设备间数据传输问题的
常见的应用:文件复制;文件上传;文件下载
IO流分类:
- 按照数据的流向
输入流:读数据
输出流:写数据
- 按照数据类型来分
字节流
字节输入流;字节输出流
字符流
字符输入流;字符输出流
一般来说,我们说IO流的分类是按照数据类型来分
那么这两种流都在什么情况下使用呢?
- 如果数据通过Window自带的记事本软件打开,我们还可以读懂里面的内容,就是用字符流,否则使用字节流。如果你不知道该使用那种类型的流,就使用字节流
2.字节流写数据
字节流抽象基类
- InputStream:这个抽象类是表示字节输入流的所有类的超类
- OutputStream:这个抽象类是表示字节输出流的所有的超类
- 子类名特点:子类名称都是以其父类名作为子类名的后缀
FileOutputStream:文件输出流用于将数据写入File
- FileOutputStream(String name) :创建文件输出流以指定的名称写入文件
使用字节输出流写数据的步骤:
- 创建字节输出流对象(调用系统功能创建了对象,创建字节输出流对象,让字节输出流对象指向文件)
- 调用字节输出流对象的写数据方法
- 释放资源(关闭此文件输出流并释放与此流相关联的任何系统资源)
代码演示:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
//创建字节流输出对象
//File f = new File("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\fos.txt");
//FileOutputStream fos = new FileOutputStream(f);
//FileOutputStream fos = new FileOutputStream(new File("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\fos.txt"));
FileOutputStream fos = new FileOutputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\fos.txt");//这一行与上面三行是等价的,这个写法最简单
//void write(int b):将指定的字节写入此文件输出流
fos.write(50);
//最后都要释放资源
//void close():关闭此文件输出流并释放与此流相关联的任何系统资源
fos.close();
}
}
3.字节流写数据的3种方式
代码演示:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
//创建字节流输出对象
FileOutputStream fos = new FileOutputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\fos.txt");
//void write(int b)
fos.write(50);//2
fos.write(51);//3
fos.write(52);//4
//void write(byte[] b)
/* byte[] b = {53,54,55,56};
fos.write(b);//5678 */
String s = "abcde";
byte[] bytes = s.getBytes();
fos.write(bytes);//abcde
//void write(byte[] b,int off,int len)
fos.write(bytes,1,3);//bcd
//最后都要释放资源
fos.close();
}
}
4.字节流写数据的两个小问题
(1)字节流写数据如何实现换行?
- 写完数据后,加换行符
windows: \r\n
linux: \n
mac: \r
(2)字节流写数据如何实现追加写入?
- public FileOutputStream(String name,boolean append)
- 创建文件输出流以指定的名称写入文件。如果第二个参数为true,则字节流写入文件的末尾而不是开头
代码演示:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
//创建字节流输出对象,增加第二参数为true,实现追加写入的功能
FileOutputStream fos = new FileOutputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\fos.txt", true);
//写数据
for (int i = 0; i < 10; i++) {
fos.write("abcde".getBytes());
fos.write("\r\n".getBytes());
}
//释放资源
fos.close();
}
}
5.字节流写数据加异常处理
finally:在异常处理时提供finally块来执行所有清除操作。比如说IO流中的释放资源
特点:被finally控制的语句一定会执行,除非JVM退出
try{
可能出现异常的代码
} catch (异常类名 变量名) {
异常的处理代码;
} finally {
执行所有清除操作;
}
代码演示:
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\fos.txt");
fos.write("abcde".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fos != null){ //判断如果fos不是空的则进行资源释放(增加代码的健壮性),如果不进行判断可能会造成空指针异常
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
6.字节流读数据(一次读一个字节)
需求:把文件fos.txt的内容读出来在控制台输出
FileInputStream:从文件系统中的文件获取输入字节
- FileInputStream(String name) :通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名
使用字节输入流读数据的步骤:
1.创建字节输入流对象
2.调用字节输入流对象的读数据方法
3.释放资源
代码演示:
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
//创建字节流读数据的对象
FileInputStream fis = new FileInputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\fos.txt");
//读数据
/*
int by = fis.read();
while(by != -1) {
System.out.print((char)by); //此处用print 不用println
by = fis.read();
}
*/
//简化上述代码
int by;
while ((by = fis.read()) != -1) {
System.out.print((char) by);
}
//释放资源
fis.close();
}
}
7.案例(复制文本文件)
代码实现:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyDemo {
public static void main(String[] args) throws IOException {
//创建输入输出流对象
FileOutputStream fos = new FileOutputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\fos_copy.txt");
FileInputStream fis = new FileInputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\fos.txt");
//读取数据并写入数据
int by;
while((by = fis.read()) != -1) {
fos.write(by);
}
//释放资源
fos.close();
fis.close();
}
}
8.字节流读数据(一次读一个字节数组数据)
需求:把文件fos.txt中的内容读取出来在控制台输出
使用字节输入流读数据的步骤:
1.创建字节输入流对象
2.调用字节输入流对象的读数据方法
3.释放资源
代码演示:
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamDemo2 {
public static void main(String[] args) throws IOException {
//创建字节输入流的对象
FileInputStream fis = new FileInputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\fos.txt");
//读数据
byte[] bys = new byte[1024];//1024及其整数倍
int len;
while((len = fis.read(bys)) != -1){
System.out.print(new String(bys,0,len));
}
//释放资源
fis.close();
}
}
9.字节流复制图片
代码演示:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyJpgDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\头像.jpg");
FileOutputStream fos = new FileOutputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\头像Copy.jpg");
byte[] bys = new byte[1024];
int len;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}
fis.close();
fos.close();
}
}
10.字节缓冲流
代码演示:
import java.io.*;
public class BufferStreamDemo {
public static void main(String[] args) throws IOException {
/*
FileOutputStream fos = new FileOutputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\Bos.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
*/
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\Bos.txt"));
bos.write("hello\n".getBytes());
bos.write("world\n".getBytes());
bos.close();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\Bos.txt"));
//一次读一个字节
/* int by;
while ((by = bis.read()) != -1) {
System.out.print((char) by);
}*/
//一次读一组字节
byte[] bys = new byte[1024];
int len;
while ((len = bis.read(bys)) != -1) {
System.out.println(new String(bys, 0, len));
}
bis.close();
}
11.案例(复制视频)
代码实现:
import java.io.*;
public class CopyMP4Demo {
public static void main(String[] args) throws IOException {
//记录开始时间
long startTime = System.currentTimeMillis();
//创建字节输入输出流对象
FileInputStream fis = new FileInputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\素材.mp4");
FileOutputStream fos = new FileOutputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\素材copy.mp4");
//读取数据并写入数据
//1.基本字节流一次读写一个字节
/*int dy;
while ((dy = fis.read()) != -1) {
fos.write(dy);
} //共耗时:5006毫秒*/
//2.基本字节流一次读写一个字节数组
/*byte[] bys = new byte[1024];
int len;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
} //共耗时:9毫秒*/
//3.字节缓冲流一次读写一个字节
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\素材.mp4"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\JAVA\\JAVA Document\\Review\\src\\TEMP\\TEMP25\\素材copy.mp4"));
/* int by;
while ((by = bis.read()) != -1) {
bos.write(by);
} //共耗时:35毫秒*/
//4.字节缓冲流一次读写一个字节数组
byte[] bys2 = new byte[1024];
int len2;
while ((len2 = bis.read(bys2)) != -1) {
bos.write(bys2, 0, len2);
} //共耗时:3毫秒
//释放资源
/*fis.close();
fos.close();*/
bis.close();
bos.close();
//记录结束时间
long endTime = System.currentTimeMillis();
System.out.println("共耗时:" + (endTime - startTime) + "毫秒");
}
}
总结:四种读写方式中字节缓冲流一次读写一个字节数组是最快的方式,基本字节流一次读写一个字符是最慢的