缓冲流(字节型)实现非文本的复制
- Buffered能够提高读写速度的原因:内部提供了一个缓冲区。
打开源码,可以发现其内部提供了一个大小为1024八倍的常量,相当于提供了一个8192大小的缓冲区。当读文件时,先把文件读进缓冲区中,当达到8192大小时一次性写出。相应的也有一个flush()方法用来刷新缓冲区。(缓冲流的write中会自动进行flush刷新。)
使用字节型缓冲流实现非文本文件(.MP4)的复制:
@Test
public void testCopyFile() {
long start = System.currentTimeMillis();
String srcPath = "video.mp4";
String destPath = "video3.mp4";
copyFileWithBuffered(srcPath, destPath);
long end = System.currentTimeMillis();
System.out.println("缓冲流(Buffered)复制文件花费的时间为:" + (end - start));
}
public void copyFileWithBuffered(String srcPath, String destPath) {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(new File(srcPath)));
bos = new BufferedOutputStream(new FileOutputStream(new File(destPath)));
//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 {
//关闭外层流的同时,内层流也会自动进行关闭;可以省略内层流的关闭.
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 testBufferedReaderBufferedWriter(){
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(new File("hello.txt")));
bw = new BufferedWriter(new FileWriter(new File("hello2.txt")));
//方式一:
// char[] cbuf = new char[1024];
// int len;
// while ((len = br.read(cbuf)) != -1) {
// bw.write(cbuf, 0, len);
// }
//方式二:
String data;
while((data=br.readLine())!=null){
bw.write(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();
}
}
}
}
节点流与缓冲流总结
节点流(又称文件流) | 缓冲流(处理流的一种) |
---|---|
FileInputStream (read(byte[] buffer)) |
BufferedInputStream (read(byte[] buffer)) |
FileOutputStream (write(byte[] buffer,0,len)) |
BufferedOutputStream (write(byte[] buffer,0,len)) |
FileReader (read(char[] cbuf)) |
BufferedReader (read(char[] cbuf)/readLine()) |
FileWriter (write(char[] cbuf,0,len)) |
BufferedWriter (write(char[] cbuf,0,len)/flush()) |
缓冲流练习1
需求:使用缓冲流实现图片加密解密操作。
异或加密:与其说这是一种加密算法,倒不如称其为文件信息的简单变换,将每一个数据与某给定数据进行异或操作即可完成加密或解密。
图片加密:
@Test
public void test1(){
BufferedInputStream fis = null;
BufferedOutputStream fos = null;
try {
fis = new BufferedInputStream(new FileInputStream("img1.jpg"));
fos = new BufferedOutputStream(new FileOutputStream("img2.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();
}
}
}
}
图片解密:
@Test
public void test2(){
BufferedInputStream fis = null;
BufferedOutputStream fos = null;
try {
fis = new BufferedInputStream(new FileInputStream("img2.jpg"));
fos = new BufferedOutputStream(new FileOutputStream("img3.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();
}
}
}
}
缓冲流练习2
获取文本上每个字符出现的次数。(
提示:遍历文本的每一个字符,字符以及出现的次数保存在Map中;将Map中数据写入文件。
)
@Test
public void test3(){
BufferedReader br = null;
BufferedWriter bw = null;
try {
Map<Character, Integer> map = new HashMap<>();
br = new BufferedReader(new FileReader("hello.txt"));
bw = new BufferedWriter(new FileWriter("copyHello.txt"));
int c = 0;
while ((c = br.read()) != -1) {
char ch = (char) c;
if (map.get(ch) == null) {
map.put(ch, 1);
} else {
map.put(ch, map.get(ch) + 1);
}
}
Set<Map.Entry<Character, Integer>> entrySet = map.entrySet();
for (Map.Entry<Character, Integer> i : entrySet) {
switch (i.getKey()) {
case ' ':
bw.write("空格:" + i.getValue());
break;
case '\t':
bw.write("tab:" + i.getValue());
break;
case '\r':
bw.write("回车:" + i.getValue());
break;
case '\n':
bw.write("换行:" + i.getValue());
break;
default:
bw.write(i.getKey() + "=" + i.getValue());
break;
}
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();
}
}
}
}
程序执行后,写出到新文件中的内容如下: