Java IO体系之RandomAccessFile浅析
Java IO体系之RandomAccessFile浅析
一、RandomAccessFile综述:
1.1RandomAccessFile简介
RandomAccessFile是java Io体系中功能最丰富的文件内容访问类。即可以读取文件内容,也可以向文件中写入内容。
RandomAccessFile的唯一父类是Object,与其他流父类不同。是用来访问那些保存数据记录的文件的,这样你就可以用seek( )方法来访问记录,并进行读写了。这些记录的大小不必相同;但是其大小和位置必须是可知的。
由于RandomAccessFile可以自由访问文件的任意位置,所以如果我们希望只访问文件的部分内容,RandomAccessFile将是更好的选择。
与OutputStearm,Writer等输出流不同的是,RandomAccessFile类允许自由定位文件记录指针,程序可以直接跳到文件的任意位置来读写数据,所以RandomAccessFile可以不从文件开始的地方进行输出,如果需要向已存在的文件后追加内容。则可以使用RandomAccessFile。
这个类在很多资料上翻译成中文都是:随机访问文件,在中文里,随机是具有不确定的含义,指一会访问这里,一会访问那里的意思。如果以这种语义来解释的话,就会感到很困惑。其实,Random在英文中不仅仅有随机,还有任意的意思。如果中文名为任意访问文件是不是就会更好的理解。任意表示我们可以指定文件中任何一个位置去操作一个文件。
1.2、RandomAccessFile数据结构
这个是JDK上的截图,我们可以看到它的父类是Object,没有继承字节流、字符流家族中任何一个类。实际上,除了实现DataInput和DataOutput接口之外(DataInputStream和DataOutputStream也实现了这两个接口,意味着这个类即可以读也可以写),它和字节流、字符流类系毫不相干,甚至都没有用InputStream和OutputStream已经准备好的功能;它是一个完全独立的类,所有方法(绝大多数都只属于它自己)都是从零开始写的。这可能是因为RandomAccessFile能在文件里面前后移动,所以它的行为与其它的I/O类有些根本性的不同。总而言之,它是一个直接继承Object的,独立的类。
1.3.RandomAccessFile的整体介绍
RandomAccessFile类包含了一个记录指针,用以标识当前读写处的位置,当程序新创建一个RandomAccessFile对象时,该对象的文件记录指针位于文件头(也就是0处),当读/写了n个字节后,文件记录指针将会向后移动n个字节。除此之外,RandomAccessFile可以自由的移动记录指针,即可以向前移动,也可以向后移动。RandomAccessFile包含了以下两个方法来操作文件的记录指针:RandomAccessFile即可以读文件,也可以写,所以它即包含了完全类似于InputStream的3个read()方法,其用法和InputStream的3个read()方法完全一样;也包含了完全类似于OutputStream的3个write()方法,其用法和OutputStream的3个Writer()方法完全一样。除此之外,RandomAccessFile还包含了一系类的readXXX()和writeXXX()方法来完成输入和输出。
- long getFilePointer(); 返回文件记录指针的当前位置
- void seek(long pos); 将文件记录指针定位到pos位置
RandomAccessFile有两个构造器,其实这两个构造器基本相同,只是指定文件的形式不同而已,一个使用String参数来指定文件名,一个使用File参数来指定文件本身。除此之外,创建RandomAccessFile对象还需要指定一个mode参数。该参数指定RandomAccessFile的访问模式,有以下4个值:
“r” 以只读方式来打开指定文件夹。如果试图对该RandomAccessFile执行写入方法,都将抛出IOException异常。
“rw” 以读,写方式打开指定文件。如果该文件尚不存在,则试图创建该文件。
“rws” 以读,写方式打开指定文件。相对于”rw” 模式,还要求对文件内容或元数据的每个更新都同步写入到底层设备。
“rwd” 以读,写方式打开指定文件。相对于”rw” 模式,还要求对文件内容每个更新都同步写入到底层设备。
1.4工作方式
- 基本上,RandomAccessFile的工作方式是,把DataInputStream和DataOutputStream粘起来,再加上它自己的一些方法,比如定位用的getFilePointer( ),在文件里移动用的seek( ),以及判断文件大小的length( )。此外,它的构造函数还要一个表示以只读方式("r"),还是以读写方式("rw")打开文件的参数 (和C的fopen( )一模一样)。它不支持只写文件,从这一点上看,假如RandomAccessFile继承了DataInputStream,它也许会干得更好。
- 只有RandomAccessFile才有seek方法,而这个方法也只适用于文件。BufferedInputStream有一个mark( )方法,你可以用它来设定标记(把结果保存在一个内部变量里),然后再调用reset( )返回这个位置,但是它的功能太弱了,而且也不怎么实用。
- RandomAccessFile的绝大多数功能,如果不是全部的话,已经被JDK1.4的nio的"内存映射文件(memory-mapped files)"给取代了。
二、RandomAccessFile方法摘要:
构造方法摘要 | |
---|---|
RandomAccessFile(File file, String mode) 创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。 |
|
RandomAccessFile(String name, String mode) 创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。 |
方法摘要 | |
---|---|
void |
close() 关闭此随机访问文件流并释放与该流关联的所有系统资源。 |
FileChannel |
getChannel() 返回与此文件关联的唯一 FileChannel 对象。 |
FileDescriptor |
getFD() 返回与此流关联的不透明文件描述符对象。 |
long |
getFilePointer() 返回此文件中的当前偏移量。 |
long |
length() 返回此文件的长度。 |
int |
read() 从此文件中读取一个数据字节。 |
int |
read(byte[] b) 将最多 b.length 个数据字节从此文件读入 byte 数组。 |
int |
read(byte[] b, 将最多 len 个数据字节从此文件读入 byte数组。 |
boolean |
readBoolean() 从此文件读取一个 boolean 。 |
byte |
readByte() 从此文件读取一个有符号的八位值。 |
char |
readChar() 从此文件读取一个字符。 |
double |
readDouble() 从此文件读取一个 double 。 |
float |
readFloat() 从此文件读取一个 float 。 |
void |
readFully(byte[] b) 将 b.length 个字节从此文件读入 byte 数组,并从当前文件指针开始。 |
void |
readFully(byte[] b, 将正好 len 个字节从此文件读入 byte数组,并从当前文件指针开始。 |
int |
readInt() 从此文件读取一个有符号的 32 位整数。 |
String |
readLine() 从此文件读取文本的下一行。 |
long |
readLong() 从此文件读取一个有符号的 64 位整数。 |
short |
readShort() 从此文件读取一个有符号的 16 位数。 |
int |
readUnsignedByte() 从此文件读取一个无符号的八位数。 |
int |
readUnsignedShort() 从此文件读取一个无符号的 16 位数。 |
String |
readUTF() 从此文件读取一个字符串。 |
void |
seek(long pos) 设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。 |
void |
setLength(long newLength) 设置此文件的长度。 |
int |
skipBytes(int n) 尝试跳过输入的 n 个字节以丢弃跳过的字节。 |
void |
write(byte[] b) 将 b.length 个字节从指定 byte 数组写入到此文件,并从当前文件指针开始。 |
void |
write(byte[] b, 将 len 个字节从指定 byte数组写入到此文件,并从偏移量 off 处开始。 |
void |
write(int b) 向此文件写入指定的字节。 |
void |
writeBoolean(boolean v) 按单字节值将 boolean 写入该文件。 |
void |
writeByte(int v) 按单字节值将 byte 写入该文件。 |
void |
writeBytes(String s) 按字节序列将该字符串写入该文件。 |
void |
writeChar(int v) 按双字节值将 char 写入该文件,先写高字节。 |
void |
writeChars(String s) 按字符序列将一个字符串写入该文件。 |
void |
writeDouble(double v) 使用 Double 类中的 doubleToLongBits 方法将双精度参数转换为一个 long ,然后按八字节数量将该 long 值写入该文件,先定高字节。 |
void |
writeFloat(float v) 使用 Float 类中的 floatToIntBits 方法将浮点参数转换为一个int ,然后按四字节数量将该 int 值写入该文件,先写高字节。 |
void |
writeInt(int v) 按四个字节将 int 写入该文件,先写高字节。 |
void |
writeLong(long v) 按八个字节将 long 写入该文件,先写高字节。 |
void |
writeShort(int v) 按两个字节将 short 写入该文件,先写高字节。 |
void |
writeUTF(String str) 使用 modified UTF-8 编码以与机器无关的方式将一个字符串写入该文件。 |
三、实例分析
1 package me.io.raffile;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.RandomAccessFile;
6 import java.util.Arrays;
7
8 public class RafDemo {
9
10 public static void main(String[] args) throws IOException {
11 File demo = new File("demo");
12 if(!demo.exists())
13 demo.mkdir();
14 File file = new File(demo, "raf.dat");
15 if (!file.exists())
16 file.createNewFile();
17 RandomAccessFile raf = new RandomAccessFile(file, "rw");
18 //指针的位置
19 System.out.println(raf.getFilePointer());
20 raf.write('A');//只写了一个字节
21 System.out.println(raf.getFilePointer());
22
23 raf.write('B');
24 System.out.println(raf.getFilePointer());
25
26 //Java中最大的整数
27 int i = 0x7fffffff;
28
29 //占四个字节,如果要把i写进去,就得写四次
30 raf.write(i >>> 24);//高八位
31 raf.write(i >>> 16);
32 raf.write(i >>> 8);
33 raf.write(i);
34
35 //可以直接写一个int
36 raf.writeInt(i);
37
38 String string = "中";
39 byte[] bytes = string.getBytes();
40 raf.write(bytes);
41 System.out.println(raf.length());
42
43 //读文件,必须把指针移到头部
44 raf.seek(0);
45 //一次性读取,把文件中的内容都堵到字节数组
46 byte[] buf = new byte[(int) raf.length()];
47 raf.read(buf);
48 System.out.println(Arrays.toString(buf));
49 for (byte b : buf) {
50 System.out.print(Integer.toHexString(b & 0xff) + " ");
51 }
52 raf.close();
53 }
54 }
三、专题总结(FIle与RandomAccessFile)
注:这里File类的介绍可参见我的上一篇博文
java.io.File类用于表示文件(目录)
File类只用于表示文件(目录)的信息(名称、大小等),不能用于文件内容的访问
RandomAccessFile java提供的对文件内容的访问,既可以读文件,也可以写文件。
RandomAccessFile支持随机访问文件,可以访问文件的任意位置
(1)java文件模型
在硬盘上的文件是byte byte byte存储的,是数据的集合
(2)打开文件
有两种模式"rw"(读写) "r"(只读)
RandomAccessFile raf = new RandomeAccessFile(file,"rw")
文件指针,打开文件时指针在开头 pointer = 0;
(3) 写方法
raf.write(int)--->只写一个字节(后8位),同时指针指向下一个位置,准备再次写入
(4)读方法
int b = raf.read()--->读一个字节
(5)文件读写完成以后一定要关闭(Oracle官方说明)
参考文章:
http://blog.csdn.net/nightcurtis/article/details/51384126
https://www.cnblogs.com/dongguacai/p/5699444.html
Java IO体系之RandomAccessFile浅析的更多相关文章
- Java IO体系之File类浅析
Java IO体系之File类浅析 一.File类介绍 位于java.io下的Java File类以抽象的方式代表文件名和目录路径名.该类主要用于文件和目录的创建.文件的查找和文件的删除等.File对 ...
- JAVA基础知识之IO——Java IO体系及常用类
Java IO体系 个人觉得可以用"字节流操作类和字符流操作类组成了Java IO体系"来高度概括Java IO体系. 借用几张网络图片来说明(图片来自 http://blog.c ...
- Java IO体系综述
Java IO体系综述 一.流的概念 在Java API中,可以从其中读入一个字节序列的对象称作输入流,而可以向其中写入一个字节序列的对象称作输出流.这些字节序列的来源地和目的地可以是文件,而且通常都 ...
- 高效IO之Java IO体系(一)
更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 个人觉得可以用“字节流操作类和字符流操作类组成了Java IO体系”来高度概括J ...
- 【Java IO流】RandomAccessFile类的使用
RandomAccessFile类的使用 RandomAccessFile类是java提供的对文件内容的访问,既可以读文件,也可以写文件. 支持随机访问文件,可以访问文件的任意位置. RandomAc ...
- JAVA IO 体系
一.体系结构
- Java IO的RandomAccessFile的使用(转)
现有如下的一个需求,向已存在1G数据的txt文本里末尾追加一行文字,内容如下“Lucene是一款非常优秀的全文检索库”.可能大多数朋友会觉得这个需求很easy,说实话,确实easy,然后XXX君开始实 ...
- 关于Java IO与NIO知识都在这里
由于内容比较多,我下面放的一部分是我更新在我的微信公众号上的链接,微信排版比较好看,更加利于阅读.每一篇文章下面我都把文章的主要内容给列出来了,便于大家学习与回顾. Java面试通关手册(Java学习 ...
- Java 基础之详解 Java IO
Java IO基本概念 Java IO:即Java输入/输出系统,区分Java的输入和输出:把自己当成程序, 当你从外边读数据到自己这里就用输入(InputStream/Reader), 向外边写数据 ...
随机推荐
- 0004. 寻找两个有序数组的中位数(Java)
4. 寻找两个有序数组的中位数 https://leetcode-cn.com/problems/median-of-two-sorted-arrays/ 最简单的就是用最简单的,把两个数组分别抽出然 ...
- LinkedHashMap的特殊之处
一.前言 乍眼一看会怀疑或者问LinkedHashMap与HashMap有什么区别? 它有什么与众不同之处? 由于前面已经有两篇文章分析了HashMap,今天就看看LinkedHashMap.(基于 ...
- 【Android】Field requires API level 4 (current min is 1): android.os.Build.VERSION#SDK_INT
刚遇到了这个问题: Field requires API level 4 (current min is 1): android.os.Build.VERSION#SDK_INT 解决方法: 修改 A ...
- Linux系统下增加LV(逻辑卷)容量 、Linux系统下减少LV(逻辑卷)容量
查看文件系统现有lv_test容量,总计4.9G,已使用3% 命令 df -h 查看现有磁盘情况,我们发现磁盘sdb共有1305个柱面,每个柱面大小是8225280 bytes (大约8M).有一 ...
- JAVA并发编程之倒计数器CountDownLatch
CountDownLatch 的使用场景:在主线程中开启多线程去并行执行任务,并且主线程需要等待所有子线程执行完毕后汇总返回结果. 我把源码中的英文注释全部删除,写上自己的注释.就剩下 70 行不到的 ...
- 基于vue2.0搭建项目流程
搭建vue2.0项目--myproject 一. 环境搭建: 1 打开命令行(cmd) 2 安装node node官网 3 安装 vue-cli步骤如下: npm install -g vue-cli ...
- 邮件服务配置(虚拟域&虚拟用户)
邮件服务配置(虚拟域&虚拟用户) 现在我做的是: Linux + httpd + php + mariadb + postfix + dovecot + phpMyAdmin + postfi ...
- 以太坊RLPx传输协议
本文主要内容翻译自:The RLPx Transport Protocol,其中添加了一些个人的理解,由于密码学水平有限,不正确之处望指正.另外原文可能已经更新,最新内容请直接阅读原文. 本文档定义了 ...
- Unity经典游戏教程之:贪吃蛇
版权声明: 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客&qu ...
- JDK1.8源码分析03之idea搭建源码阅读环境
序言:上一节说了阅读源码的顺序,有了一个大体的方向,咱们就知道该如何下手.接下来,就要搭建一个方便阅读源码及debug的环境.有助于跟踪源码的调用情况. 目前新开发的项目, 大多数都是基于JDK1.8 ...