您的浏览器过于古老 & 陈旧。为了更好的访问体验, 请 升级你的浏览器
一纸荒年 发布于2019年11月21日 00:44 最近更新于 2019年11月21日 14:13

原创 RandomAccessFile使用

393 次浏览 读完需要≈ 12 分钟 Java

内容目录

作用:

随机流(RandomAccessFile)不属于IO流,支持对文件的读取和写入随机访问。

随机访问文件原理:

首先把随机访问的文件对象看作存储在文件系统中的一个大型 byte 数组,然后通过指向该 byte 数组的光标或索引(即:文件指针 FilePointer)在该数组任意位置读取或写入任意数据。

相关方法说明:

20190314222653937.png

可以看出:

这个类集中了丰富的读写方法

下面我举几个比较典型的方法来说明一下这个类的强大之处

============================================

1、seek:指定文件的光标位置,通俗点说就是指定你的光标位置

然后下次读文件数据的时候从该位置读取。

============================================

2、getFilePointer:我们注意到这是一个long类型的返回值,

字面意思就是返回当前的文件光标位置。

这样方便我们后面读取插入。

============================================

3、length:毫无疑问的方法,文件的长度,返回long类型。

注意它并不会受光标的影响。只会反应客观的文本长度。

============================================

4、read()、read(byte[] b)、read(byte[] b,int off,int len)

这些方法跟readstream中的方法一样,

例如最后一个:定义缓冲数组,从数组的off偏移量位置开始写,

读取转换为数组数据达到len个字节。

总之这是一个读文件内容的标准操作api。

============================================

5、readDouble() readFloat() readBoolean() readInt()

readLong() readShort() readByte() readChar()

这些方法都是去read每一个字符,个人感觉就是返回他们的ASCII码

当然如果专家们有异议可以指出,我测试的时候至少是这么感觉得。

大家也可以自己试一下。

比如readLong就是要求你的文本内容必须有八个字符,不然会报错。

伴随着也就是

writeDouble() writeFloat() writeBoolean() writeInt()

writeLong() writeShort() writeByte() writeChar()

============================================

6、readFully(byte[] b):

这个方法的作用就是将文本中的内容填满这个缓冲区b。

如果缓冲b不能被填满,那么读取流的过程将被阻塞,

如果发现是流的结尾,那么会抛出异常。

这个过程就比较像“凑齐一车人在发车,不然不走”。

============================================

7、getChannel:它返回的就是nio通信中的file的唯一channel

============================================

8、skipBytes(int n):跳过n字节的位置,相对于当前的point。

RandomAccessFileDemo:

/**
 * 读取任意文件的位置
 * 
 * @param path 路径
 * @param position 需要读取的位置
 */
public static void randomRead(String path, int position) {
	try {
		// 以只读的方式打开一个RandomAccessFile
		RandomAccessFile raf = new RandomAccessFile(path, "r");
		// 获取RandomAccessFile对象文件指针的位置,初始位置是0
		System.out.println("RandomAccessFile文件指针的初始位置:" + raf.getFilePointer());
		raf.seek(position);// 移动文件指针位置
		byte[] buff = new byte[1024];
		// 用于保存实际读取的字节数
		int hasRead = 0;
		// 循环读取
		while ((hasRead = raf.read(buff)) > 0) {
			// 打印读取的内容,并将字节转为字符串输入
			System.out.println(new String(buff, 0, hasRead));
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
}
/**
 * 追加数据
 */
public static void randomWrite(String path, String content) {
	try {
		// 以读写的方式建立一个RandomAccessFile对象
		RandomAccessFile raf = new RandomAccessFile(path, "rw");
		// 将记录指针移动到文件最后
		raf.seek(raf.length());
		raf.write(content.getBytes("UTF-8"));
	} catch (Exception e) {
		e.printStackTrace();
	}
}
/**
 * 任意位置插入数据
 * 
 * @param fileName 文件名
 * @param points 数据插入的位置
 * @param insertContent 插入的内容
 */
public static void randomInsert(String fileName, long points, String insertContent) {
	try {
		File tmp = File.createTempFile("tmp", null);
		tmp.deleteOnExit();// 在JVM退出时删除
		RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
		// 创建一个临时文件夹来保存插入点后的数据
		FileOutputStream tmpOut = new FileOutputStream(tmp);
		FileInputStream tmpIn = new FileInputStream(tmp);
		raf.seek(points);
		// 将插入点后的内容读入临时文件夹
		byte[] buff = new byte[1024];
		// 用于保存临时读取的字节数
		int hasRead = 0;
		// 循环读取插入点后的内容
		while ((hasRead = raf.read(buff)) > 0) {
			// 将读取的数据写入临时文件中
			tmpOut.write(buff, 0, hasRead);
		}
		// 插入需要指定添加的数据
		raf.seek(points);// 返回原来的插入处
		// 追加需要追加的内容
		raf.write(insertContent.getBytes("UTF-8"));
		// 最后追加临时文件中的内容
		while ((hasRead = tmpIn.read(buff)) > 0) {
			raf.write(buff, 0, hasRead);
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
}
public void test() {
	randomWrite("G:\\test.txt", "追加内容");		
	randomInsert("G:\\test.txt", 0, "@");
	randomRead("G:\\test.txt", 0);
}

以上例子并未关闭流,自行关闭,在Java7之前一般都是在finally中关闭流。

try {
} catch (IOException e) {
} finally {
    if (inputStream != null) {
        try {
            inputStream.close(); // 关闭流
        } catch (Exception e) {  
            e.printStackTrace();  
        } 
    }
}

在Java7中,关闭流这种繁琐的操作就不用我们自己写了,只要实现的自动关闭接口(Closeable)的类都可以在try结构体上定义,java会自动帮我们关闭,及时在发生异常的情况下也会。可以在try结构体上定义多个,用分号隔开即可;

try (OutputStream out = new FileOutputStream("");OutputStream out2 = new FileOutputStream("")){  
    // ...操作流代码  
} catch (Exception e) {  
    e.printStackTrace();  
}
  • CodePlayer技术交流群1
  • CodePlayer技术交流群2

0 条评论

撰写评论