Java IO之字节流

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 }
IOUtils.java
 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 }
FileOutputStream
 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 }
DataInputStream
 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 }
DataOutputStream
 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方法

这里从main方法打印结果可以看出:我们在拷贝文件时,建议用字节批量读取,相对较快一点

原文地址:https://www.cnblogs.com/albertrui/p/8361643.html