深入理解JAVA I/O系列四:RandomAccessFile
一、简述
这个是JDK上的截图,我们可以看到它的父类是Object,没有继承字节流、字符流家族中任何一个类。并且它实现了DataInput、DataOutput这两个接口,也就意味着这个类既可以读也可以写。
二、存在的意义
1、是JAVA I/O流体系中功能最丰富的文件内容访问类,它提供了众多方法来访问文件内容。
2、由于可以自由访问文件的任意位置,所以如果需要访问文件的部分内容,RandomAccessFile将是更好的选择。
3、可以用来访问保存数据记录的文件,文件的记录的大小不必相同,但是其大小和位置必须是可知的。
这个类在很多资料上翻译成中文都是:随机访问文件,在中文里,随机是具有不确定的含义,指一会访问这里,一会访问那里的意思。如果以这种语义来解释的话,就会感到很困惑。其实,Random在英文中不仅仅有随机,还有任意的意思。如果中文名为任意访问文件是不是就会更好的理解。任意表示我们可以指定文件中任何一个位置去操作一个文件。
三、DEMO演示
(1)、写入文件
public class RandomAccessFileTest
{
public static void main(String[] args) throws IOException
{
RandomAccessFile raf = new RandomAccessFile("d:/data.txt","rw");
Person p = new Person(1001,"xiaoming",1.80d);
p.write(raf);
}
}
class Person
{
int id;
String name;
double height;
public Person()
{
}
public Person(int id, String name, double height)
{
this.id = id;
this.name = name;
this.height = height;
} public void write(RandomAccessFile raf) throws IOException
{
raf.write(id);
raf.writeUTF(name);
raf.writeDouble(height);
}
}
执行结果:
1、执行结果乱码是由于写入的是二进制文件,这个待会我们再使用程序读取。(这个跟前面介绍的DataInputStream、DataOutputStream类似)
2、第五行中,RandomAccessFile的构造函数除了指定了要写入了文件,还有另外一个参数:mod,主要用来指定打开文件的访问模式。
3、读取的方式就是读取基本数据类型,其中第28行使用的方法是:writeUTF(String str)
使用 modified UTF-8 编码以与机器无关的方式将一个字符串写入该文件,这个方法就是将字符串写入文件,而且不用担心会出现乱码,因为使用的编码方式是UTF-8
(2)、文件读取
由于刚才写入的是二进制文件,现在使用程序去读取文件:
public class RandomAccessFileTest
{
public static void main(String[] args) throws IOException
{
RandomAccessFile raf = new RandomAccessFile("d:/data.txt", "rw");
Person p = new Person(1001, "xiaoming", 1.80d);
p.write(raf);// 写入文件后,任意访问文件的指针在文件的结尾 raf.seek(0);// 读取时,将指针重置到文件的开始位置。
Person p2 = new Person();
p2.read(raf);
System.out.println("id=" + p2.getId() + ";name=" + p2.getName()
+ ";height=" + p2.getHeight()); }
}
class Person
{
int id;
String name;
double height;
public Person()
{
}
public Person(int id, String name, double height)
{
this.id = id;
this.name = name;
this.height = height;
} public void write(RandomAccessFile raf) throws IOException
{
raf.writeInt(id);
raf.writeUTF(name);
raf.writeDouble(height);
} public void read(RandomAccessFile raf) throws IOException
{
this.id = raf.readInt();
this.name = raf.readUTF();
this.height = raf.readDouble();
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public double getHeight()
{
return height;
}
public void setHeight(double height)
{
this.height = height;
} }
执行结果:
id=1001;name=xiaoming;height=1.8
1、在39-43行代码中,由于是按基本数据类型写入和读取,所以在读取的时候一定严格按照写入的顺序。
2、第9行的位置上,由于在写入的时候,导致访问的指针的位置在文件的结尾处,现在读取的时候,需要将访问指针的位置重置到文件开头处。
(3)、追加内容
public static void main(String[] args) throws IOException
{
RandomAccessFile raf = new RandomAccessFile("D:/out.txt","rw");
raf.seek(raf.length());
raf.write("\r\n中国移动阅读基地".getBytes());
}
执行结果:
1、这段程序演示了在文件原有内容的基础上去追加内容。其中seek方法就是将访问指针移动到文件内容的末尾。
2、RandomAccessFile依然只能追加,不能像文件的指定位置插入内容。如果强制将文件记录指针移动到中间位置后开始输出内容,则新的内容会覆盖文件中原有的内容。
3、如果需要向文件指定的位置插入内容,程序需要先把插入点后面的内容读入缓冲区,等插入完成后,再讲缓冲区的内容追加到文件的后面。
(4)、指定位置插入
public static void main(String[] args)
{
try
{
insert("d:/out.txt",5,"插入的内容");
}
catch (IOException e)
{
e.printStackTrace();
}
} private static void insert(String fileName,long pos,String content) throws IOException
{
//创建临时空文件
File tempFile = File.createTempFile("temp",null);
//在虚拟机终止时,请求删除此抽象路径名表示的文件或目录
tempFile.deleteOnExit();
FileOutputStream fos = new FileOutputStream(tempFile); RandomAccessFile raf = new RandomAccessFile(fileName,"rw");
raf.seek(pos);
byte[] buffer = new byte[4];
int num = 0;
while(-1 != (num = raf.read(buffer)))
{
fos.write(buffer,0,num);
}
raf.seek(pos);
raf.write(content.getBytes());
FileInputStream fis = new FileInputStream(tempFile);
while(-1 != (num = fis.read(buffer)))
{
raf.write(buffer,0,num);
}
}
执行结果:
1、这里插入内容的原理就是:先把插入点后面的内容读入缓冲区,等插入完成后,再讲缓冲区的内容追加到文件的后面。
深入理解JAVA I/O系列四:RandomAccessFile的更多相关文章
- 深入理解java内存模型系列文章
转载关于java内存模型的系列文章,写的非常好. 深入理解java内存模型(一)--基础 深入理解java内存模型(二)--重排序 深入理解java内存模型(三)--顺序一致性 深入理解java内存模 ...
- java基础解析系列(四)---LinkedHashMap的原理及LRU算法的实现
java基础解析系列(四)---LinkedHashMap的原理及LRU算法的实现 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析 ...
- 《深入理解Java虚拟机》(四)虚拟机性能监控与故障处理工具
虚拟机性能监控与故障处理工具 详解 4.1 概述 本文参考的是周志明的 <深入理解Java虚拟机> 第四章 ,为了整理思路,简单记录一下,方便后期查阅. JDK本身提供了很多方便的JVM性 ...
- 深入理解JAVA I/O系列一:File
I/O简介 I/O问题可以说是当今web应用中所面临的的主要问题之一,大部分的web应用系统的瓶颈都是I/O瓶颈.这个系列主要介绍JAVA的I/O类库基本架构.磁盘I/O工作机制.网络I/O工作机制以 ...
- Java新知识系列 四
[]URL的组成<协议>://<主机>:<端口>/<路径> . []线程的定义实例化和启动. []类的final变量初始化需要满足的条件. []管道通信 ...
- 深入理解JAVA I/O系列二:字节流详解
流的概念 JAVA程序通过流来完成输入/输出.流是生产或消费信息的抽象,流通过JAVA的输入输出与物理设备链接,尽管与它们链接的物理设备不尽相同,所有流的行为具有相同的方式.这样就意味一个输入流能够抽 ...
- 深入理解JAVA I/O系列六:Linux中的IO模型
IO模型 linux系统IO分为内核准备数据和将数据从内核拷贝到用户空间两个阶段. 这张图大致描述了数据从外部磁盘向运行中程序的内存中移动的过程. 用户空间.内核空间 现在操作系统都是采用虚拟存储器, ...
- 深入理解Java内存模型(四)——volatile
volatile的特性 当我们声明共享变量为volatile后,对这个变量的读/写将会很特别.理解volatile特性的一个好方法是:把对volatile变量的单个读/写,看成是使用同一个监视器锁对这 ...
- 【转】深入理解Java内存模型(四)——volatile
volatile的特性 当我们声明共享变量为volatile后,对这个变量的读/写将会很特别.理解volatile特性的一个好方法是:把对volatile变量的单个读/写,看成是使用同一个监视器锁对这 ...
随机推荐
- 架构相关:组件化/模块化/工程化/性能优化/开发规范与团队协作/组件间调用与通信(flex/redux)/调试与测试
https://github.com/fouber/blog http://teropa.info/blog/2015/09/10/full-stack-redux-tutorial.html htt ...
- 补交20145226蓝墨云班课 -- Arrays和String单元测试
蓝墨云班课 -- Arrays和String单元测试 具体描述: 在IDEA中以TDD的方式对String类和Arrays类进行学习 测试相关方法的正常,错误和边界情况 String类 charAt ...
- 如何搭建openvpn
一.什么是openvpn Openvpn是一款基于openssl的开源vpn软件,它可以很好的运行在linux及windows各发行版本中,它的核心技术是虚拟网卡,其实它更像是一个底层的网卡驱动软件, ...
- 5469: [FJOI2018]领导集团问题
5469: [FJOI2018]领导集团问题 链接 题意: 要求在一棵树内选一个子集,满足子集内的任意两个点u,v,如果u是v的祖先,那么u的权值小于等于v. 分析: dp[u][i]表示在u的子树内 ...
- Python之元类详细解析
一.补充内置函数isinstance和issubclass 1.isinstance是判断一个对象是不是由一个对象产生的 class Foo: pass obj=Foo() print(isinsta ...
- 【转】将Centos的yum源更换为国内的阿里云源
摘要: 阿里云是最近新出的一个镜像源.得益于阿里云的高速发展,这么大的需求,肯定会推出自己的镜像源. 阿里云Linux安装镜像源地址:http://mirrors.aliyun.com/ CentOS ...
- sql server sql查询数据库的表,字段,主键,自增,字段类型等信息
1.查询数据表的属性(名称.说明.是否主键.数据类型.是否自增) SELECT t1.name columnName,case when t4.id is null then 'false' else ...
- Tomcat性能优化方案
1. 提高JVM栈内存Increase JVM heap memory 你使用过tomcat的话,简单的说就是"内存溢出". 通常情况下,这种问题出现在实际的生产环境中.产生这种问 ...
- 浅谈C与Java
Java的方法调用过程 Java变量:基本类型变量.指针变量 push 压入新的栈桢 在栈桢内部创建局部基本类型变量,接收参数值 在栈桢内部创建局部指针变量,接收参数值后,该指针变量指向堆上实例 po ...
- Python 3 利用 Dlib 实现摄像头实时人脸检测和平铺显示
1. 引言 在某些场景下,我们不仅需要进行实时人脸检测追踪,还要进行再加工:这里进行摄像头实时人脸检测,并对于实时检测的人脸进行初步提取: 单个/多个人脸检测,并依次在摄像头窗口,实时平铺显示检测到的 ...