Java IO之字节流
一、Java字节流简介:
在Java中,字节流一般适用于处理字节数据(诸如图片、视频),字符流适用于处理字符数据(诸如文本文件),但二者并没有严格的功能划分,因为有转换流的存在,使得对于数据的处理变得更加灵活。
InputStream和OutputStream分别是字节输入流与字节输出流的抽象基类,它们的子类都是字节流,主要用在按字节来处理二进制数据
InputStream抽象了应用程序读取数据的方式,OutputStream抽象了应用程序写出数据的方式
FileInputStream--->具体实现了在文件上读取数据,FileOutputStream 实现了向文件中写出byte数据的方法
DataOutputStream和DataInputStream是对"流"功能的扩展,可以更加方面的读取int,long,字符等类型数据
BufferedInputStream和BufferedOutputStream,这两个流类为IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能
性能比较:从应用程序中把输入放入文件,相当于将一缸水倒入到另一个缸中:,其中:
FileOutputStream--->write()方法相当于一滴一滴地把水“转移”过去
DataOutputStream-->writeXxx()方法会方便一些,相当于一瓢一瓢把水“转移”过去
BufferedOutputStream--->write方法更方便,相当于一飘一瓢先放入桶中,再从桶中倒入到另一个缸中,性能提高了
文件读取:EOF = End 读到-1就读到结尾
本篇从字节流开始。主要包含以下内容:
- InputStream/OutPutStream - - -字节流基类
- FileInputStream/FileOutputStream - - - - -处理文件类型
- ByteArrayInputStream/ByteArrayOutputStream - - - -字节数组类型
- DataInputStream/DataOutputStream - - - -装饰类
- BufferedInputStream/BufferedOutputStream - - - -缓冲流
常用字节流继承结构图:
常用方法说明:
输入流基本方法
int b = in.read();读取一个字节无符号填充到int低八位.-1是 EOF
in.read(byte[] buf)
in.read(byte[] buf,int start,int size)
输出流基本方法
out.write(int b) 写出一个byte到流,b的低8位
out.write(byte[] buf)将buf字节数组都写入到流
out.write(byte[] buf,int start,int size)
二、实例分析:
这里我们就基于字节流写个工具类分析分析吧
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package me.io;
2
3 import java.io.BufferedInputStream;
4 import java.io.BufferedOutputStream;
5 import java.io.File;
6 import java.io.FileInputStream;
7 import java.io.FileOutputStream;
8 import java.io.IOException;
9
10 public class IOUtils {
11
12 /**
13 * 读取指定文件内容,按照16进制输出到控制台 并且每输出10个byte换行
14 *
15 * @param fileName
16 * @throws IOException
17 */
18 public static void printHex(String fileName) throws IOException {
19 // 把文件作为字节流进行读操作
20 FileInputStream fis = new FileInputStream(fileName);
21 int b = 0;
22 int i = 1;
23 while ((b = fis.read()) != -1) {
24 if (b <= 0xf) {
25 // 单位数前面补0
26 System.out.print('0');
27 }
28 System.out.print(Integer.toHexString(b) + " ");
29 if (i++ % 10 == 0) {
30 System.out.println();
31 }
32 }
33 fis.close();
34 }
35
36 /**
37 * 读取文件放入到字节数组中,再遍历打印到控制台
38 *
39 * @param fileName
40 * @throws IOException
41 */
42 public static void printHexByByteArray(String fileName) throws IOException {
43 FileInputStream fis = new FileInputStream(fileName);
44 byte[] buf = new byte[20 * 1024];
45
46 /**
47 * 从fis中批量读取字节,放入到buf这个字节数组中 从第零个位置开始放,最多放buf.length个字节 返回的是读到的字节个数
48 * 一次性读完,说明字节数组足够大
49 */
50
51 /*
52 int bytes = fis.read(buf, 0, buf.length);
53 int j = 1;
54 for (int i = 0; i < bytes; i++) {
55 if (buf[i] <= 0xf && buf[i] >= 0x0) {
56 System.out.print('0');
57 }
58 System.out.print(Integer.toHexString(buf[i]) + " ");
59 if (j++ % 10 == 0) {
60 System.out.println();
61 }
62 }*/
63
64 int j = 1;
65 int bytes = 0;
66 while ((bytes = fis.read(buf, 0, buf.length)) != -1) {
67 for (int i = 0; i < bytes; i++) {
68 System.out.print(Integer.toHexString(buf[i] & 0xff) + " ");
69 if (j++ % 10 == 0)
70 System.out.println();
71 }
72 }
73 fis.close();
74 }
75
76 /**
77 * 文件拷贝,字节批量读取
78 *
79 * @param srcFile
80 * @param destFile
81 * @throws IOException
82 */
83 public static void copyFile(File srcFile, File destFile) throws IOException {
84 if (!srcFile.exists())
85 throw new IllegalArgumentException("文件" + srcFile + "不存在!");
86 if (!srcFile.isFile())
87 throw new IllegalArgumentException(srcFile + "不是文件!");
88 FileInputStream fis = new FileInputStream(srcFile);
89 FileOutputStream fos = new FileOutputStream(destFile);
90 byte[] buf = new byte[8 * 1024];
91 int b = 0;
92 while ((b = fis.read(buf, 0, buf.length)) != -1) {
93 fos.write(buf, 0, b);
94 fos.flush();// 最好加上
95 }
96 fis.close();
97 fos.close();
98 }
99
100 /**
101 * 使用带缓冲区的字节流进行文件拷贝
102 *
103 * @param srcFile
104 * @param destFile
105 * @throws IOException
106 */
107 public static void copyFileByBuffer(File srcFile, File destFile) throws IOException {
108 if (!srcFile.exists())
109 throw new IllegalArgumentException("文件" + srcFile + "不存在!");
110 if (!srcFile.isFile())
111 throw new IllegalArgumentException(srcFile + "不是文件!");
112
113 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
114 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
115 int c = 0;
116 while ((c = bis.read()) != -1) {
117 bos.write(c);
118 bos.flush();// 刷新缓冲区
119 }
120 bis.close();
121 bos.close();
122 }
123
124 /**
125 * 单字节不带缓冲区拷贝文件
126 *
127 * @param srcFile
128 * @param destFile
129 * @throws IOException
130 */
131 public static void copyFileByByte(File srcFile, File destFile) throws IOException {
132 if (!srcFile.exists())
133 throw new IllegalArgumentException("文件" + srcFile + "不存在!");
134 if (!srcFile.isFile())
135 throw new IllegalArgumentException(srcFile + "不是文件!");
136 FileInputStream fis = new FileInputStream(srcFile);
137 FileOutputStream fos = new FileOutputStream(destFile);
138 int c = 0;
139 while ((c = fis.read()) != -1) {
140 fos.write(c);
141 fos.flush();// 刷新缓冲区
142 }
143 fis.close();
144 fos.close();
145 }
146
147 /**
148 * 带缓冲区批量拷贝文件
149 *
150 * @param srcFile
151 * @param destFile
152 * @throws IOException
153 */
154 public static void cloneFile(File srcFile, File destFile) throws IOException {
155 if (!srcFile.exists())
156 throw new IllegalArgumentException("文件" + srcFile + "不存在!");
157 if (!srcFile.isFile())
158 throw new IllegalArgumentException(srcFile + "不是文件!");
159 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
160 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
161 byte[] buf = new byte[8 * 1024];
162 int bytes = 0;
163 while ((bytes = bis.read(buf, 0, buf.length)) != -1) {
164 bos.write(buf, 0, bytes);
165 bos.flush();
166 }
167 bis.close();
168 bos.close();
169 }
170 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package me.io;
2
3 import java.io.FileOutputStream;
4 import java.io.IOException;
5
6 public class FileOutDemo {
7
8 public static void main(String[] args) throws IOException {
9 //若果文件不存在,则直接创建,如果文件存在,则删除后创建,如果要追加内容,则应该传入参数true
10 @SuppressWarnings("resource")
11 FileOutputStream fos = new FileOutputStream("demo/out.dat");
12
13 fos.write('A');//写入A的低八位
14 fos.write('B');
15
16 //写一个int,要写四次
17 int i = 0x7fffffff;
18 fos.write(i >>> 24);
19 fos.write(i >>> 16);
20 fos.write(i >>> 8);
21 fos.write(i);
22 IOUtils.printHex("demo/out.dat");
23 }
24 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package me.io;
2
3 import java.io.DataInputStream;
4 import java.io.FileInputStream;
5 import java.io.IOException;
6
7 public class DisDemo {
8
9 public static void main(String[] args) throws IOException {
10 String file = "demo/dos.dat";
11 DataInputStream dis = new DataInputStream(new FileInputStream(file));
12 System.out.println(dis.readInt());
13 System.out.println(dis.readInt());
14 System.out.println(dis.readDouble());
15 System.out.println(dis.readLong());
16 System.out.println(dis.readUTF());
17 System.out.println(dis.readChar());
18 }
19 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package me.io;
2
3 import java.io.DataOutputStream;
4 import java.io.FileOutputStream;
5 import java.io.IOException;
6
7 /**
8 * DataOutputStream测试类
9 * @author Administrator
10 *
11 */
12 public class DosDemo {
13
14 public static void main(String[] args) throws IOException {
15 String file = "demo/dos.dat";
16 DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
17 dos.writeInt(10);
18 dos.writeInt(-10);
19 dos.writeDouble(10.5);
20 dos.writeLong(10l);
21
22 //采用UTF-8编码写出:
23 dos.writeUTF("中国");//三个字节
24 //采用UTF-16be编码写出
25 dos.writeChars("中国");//两个字节
26 dos.close();
27 IOUtils.printHex("demo/dos.dat");
28 }
29 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package me.io;
2
3 import java.io.File;
4 import java.io.IOException;
5
6 public class IOUtilsMain {
7
8 public static void main(String[] args) throws IOException {
9 // IOUtils.printHex("src/me/io/IOUtils.java");
10 // IOUtils.printHexByByteArray("src/me/io/IOUtils.java");
11 long start = System.currentTimeMillis();
12 //IOUtils.copyFile(new File("demo/1.mp3"), new File("demo/4.mp3"));//58
13 //IOUtils.copyFileByBuffer(new File("demo/1.mp3"), new File("demo/2.mp3"));//26631毫秒
14 //IOUtils.copyFileByByte(new File("demo/1.mp3"), new File("demo/3.mp3"));//39722
15 IOUtils.cloneFile(new File("demo/1.mp3"), new File("demo/5.mp3"));//77
16 long end = System.currentTimeMillis();
17 System.out.println(end - start);//文件大小为3.2m
18 }
19 }
这里从main方法打印结果可以看出:我们在拷贝文件时,建议用字节批量读取,相对较快一点