Java中BufferedOutputStream、BufferedInputStream用法
文章目录
介绍
BufferedOutputStream 字节缓冲输出流。顾名思义就是它有一个内部的 buffer(缓存),当写数据时,可以批量的写,提高单字节读写效率。它的工作原理和 BufferedIputStream 一样。与其他流相接,提供特定数据处理功能,是操作其他流的流。
BufferedOutputStream
输出的字节值,暂存在内存数组中,放满后,自动批量输出。放不满,flush()
手动刷出
BufferedInputStream
读取一批字节值,暂存在内存数组中,可以一个字节一个字节的处理数组中的数据。这一批处理完,再缓存下一批。
tip:磁盘读取效率低,内存读取效率高
使用
创建对象 1、采用的默认的缓冲区大小,来构造一个字节缓冲输出流对象。内部缓存数组长度8192
BufferedOutputStream out = new BufferedOutputStream(相接的流);
2、指定 size 缓冲区大小构造缓冲输出流对象。如下内部缓存数组长度为 16k
BufferedOutputStream out = new BufferedOutputStream(相接的流,16*1024);
BufferedOutputStream 方法 1、一次写一个字节。末尾1个字节
write(int b)
2、写入全部指定的数组
write(byte[] buff)
3、一次写一个字节数组的一部分:从 from 开始的 length 个
write(byte[] buff,int from,int length)
4、刷新此缓冲的输出流。这迫使所有缓冲的输出字节被写出到底层输出流中。
flush()
BufferedInputStream 方法 1、读取一个字节
read();
2、根据传入的数组长度读取
read(byte[] buff);
3、获取剩余的可读取字节量
available();
这些方法都是从父类继承的,没有特殊方法
栗子1:写入文件
public class Main {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("d:/abc/f4");
BufferedOutputStream bos = new BufferedOutputStream(fos);
//这些数据被写进内存中,并没有写进文件
bos.write(97);
bos.write(98);
bos.write(99);
//内存大小8192,并没有存满,所以需要手动刷出
bos.flush();//手动刷出,可以重复执行
/*
* close()方法会先执行flush()
* 然后再执行out.close()
*
* 会先刷出缓存
* 再关闭相接的流
*
*/
bos.close();
}
}
运行程序会在 D 盘 abc 文件夹下创建 f4 文件,内容如下:
使用范围
如果是单字节读取,可以接 buffer。对批量读取,效率并没有帮助。
我们修改上一篇文章 FileInputStream和FileOutputStream用法 的单字节读取。
栗子2:上一章的单字节读取修改
public class Main {
public static void main(String[] args) {
System.out.println("请输入文件路径");
String s = new Scanner(System.in).nextLine();
File from = new File(s);
if (!from.isFile()) {
System.out.println("请输入正确的文件路径");
return;
}
System.out.println("请输入目标文件路径");
String s2 = new Scanner(System.in).nextLine();
File to = new File(s2);
if (to.isDirectory()) {
System.out.println("不是目录路径,是目标文件路径");
return;
}
try {
copy(from, to);
System.out.println("复制成功");
} catch (Exception e) {
System.out.println("复制失败");
e.printStackTrace();
}
}
private static void copy(File from, File to) throws IOException {
BufferedInputStream in = new BufferedInputStream(new FileInputStream(from));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(to));
int b;
while ((b = in.read()) != -1) {
out.write(b);
}
in.close();
out.close();
}
}
栗子3:文件拆分/合并
要求:将文件 d:/abc/a.jpg 拆分,拆分后的文件保存到 d:/abc/a.jpg_aplit 文件夹中 拆分后的文件名称为a.jpg.1、a.jpg.2、a.jpg.3…
public class Main {
public static void main(String[] args) {
System.out.println("原文件路径");
String s = new Scanner(System.in).nextLine();
File file = new File(s);
if (!file.isFile()) {
System.out.println("请输入正确的文件路径");
return;
}
System.out.println("拆分文件大小(kb)");
long size = new Scanner(System.in).nextLong();
size *= 1024;
try {
split(file, size);
System.out.println("拆分完成");
} catch (Exception e) {
System.out.println("拆分失败");
e.printStackTrace();
}
}
private static void split(File file, long size) throws Exception {
//原文件名
String name = file.getName();
//准备拆分文件存放目录
File dir = new File(file.getAbsolutePath() + "_split");
if (dir.exists()) {
//存在,清空
File[] files = dir.listFiles();
for (File file2 : files) {
file2.delete();
}
} else {
//不存在,新建
dir.mkdirs();
}
//字节计数变量 和 文件计数变量
long byteCount = 0;
int fileCount = 0;
FileInputStream in = new FileInputStream(file);
FileOutputStream out = null;
int b;
while ((b = in.read()) != -1) {
//如果没有输出流
//或者前一个文件满了
//创建新的输出流
if (out == null || byteCount == size) {
//如果前面文件满了,要先关闭前一个流
if (out != null) {
out.close();
}
out = new FileOutputStream(new File(dir, name + "." + (++fileCount)));
byteCount = 0;
}
out.write(b);
byteCount++;
}
in.close();
out.close();
}
}
现有一个88k的图片
运行程序:
原文件路径
d:/abc/headimg.jpg
拆分文件大小(kb)
22
拆分完成
上面的程序是单字节读取,我们改用 BufferedOutputStream 和 BufferedInputStream 来增加效率:
private static void split(File file, long size) throws Exception {
//原文件名
String name = file.getName();
//准备拆分文件存放目录
File dir = new File(file.getAbsolutePath() + "_split");
if (dir.exists()) {
//存在,清空
File[] files = dir.listFiles();
for (File file2 : files) {
file2.delete();
}
} else {
//不存在,新建
dir.mkdirs();
}
//字节计数变量 和 文件计数变量
long byteCount = 0;
int fileCount = 0;
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream out = null;
int b;
while ((b = in.read()) != -1) {
//如果没有输出流
//或者前一个文件满了
//创建新的输出流
if (out == null || byteCount == size) {
//如果前面文件满了,要先关闭前一个流
if (out != null) {
out.close();
}
out = new BufferedOutputStream(new FileOutputStream(new File(dir, name + "." + (++fileCount))));
byteCount = 0;
}
out.write(b);
byteCount++;
}
in.close();
out.close();
}
栗子4:文件合并
public class Main {
public static void main(String[] args) {
System.out.println("输入拆分文件存放的文件夹路径");
String s = new Scanner(System.in).nextLine();
File dir = new File(s);
if (!dir.isDirectory()) {
System.out.println("请输入正确的文件夹路径");
return;
}
System.out.println("输入合并的目标文件名");
String s2 = new Scanner(System.in).nextLine();
File name = new File(s2);
if (name.isDirectory()) {
System.out.println("请输入具体的文件路径,不是目录路径");
return;
}
try {
conbine(dir, name);
System.out.println("合并完成");
} catch (Exception e) {
System.out.println("合并失败");
e.printStackTrace();
}
}
private static void conbine(File dir, File name) throws Exception {
File[] list = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File f) {
//只列出数字后缀的文件
if (f.isDirectory()) {
return false;
}
String n = f.getName();
int index = n.lastIndexOf(".");
if (index == -1) {
return false;
}
n = n.substring(index + 1);
return n.matches("\\d+");
}
});
//外接比较器,对文件按数字大小排序
Arrays.sort(list, new Comparator<File>() {
@Override
public int compare(File f1, File f2) {
String n1 = f1.getName();
String n2 = f2.getName();
n1 = n1.substring(n1.lastIndexOf(".") + 1);
n2 = n2.substring(n2.lastIndexOf(".") + 1);
int a = Integer.parseInt(n1);
int b = Integer.parseInt(n2);
return a - b;
}
});
FileOutputStream out = new FileOutputStream(name);
FileInputStream in = null;
byte[] buff = new byte[8192];
int n;
for (File f : list) {
in = new FileInputStream(f);
while ((n = in.read(buff)) != -1) {
out.write(buff, 0, n);
}
in.close();
}
out.close();
}
}
输出结果
输入拆分文件存放的文件夹路径
d:/abc/headimg.jpg_split
输入合并的目标文件名
d:/abc/copy.jpg
合并完成
转载自:https://juejin.cn/post/7016979790590640158