IO、 字节流
一. IO流概述
a. IO: 输入和输出
b. 流: 是一种抽象概念,是对数据传输的总称
c. IO流就是用来处理设备间数据传输的,常见应用,文件复制,上传,下载
二. IO流概述和分类
按数据的流向,
输出流:写数据
输入流:读数据
按类型分,
字节流:打开读不懂的,就是字节流,不清楚该用什么的,也用字节流
字符流:打开读的懂的,就是字符流
三. 抽象类 InputStream、OutputStream
字节流写数据
FileOutputStream fi = new FileOutputStream("myByteStream/fileI.txt");
/*
做了3件事
a. 调用系统功能创建了文件
b. 创建了字节流对象
c. 让字节输出流对象指向创建好的文件
*/
fi.write(99);
/*
a. 关闭此文件输出流
b. 释放与此有关联的任何系统资料
*/
fi.close();
写数据的3种方式
-write(int b) 一次写一个字节数据
-write(byte[] b) 一次写一个字节数组数据
-write(byte[] b, int off, int len) 字节数组从off开始,len长度的一段写入
FileOutputStream fo = new FileOutputStream("myByteStream/fo.txt");
fo.write(97);
fo.write(97);
byte[] bt = {10, 20 ,89, 96, 96, 96, 96, 95, 93, 93, 93};
// fo.write(bt);
fo.write(bt, 2,5);
fo.close();
1:字节流写数据如何实现换行呢?
window: \r\n
linux: \n
mac: \r
2:字节流写数据如何实现追加写入呢?
public FileOutputStream(String name, boolean append)
throws FileNotFoundException
/** 实现换行 */
//创建字节输出流对象
FileOutputStream fos = new FileOutputStream("myByteStream/fos.txt");
//写数据
for (int i = 0; i < 10; i++) {
fos.write("hello".getBytes());
fos.write("\r\n".getBytes());
}
//释放资源
fos.close();
/** 实现追加写入 */
FileOutputStream fo = new FileOutputStream("myByteStream/fos.txt",true);
//写数据
for (int i = 0; i < 10; i++) {
fo.write("world".getBytes());
fo.write("\r\n".getBytes());
}
//释放资源
fo.close();
四. 字节流写数据加异常处理
-因为try catch的时候,如果出现异常,会执行不到close,资源还在被暂用着,这时需要用到finally
finally:在处理异常时执行清除操作,比如IO流中释放资源;它一定会执行,除非JVM退出;
完整的,就长这个挫样子
FileOutputStream fos = null;
try {
fos = new FileOutputStream("myByteStream\\fos.txt");
fos.write("hello".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
五. 字节流读数据
read() 一次读一个字节数据,返回值是-1,则表示已经读取完毕
// 创建
FileInputStream fis = new FileInputStream("myByteStrean/fos.txt");
// 读
int bt;
while ((bt = fis.read()) != -1) {
System.out.println((char)bt);
}
// 关闭
fis.close();
案例:
读 1.txt内的内容,复制到2.txt中
// 字节流 - 读
FileInputStream fis = new FileInputStream("myByteStream/fos.txt");
// 字节流 - 写
FileOutputStream fos = new FileOutputStream("myByteStream/foo.txt",true);
// 读、写
int bt;
while ((bt = fis.read()) != -1) {
fos.write(bt);
}
// 关闭
fis.close();
fos.close();
一次读取一个 “字节数组”的数据
FileInputStream fis = new FileInputStream("myByteStream/fos.txt");
//存储器
byte[] by = new byte[1024]; // 一次读取1024的倍数
int len;
while ((len = fis.read(by)) != -1) {
System.out.print(new String(by));
}
fis.close();
案例:使用字节流复制图片,到目的地文件夹
// 字节流 - 读
FileInputStream fis = new FileInputStream("/Users/thor/desktop/1.png");
// 字节流 - 写
FileOutputStream fos = new FileOutputStream("/Users/thor/desktop/copyPng/2.png");
// 读、写
byte[] by = new byte[1024]; // 1024的存储器
int len;
while ((len = fis.read(by)) != -1) {
fos.write(by,0, len);
/*
这里要用 0 和len, 因为数组是重复使用,例子:第一次循环by被填满了,第二次填数据是可能只替换了前800个数据,
… by[788] = a, by[799] = b; 后面的224个数据还是上一个循环的数据,并没有被替换掉,数据就错误了;
*/
}
// 关闭
fis.close();
fos.close();
六. 字节缓冲流:
BufferOutputStream
BufferedInputStream
构造方法:
字节缓冲输出流:BufferedOutputStream(OutputStream out)
字节缓冲输入流:BufferedInputStream(InputStream in)
// 读数据
// 方式 一
FileInputStream fos1 = new FileInputStream("myByteStream/foo.txt");
BufferedInputStream bfi1 = new BufferedInputStream(fos1);
// 方式二
BufferedInputStream bfi = new BufferedInputStream(new FileInputStream("myByteStream/foo.txt"));
/* 字节输出流在创建文件的时候,会把原文件覆盖掉,如果不想覆盖,就要append true */
BufferedOutputStream bfo = new BufferedOutputStream(new FileOutputStream("myByteStream/fos.txt",true));
// 读写方式一 ,一次读一个字节
int by;
while ((by = bfi.read()) != -1) {
bfo.write(by);
}
// 读写方式二,一次读多个字节
byte[] byt = new byte[1024];
int len;
while ((len = bfi.read(byt)) != -1) {
bfo.write(byt,0,len); //
}
// 关闭
bfi.close();
bfo.close();
七. 案例
四种方式实现复制视频,并记录每种方式复制视频的时间
1:基本字节流一次读写一个字节
2:基本字节流一次读写一个字节数组
3:字节缓冲流一次读写一个字节
4:字节缓冲流一次读写一个字节数组
//记录开始时间
long startTime = System.currentTimeMillis();
// 复制视频
// 1:基本字节流一次读写一个字节
FileInputStream fi = new FileInputStream("/Users/home/desktop/1.avi");
FileOutputStream fo = new FileOutputStream(“/home/thor/desktop/avi/2.avi");
/*// 一次读一个字节 共耗时:97650毫秒
int by;
while ((by = fi.read()) != -1) {
fo.write(by);
}*/
/* // 一次读多个字节 共耗时:264毫秒
byte[] by = new byte[1024];
int len;
while ((len = fi.read(by)) != -1){
fo.write(by,0,len);
*//*
这里要用 0 和len, 因为数组是重复使用,例子:第一次循环by被填满了,第二次填数据是可能只替换了前800个数据,
… by[788] = a, by[799] = b; 后面的224个数据还是上一个循环的数据,并没有被替换掉,数据就错误了;
*//*
}*/
// 3:字节缓冲流
BufferedInputStream bfi = new BufferedInputStream(fi);
BufferedOutputStream bfo = new BufferedOutputStream(fo);
/* // 一次读写一个字节 共耗时:936毫秒
int len;
while ((len = bfi.read()) != -1){
bfo.write(len);
}*/
// 一次读写一个字节数组 66毫秒
byte[] by = new byte[1024];
int len;
while ((len = bfi.read(by)) != -1) {
bfo.write(by, 0, len);
}
// 关闭
fi.close();
fo.close();
//记录结束时间
long endTime = System.currentTimeMillis();
System.out.println("共耗时:" + (endTime - startTime) + "毫秒");