0
点赞
收藏
分享

微信扫一扫

【达内课程】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 文件,内容如下:
【达内课程】BufferedOutputStream、BufferedInputStream用法_输出流
使用范围
如果是单字节读取,可以接 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的图片
【达内课程】BufferedOutputStream、BufferedInputStream用法_缓存_02
运行程序:

原文件路径
d:/abc/headimg.jpg
拆分文件大小(kb)
22
拆分完成

【达内课程】BufferedOutputStream、BufferedInputStream用法_buffer_03
【达内课程】BufferedOutputStream、BufferedInputStream用法_缓存_04

上面的程序是单字节读取,我们改用 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
合并完成

举报

相关推荐

0 条评论