字节流
字节流:
用RandomAccessFile对文件进行读写,速度太慢,所以需要用到I/O流,有一读写时以字符为单位还是字节为单位分为字符流,字节流,Java分别用不同的类实现这种读写的功能。
1) I/O -> InputStram OutputStream
InputStream抽象了应用程序读取数据的方式;OutputStream抽象了应用程序写出数据的方式。
EOF=End 读到-1就读到结尾 end of file
2)输入流基本方法
int b=inputStream.read();//读取一个字节无符号填充到int低方位
inputStream.read(byte[] buf);
inputStream.read(byte[] buf,int start,int size);
3)输出流基本方法
outputStram.write(int b)写一个byte到流b的低8位
outputStram.write(buf[] buf)
4)FileInputStream / FileOutputStream ; DataInputStream / DataOutputStream ; BufferedInputStream / BufferedOutputStream
对文件读写来说,FileInputStream FileOutputStream的单字节读写,批量读写,本质都是一个一个字节的写,而BufferedInputStream / BufferedOutputStream是FileInputStream / FileOutputStream的封装,我们看不到高速缓冲区如何工作,但我们能知道,先把文件一个字节一个字节读到缓冲区,再从缓冲区往外写,是个高速 高效的过程。
DataInputStream / DataOutputStream对流功能的扩展,可以更加方便的读取int long等类型数据。本质也是对FileInputStream / FileOutputStream的封装,写一个int依旧需要用4次,不过它都写在方法里了,直接调用writeInt()便可以了。
package com.zhao.byteStream; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class IOUtil { private IOUtil() { // TODO Auto-generated constructor stub } /** * 读取指定文件内容,按照16进制输出到控制台 并且每输出10个byte换行 单字节读取,不适合读取大文件,大文件效率很低 * * @param pathName:文件路径 * @throws Exception */ public static void printHex(String pathName) throws Exception { File file = new File(pathName); if (!file.exists()) { throw new Exception("输入的文件路径有误,找不到该文件"); } // 把文件作为字节流进行读操作 FileInputStream inputStream = new FileInputStream(file); int index = 0; int b; while ((b = inputStream.read()) != -1) { if (b <= 0xF) { // 单位数前面补0 System.out.print("0"); } // 将整型b转换成16进制表示的字符串 System.out.print(Integer.toHexString(b) + " "); index++; if ((index % 10 == 0) && index != 0) { System.out.println(); } } inputStream.close(); } /** * 批量读取,对大文件而言,效率高。常用的方式。 * * @param pathname * @throws Exception */ public static void printHexByByteArray(String pathname) throws Exception { File file = new File(pathname); if (!file.exists()) { file.createNewFile(); } FileInputStream inputStream = new FileInputStream(file); System.out.println("文件的长度是:" + file.length()); byte[] bs = new byte[20 * 1024]; /* * 从inputStream中批量读取字节,放入到这个字节数组中 从第0个位置开始放,最多放bs.length个, 返回的是读到的字节的个数。 */ inputStream.read(bs, 0, bs.length); // 一次性读完,说明字节数组足够大 for (int i = 0; i < bs.length; i++) { if (i % 10 == 0) { System.out.println(); } System.out.print(Integer.toHexString(bs[i] & 0xFF) + " "); } inputStream.close(); } /** * 拷贝文件 * @param srcFile * @param targetFile * @throws Exception */ public static void copyFile(File srcFile, File targetFile) throws Exception { if (!srcFile.exists()) { throw new IllegalArgumentException("文件:" + srcFile + "不存在"); } if (!srcFile.isFile()) { throw new IllegalArgumentException(srcFile + "不是文件"); } // 创建源文件srcFile的输入流 FileInputStream fileInputStream = new FileInputStream(srcFile); // 创建目标文件targetFile的输出流 FileOutputStream fileOutputStream = new FileOutputStream(targetFile); byte[] bytes = new byte[(int) srcFile.length()]; fileInputStream.read(bytes); fileOutputStream.write(bytes, 0, bytes.length); fileInputStream.close(); fileOutputStream.close(); String pathName = targetFile.getAbsolutePath(); printHexByByteArray(pathName); } /** * 进行文件的拷贝,利用带缓冲的字节流 * @param srcFile * @param targetFile * @throws Exception */ public static void copyFileByBuffer(File srcFile, File targetFile) throws Exception{ if (!srcFile.exists()) { throw new IllegalArgumentException("文件:" + srcFile + "不存在"); } if (!srcFile.isFile()) { throw new IllegalArgumentException(srcFile + "不是文件"); } BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream(srcFile)); BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(new FileOutputStream(targetFile)); int c; while((c=bufferedInputStream.read())!=-1){ bufferedOutputStream.write(c); bufferedOutputStream.flush();//刷新缓冲区 } bufferedInputStream.close(); bufferedOutputStream.close(); String pathName = targetFile.getAbsolutePath(); printHexByByteArray(pathName); } }