缓冲流涉及到的类
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
引入目的
- 作用:提供流的读取、写入的速度
- 提高读写速度的原因:内部提供了一个缓冲区。默认情况下是8kb
使用说明
- 当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区。
- 当使用
BufferedInputStream
读取字节文件时,BufferedInputStream
会一次性从文件中读取8192
个(8Kb
),存在缓冲区中,直到缓冲区装满了,才重新从文件中读取下一个8192
个字节数组。 - 向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满,
BufferedOutputStream
才会把缓冲区中的数据一次性写到文件里。使用方法flush()
可以强制将缓冲区的内容全部写入输出流。 - 关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也会相应关闭内层节点流。
-
flush()
方法的使用:手动将buffer
中内容写入文件。 - 如果是带缓冲区的流对象的
close()
方法,不但会关闭流,还会在关闭流之前刷新缓冲区,关闭后不能再写出。
使用BufferInputStream和BufferOutputStream实现非文本文件的复制
代码示例:
@Test
public void testBufferedStream() {
BufferedOutputStream bos = null;
BufferedInputStream bis = null;
try {
// 1.创建File对象,指定要复制的非文本文件
File srcFile = new File("D:\\io\\test.jpg");
File destFile = new File("D:\\io\\test_copy.jpg");
// 2.创建节点流(字节流)
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
// 造缓冲流,可以合并书写
// BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
// BufferedOutputStream bos = new BufferedOutputStream(new FilterOutputStream(destFile));
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
// 3.文件读取、写出操作
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭资源
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
使用BufferedReader和BufferedWriter实现文本文件的复制
代码示例:
@Test
public void testBufferedReaderBufferWriter() {
BufferedWriter bw = null;
BufferedReader br = null;
try {
// 创建文件和响应的流
br = new BufferedReader(new FileReader(new File("D:\\io\\hello.txt")));
bw = new BufferedWriter(new FileWriter(new File("D:\\io\\hello_copy.txt")));
// 读写操作
// 方式一:使用char[]数组
// char[] cbuf = new char[1024];
// int len;
// while ((len = br.read(cbuf)) != -1) {
// bw.write(cbuf, 0, len);
// bw.flush();
// }
// 方式二:使用String
String data;
while ((data = br.readLine()) != null) {
// 方法一:
// bw.write(data + "\n"); // data中不包含换行符
// 方法二:
bw.write(data); // data中不包含换行符
bw.newLine(); // 提供换行的操作
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
小练习
测试缓冲流和节点流文件复制速度
节点流实现复制方法
//指定路径下文件的复制
public void copyFile(String srcPath, String destPath) {
FileOutputStream fos = null;
FileInputStream fis = null;
try {
// 1.根据给定路径创建File对象
File srcFile = new File(srcPath);
File destFile = new File(destPath);
// 2.创建字节流
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(destFile);
// 3.开始复制
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
缓冲流实现复制操作
//缓冲流实现文件复制的方法
public void copyFileWithBuffered(String srcPath, String destPath) {
BufferedOutputStream bos = null;
BufferedInputStream bis = null;
try {
// 1.根据传入的路径创建File实例
File srcFile = new File(srcPath);
File destFile = new File(destPath);
// 2.创建节点流(字节流儿)
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
// 创建缓冲流
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
// 复制的相关操作
byte[] buffer = new byte[1024];
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4. 关闭资源
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
测试二者速度
@Test
public void testCopyFileWithBuffered() {
long start = System.currentTimeMillis();
String srcPath = "D:\\io\\test.mp4";
String destPath = "D:\\io\\test_copy.mp4";
// copyFile(srcPath, destPath); // 复制操作花费的时间为:29657 未使用缓冲流
copyFileWithBuffered(srcPath, destPath); // 复制操作花费的时间为:9647 使用缓冲流
long end = System.currentTimeMillis();
System.out.println("复制操作花费的时间为:" + (end - start));
}
实现图片加密操作
加密操作
- 将图片文件通过字节流读取到程序中
- 将图片的字节流逐一进行
^
操作 - 将处理后的图片字节流输出
//图片的加密
@Test
public void test1() {
FileOutputStream fos = null;
FileInputStream fis = null;
try {
fis = new FileInputStream("D:\\io\\test.jpg");
fos = new FileOutputStream("D:\\io\\testSecret.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
for (int i = 0; i < len; i++) {
buffer[i] = (byte) (buffer[i] ^ 5);
}
fos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
解密操作
- 将加密后图片文件通过字节流读取到程序中
- 将图片的字节流逐一进行
^
操作(原理:A^
B^
B = A) - 将处理后的图片字节流输出
//图片的解密
@Test
public void test2() {
FileOutputStream fos = null;
FileInputStream fis = null;
try {
fis = new FileInputStream("D:\\io\\testSecret.jpg");
fos = new FileOutputStream("D:\\io\\test1.jpg");
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
for (int i = 0; i < len; i++) {
buffer[i] = (byte) (buffer[i] ^ 5);
}
fos.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
统计文本字符出现次数
实现思路:
- 遍历文本每一个字符
- 字符出现的次数存在
Map
中 - 把
Map
中的数据写入文件
@Test
public void testWordCount() {
FileReader fr = null;
BufferedWriter bw = null;
try {
// 1.创建Map集合
Map<Character, Integer> map = new HashMap<>();
// 2.遍历每一个字符,每个字符出现的次数放到map中
fr = new FileReader("D:\\io\\hello.txt");
int c = 0;
while ((c = fr.read()) != -1) {
// int 还原成 char
char ch = (char) c;
// 判断char是否在map中第一次出现
if (map.get(ch) == null) {
map.put(ch, 1);
} else {
map.put(ch, map.get(ch) + 1);
}
}
// 3.把map中数据存在文件count.txt
bw = new BufferedWriter(new FileWriter("D:\\io\\count.txt"));
// 遍历map,再写入数据
Set<Map.Entry<Character, Integer>> entrySet = map.entrySet();
for (Map.Entry<Character, Integer> entry : entrySet) {
switch (entry.getKey()) {
case ' ':
bw.write("空格 = " + entry.getValue());
break;
case '\t': // '\t'表示 tab键 制表符
bw.write("tab键 = " + entry.getValue());
break;
case '\r': // '\r' 回车符
bw.write("回车 = " + entry.getValue());
break;
case '\n':
bw.write("换行 = " + entry.getValue());
break;
default:
bw.write(entry.getKey() + " = " + entry.getValue());
break;
}
bw.newLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭资源
if (fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bw != null) {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
网友评论