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 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 }
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 }
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 }
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 }
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方法打印结果可以看出:我们在拷贝文件时,建议用字节批量读取,相对较快一点