任务:练习Java读取二进制文件,读取文件的前64和最后64个字节。
推荐一个十六进制在线编辑器:HexEd.it - Browser-based Online and Offline Hex Ed...https://hexed.it/ 可用来核对自己输出的与文件内容是否一致。
FileWriter只能接受字符串形式的参数,也就是说只能把内容存到文本文件。相对于文本文
件,采用二进制格式的文件存储更省空间
InputStream
InputStream用于按字节从输入流读取数据。其中的int read()方法读取一个字节,这个字节
以整数形式返回0到255之间的一个值。为什么读一个字节,而不直接返回一个byte类型的值?
因为byte类型最高位是符号位,它所能表示的最大的正整数是127。
InputStream只是一个抽象类,不能实例化。FilelnputStream是InputStream的子类,用于从
文件中按字节读取。
read方法
read方法一共有三种重载方式
int read()
int read(byte b[])
int read(byte b[], int off, int len)
这三种重载方式都符合一下两条结论:
read方法每读一次就会使文件指针向后移动一个字节或者N个字节(N=读取到的数组字节数<=指定的字节数组长度)
如果文件指针到文件末尾,就返回-1,否者返回读取字节的长度
RandomAccessFile
RandomAccessFile实现了大部分文件输入输出流的方法,但是底层实现中他实现的是DataInput和DataOutput接口,并非是FileInputStream和FileOutputStream。RandomAccessFile使用很多native方法实现了对文件的操作,并且很多native方法跟inputstream都有重叠,比如read0方法。
r:以只读的模式打开,如果调用write方法将会抛出IO异常
rw:以读和写的模式打开
rws:以读和写的模式打开,要求对”文件的内容“和”元数据“的每个更新都同步到存储设备
rwd:以读和写的模式打开,要求对”文件的内容“的每个更新都同步到存储设备
long getFilePointer() //返回文件记录中指针的当前位置
void seek(long pos) //将文件记录移动到指定的pos文件
实现代码:
import java.io.*;
public class day2 {
public static void main(String[] args) throws IOException{
String filePath = "src/picture/day1.png";
File file = new File (filePath);
file.setReadable(true);
System.out.println(file.canRead());
RandomAccessFile fis = null;
try {
fis =new RandomAccessFile(filePath,"rw");
//用字节数组,减少了内存和硬盘的交互,提高了运行效率,一次最多读取bytes.length个字节
byte[] bytes = new byte[64];
fis.read(bytes);
print(bytes);
fis.seek(file.length()-64);//将文件指针定位到末尾
fis.read(bytes);
print(bytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fis !=null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void print(byte[] bytes)
{
for (int i = 0; i < bytes.length; i++) {
System.out.printf("%02X ",bytes[i]);
if((i+1)%8==0) System.out.print("\n");
}
System.out.println("-----------------");
}
}
遇到的问题
问题:一直读取不到文件。
解决:直接复制文件的路径,不要手打。(玄学问题)