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)
二、实例分析:
这里我们就基于字节流写个工具类分析分析吧
1 packageme.io;2
3 importjava.io.BufferedInputStream;4 importjava.io.BufferedOutputStream;5 importjava.io.File;6 importjava.io.FileInputStream;7 importjava.io.FileOutputStream;8 importjava.io.IOException;9
10 public classIOUtils {11
12 /**
13 * 读取指定文件内容,按照16进制输出到控制台 并且每输出10个byte换行14 *15 *@paramfileName16 *@throwsIOException17 */
18 public static void printHex(String fileName) throwsIOException {19 //把文件作为字节流进行读操作
20 FileInputStream fis = newFileInputStream(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 *@paramfileName40 *@throwsIOException41 */
42 public static void printHexByByteArray(String fileName) throwsIOException {43 FileInputStream fis = newFileInputStream(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 *@paramsrcFile80 *@paramdestFile81 *@throwsIOException82 */
83 public static void copyFile(File srcFile, File destFile) throwsIOException {84 if (!srcFile.exists())85 throw new IllegalArgumentException("文件" + srcFile + "不存在!");86 if (!srcFile.isFile())87 throw new IllegalArgumentException(srcFile + "不是文件!");88 FileInputStream fis = newFileInputStream(srcFile);89 FileOutputStream fos = newFileOutputStream(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 *@paramsrcFile104 *@paramdestFile105 *@throwsIOException106 */
107 public static void copyFileByBuffer(File srcFile, File destFile) throwsIOException {108 if (!srcFile.exists())109 throw new IllegalArgumentException("文件" + srcFile + "不存在!");110 if (!srcFile.isFile())111 throw new IllegalArgumentException(srcFile + "不是文件!");112
113 BufferedInputStream bis = new BufferedInputStream(newFileInputStream(srcFile));114 BufferedOutputStream bos = new BufferedOutputStream(newFileOutputStream(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 *@paramsrcFile128 *@paramdestFile129 *@throwsIOException130 */
131 public static void copyFileByByte(File srcFile, File destFile) throwsIOException {132 if (!srcFile.exists())133 throw new IllegalArgumentException("文件" + srcFile + "不存在!");134 if (!srcFile.isFile())135 throw new IllegalArgumentException(srcFile + "不是文件!");136 FileInputStream fis = newFileInputStream(srcFile);137 FileOutputStream fos = newFileOutputStream(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 *@paramsrcFile151 *@paramdestFile152 *@throwsIOException153 */
154 public static void cloneFile(File srcFile, File destFile) throwsIOException {155 if (!srcFile.exists())156 throw new IllegalArgumentException("文件" + srcFile + "不存在!");157 if (!srcFile.isFile())158 throw new IllegalArgumentException(srcFile + "不是文件!");159 BufferedInputStream bis = new BufferedInputStream(newFileInputStream(srcFile));160 BufferedOutputStream bos = new BufferedOutputStream(newFileOutputStream(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 }
IOUtils.java
1 packageme.io;2
3 importjava.io.FileOutputStream;4 importjava.io.IOException;5
6 public classFileOutDemo {7
8 public static void main(String[] args) throwsIOException {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 }
FileOutputStream
1 packageme.io;2
3 importjava.io.DataInputStream;4 importjava.io.FileInputStream;5 importjava.io.IOException;6
7 public classDisDemo {8
9 public static void main(String[] args) throwsIOException {10 String file = "demo/dos.dat";11 DataInputStream dis = new DataInputStream(newFileInputStream(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 }
DataInputStream
1 packageme.io;2
3 importjava.io.DataOutputStream;4 importjava.io.FileOutputStream;5 importjava.io.IOException;6
7 /**
8 * DataOutputStream测试类9 *@authorAdministrator10 *11 */
12 public classDosDemo {13
14 public static void main(String[] args) throwsIOException {15 String file = "demo/dos.dat";16 DataOutputStream dos = new DataOutputStream(newFileOutputStream(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 }
DataOutputStream
1 packageme.io;2
3 importjava.io.File;4 importjava.io.IOException;5
6 public classIOUtilsMain {7
8 public static void main(String[] args) throwsIOException {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"));//5813 //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方法
这里从main方法打印结果可以看出:我们在拷贝文件时,建议用字节批量读取,相对较快一点