功能
想比较之前的流要么读要么写,RandomAccessFile提供了读写
操作RandomAccessFile声明在java.io包下,但直接继承于java.lang.Object类。并且它实现了Datalnput、DataOutput两个接口
看源码
public class RandomAccessFile implements DataOutput, DataInput, Closeable
构造函数
public RandomAccessFile(String name, String mode)
public RandomAccessFile(File file, String mode)
3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建 如果写出到的文件存在,则会对原有文件内容进行覆盖。(默认情况下,从头覆盖)
public static void main(String[] args) {
RandomAccessFile raf1 = null;
RandomAccessFile raf2 = null;
try {
raf1 = new RandomAccessFile(new File("D:\\IO\\hao.jpg"), "r");
raf2 = new RandomAccessFile(new File("D:\\IO\\a.jpg"), "rw");
byte[] buffer = new byte[1024];
int len;
while ((len = raf1.read(buffer)) != -1) {
raf2.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (raf1 != null) {
try {
raf1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (raf2 != null) {
try {
raf2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
主要是第二个参数:指定访问模式,有哦4种模式
r:以只读的模式打开,如果调用write方法将会抛出IO异常
rw:以读和写的模式打开
rws:以读和写的模式打开,要求对”文件的内容“和”元数据“的每个更新都同步到存储设备
rwd:以读和写的模式打开,要求对”文件的内容“的每个更新都同步到存储设备
特殊方法
long getFilePointer() //返回文件记录中指针的当前位置
void seek(long pos) //将文件记录移动到指定的pos文件
练习1:
@Test
public void test2() throws Exception {
RandomAccessFile raf1 = new RandomAccessFile("hello1.txt", "rw");
raf1.seek(3);//将指针跳到角标为3的位置
raf1.write("aaa".getBytes());//xyzaaa
System.out.println(raf1.getFilePointer());//6
raf1.close();
}
练习2:
使用RandomAccessFile实现数据的插入效果
- xyz…fggggrtb …为要插入的位置
例如:插入aaa
结果为xyzaaafggggrtb
@Test
public void Test3 () throws Exception {
RandomAccessFile raf3 = new RandomAccessFile("hello.txt", "rw");
raf3.seek(3);//将指针跳到角标为3的位置从1开始
//StringBuilder替代字符串拼接,长度大于16了要扩容
//为了避免扩容,我们直接使用要拼接字符串长度
StringBuilder builder = new StringBuilder((int)new File("hello.txt").length()); //保存指针3后面的所有数据到 StringBuilder中
//StringBuilder替代字符串拼接,长度大于16了要扩容
//为了避免扩容,我们直接使用要拼接字符串长度
byte[] buffer = new byte[20];
int len;
while ((len = raf3.read(buffer))!=-1){
builder.append(new String(buffer,0,len));
}
//跳回
raf3.seek(3);
raf3.write("xyz".getBytes());
//将StringBuilder中的数据写入到文件中
raf3.write(builder.toString().getBytes());
}
来看看另一种插入数据的方法
/**
* 完成数据内容的插入
* @param path 文件路径
* @param index 指定数据插入位置
* @param cont 插入的内容
*/
public class Test4 {
public static void main(String[] args) {
insertContent("D:\\IO\\b.txt",3,"123");
}
/*
* 1、校验参数的合法性
2、将指针移动到插入的位置
3、通过流读取出来写到磁盘文件上(开辟读和写的流)
4、将指针重新指定到插入位置
5、将写入的内容write写入
6、将后续内存重新写入该文件
*
*
* */
public static void insertContent(String path,int index,String cont) {
File file = new File(path);
if(!file.exists()){
return;
}
if(index<0){
return;
}
FileInputStream tmppis = null;
FileOutputStream tmpos1 = null;
RandomAccessFile randomAccessFile =null;
File tmpfile = new File(file.getParent()+file.separator+"temp.txt");
try {
//写入临时文件
tmpos1 = new FileOutputStream(tmpfile);
//读取临时文件
tmppis = new FileInputStream(tmpfile);
//打开目标文件
randomAccessFile = new RandomAccessFile(file, "rw");
//指定要插入文件位置
randomAccessFile.seek(index);
//把该位置文件读取出来
byte[] bytes = new byte[100];
int len;
while ((len= randomAccessFile.read(bytes))!=-1){
//写入临时文件
tmpos1.write(bytes,0,len);
}
tmpos1.flush();
//将指针移动到指定位置
randomAccessFile.seek(index);
randomAccessFile.write(cont.getBytes());
//将临时文件内容重写写入原文件
while ((len=tmppis.read(bytes))!=-1){
randomAccessFile.write(bytes,0,len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (tmppis != null){
try {
tmppis.close();
} catch (IOException e) {
e.printStackTrace();
}
if(tmpos1 !=null){
try {
tmpos1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}if(randomAccessFile != null){
try {
randomAccessFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
new String源码:
功能:把byte类型的数组,转码为String
public String(byte bytes[], int offset, int length) {
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(bytes, offset, length);
}
String 的getBytes源码:
得到一个操作系统默认的编码格式的字节数组。
这表示在不同的操作系统下,返回的东西不一样
https://blog.csdn.net/ljheee/article/details/51476125?
public byte[] getBytes() {
return StringCoding.encode(value, 0, value.length);
}