Java_io体系之RandomAccessFile简介、走进源码及示例——20
Java_io体系之RandomAccessFile简介、走进源码及示例——20
RandomAccessFile
1、 类功能简介:
文件随机访问流、关心几个特点:
1、他实现的接口不再是InputStream、OutputStream中的任何一个、而是实现的DataInput、DataOutput。这也注定了他可以对java基础类型进行操作、而且是即可读取、也可以写入、关于这部分的方法大多数都是从DataInputStream、DataOutputStream那里荡来的。
2、如其名、随机流、这里的随机并不是不可控制、不可预测的去访问文件、而是可以通过指针的形式定位到具体的位置——“文件指针”、具体使用“文件指针”的方法:调用此流的seek(long n)方法来设置位置、使用此方法要注意的是如果传入的n大于文件长度、此方法不会改变文件长度、只是当写入下一个字节时会改变文件大小、即下一个写入的字节是添加在n后的。如果n小于文件长度、则会从n位置开始覆盖后面的file内容、
3、此流既可以读取文件、也可以写入文件、也可具有只读功能、但是没有只写功能、具体是哪种类型是在构造方法中指定的——String mode;具体的区别上面有说明。。
这里把实例放在了前面、因为源码和方法所占篇幅太长、有兴趣的可继续往下看。
2、 实例演示:
package com.chy.io.original.test; import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile; public class RandomAccessFileTests { private static final File file = new File("D:\\rsf.txt"); /**
* 向文件中写入内容
*/
public static void testRandomAccessFileWriter() throws IOException{
//要先将已有文件删除、避免干扰。
if(file.exists()){
file.delete();
} RandomAccessFile rsfWriter = new RandomAccessFile(file, "rw"); //不会改变文件大小、但是他会将下一个字符的写入位置标识为10000、也就是说此后只要写入内容、就是从10001开始存、
rsfWriter.seek(10000);
printFileLength(rsfWriter); //result: 0 //会改变文件大小、只是把文件的size改变、并没有改变下一个要写入的内容的位置、这里注释掉是为了验证上面的seek方法的说明内容
//rsfWriter.setLength(10000);
printFileLength(rsfWriter); //result: 0 //每个汉子占3个字节、写入字符串的时候会有一个记录写入字符串长度的两个字节
rsfWriter.writeUTF("陈华应");
printFileLength(rsfWriter); //result: 10011 //每个字符占两个字节
rsfWriter.writeChar('a');
rsfWriter.writeChars("abcde");
printFileLength(rsfWriter); //result: 10023 //再从“文件指针”为5000的地方插一个长度为100、内容全是'a'的字符数组
//这里file长依然是10023、因为他是从“文件指针”为5000的地方覆盖后面的200个字节、下标并没有超过文件长度
rsfWriter.seek(5000);
char[] cbuf = new char[100];
for(int i=0; i
3、 RandomAccessFile API简介:
A:构造方法
RandomAccessFile(File file, String mode) 创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。 RandomAccessFile(String name, String mode) 从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。
补充一:mode的取值有下面四种情况
"r" 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。
"rw" 打开以便读取和写入。
"rws" 打开以便读取和写入。相对于 "rw","rws" 还要求对“文件的内容”或“元数据”的每个更新都同步写入到基础存储设备。
"rwd" 打开以便读取和写入,相对于 "rw","rwd" 还要求对“文件的内容”的每个更新都同步写入到基础存储设备。
补充二:关于文件的“元数据”
The definition of metadata is "data about other data." With a file system, the data is contained in its files and directories, and the metadata tracks information about each of these objects: Is it a regular file, a directory,
or a link? What is its size, creation date, last modified date, file owner, group owner, and access permissions?
补充三:"rw" "rws" "rwd"之间的区别
当操作的文件是存储在本地的基础存储设备上时(如硬盘, NandFlash等),"rws" 或 "rwd", "rw" 才有区别。
当模式是 "rws" 并且 操作的是基础存储设备上的文件;那么,每次“更改文件内容[如write()写入数据]” 或 “修改文件元数据(如文件的mtime)”时,都会将这些改变同步到基础存储设备上。
当模式是 "rwd" 并且 操作的是基础存储设备上的文件;那么,每次“更改文件内容[如write()写入数据]”时,都会将这些改变同步到基础存储设备上。
当模式是 "rw" 并且 操作的是基础存储设备上的文件;那么,关闭文件时,会将“文件内容的修改”同步到基础存储设备上。至于,“更改文件内容”时,是否会立即同步,取决于系统底层实现。
一般使用前两个就ok。
B:一般方法
void close() 关闭此随机访问文件流并释放与该流关联的所有系统资源。 FileChannel getChannel() 返回与此文件关联的唯一 FileChannel 对象。 FileDescriptor getFD() 返回与此流关联的不透明文件描述符对象。 long getFilePointer() 返回此文件中的当前偏移量。 long length() 返回此文件的长度。 int read() 从此文件中读取一个数据字节。 int read(byte[] b) 将最多 b.length 个数据字节从此文件读入 byte 数组。 int read(byte[] b, int off, int len) 将最多 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, int off, int len) 将正好 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, int off, int len) 将 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 编码以与机器无关的方式将一个字符串写入该文件。
4、 源码分析
package com.chy.io.original.code; import java.io.Closeable;
import java.io.EOFException;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UTFDataFormatException;
import java.nio.channels.FileChannel; import sun.nio.ch.FileChannelImpl; /**
* 随机访问文件流、既可以对文件进行读取、也可以对文件进行写入、还可以写入java基础类型、不再是InputStream或者OutputStream的子类、
* 而是实现了DataOutput、DataInput、通过这两个接口也可以看出、此类具有将java基础类型写入文件或者读取到程序中的功能、关于写入/读取文件基础类型
* 的操作大多数都是剽窃DataInputStream/DataOutputStream的。
*/ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
java.io.RandomAccessFile
private FileDescriptor fd;
private FileChannel channel = null;
private boolean rw;//标识此文件是否既可以读又可以写 //标识不同mode对应的值
private static final int O_RDONLY = 1;
private static final int O_RDWR = 2;
private static final int O_SYNC = 4;
private static final int O_DSYNC = 8; /**
* 使用指定的文件、模式构造RandomAccessFile、初始化参数、打开到文件的连接
*/
public RandomAccessFile(String name, String mode)
throws FileNotFoundException
{
this(name != null ? new File(name) : null, mode);
} /**
* 使用指定的文件、模式构造RandomAccessFile、初始化参数、打开到文件的连接
*/
public RandomAccessFile(File file, String mode)
throws FileNotFoundException
{
String name = (file != null ? file.getPath() : null);
int imode = -1;
if (mode.equals("r"))
imode = O_RDONLY;
else if (mode.startsWith("rw")) {
imode = O_RDWR;
rw = true;
if (mode.length() > 2) {
if (mode.equals("rws"))
imode |= O_SYNC;
else if (mode.equals("rwd"))
imode |= O_DSYNC;
else
imode = -1;
}
}
if (imode len) {
newpos = len;
}
seek(newpos); /* return the actual number of bytes skipped */
return (int) (newpos - pos);
} // 'Write' primitives /**
* 在当前“文件指针”标示的地方写入一个字节
*/
public native void write(int b) throws IOException; /**
* 将b的一部分写入到文件中
*/
private native void writeBytes(byte b[], int off, int len) throws IOException; /**
* 将b写入到文件中
*/
public void write(byte b[]) throws IOException {
writeBytes(b, 0, b.length);
} /**
* 将b的一部分写入到文件中
*/
public void write(byte b[], int off, int len) throws IOException {
writeBytes(b, off, len);
} // 'Random access' stuff /**
* 返回当前文件的偏移量、即“文件描述符”的位置
*/
public native long getFilePointer() throws IOException; /**
* 设置“文件指针”的偏移量、从文件的开头开始计数、如果pos大于文件的长度、也不会改变文件的大小、
* 文件的大小只有在当“文件指针”指向文件最后的时候、再向文件中写入字节才会扩展。
*/
public native void seek(long pos) throws IOException; /**
* 返回文件的字节数
*/
public native long length() throws IOException; /**
* 设置文件长度:
* if(newLength > originalLength)
* 扩展文件长度、新增加的长度使用默认值填充;
* else
* 截取源文件的前originalLength字节、如果源文件的偏移量大于newLength、则将源文件的偏移量设为newLength;
*/
public native void setLength(long newLength) throws IOException; /**
* 关闭此流、释放与此流有关的所有资源
*/
public void close() throws IOException {
if (channel != null)
channel.close(); close0();
} // 一些方法是从DataInputStream/DataOutputStream中剽窃来的。。。 /**
* 读取一个boolean型数据
*/
public final boolean readBoolean() throws IOException {
int ch = this.read();
if (ch >> 8) & 0xFF);
write((v >>> 0) & 0xFF);
//written += 2;
} /**
* 将一个char写入文件
*/
public final void writeChar(int v) throws IOException {
write((v >>> 8) & 0xFF);
write((v >>> 0) & 0xFF);
//written += 2;
} /**
* 将一个int写入文件
*/
public final void writeInt(int v) throws IOException {
write((v >>> 24) & 0xFF);
write((v >>> 16) & 0xFF);
write((v >>> 8) & 0xFF);
write((v >>> 0) & 0xFF);
//written += 4;
} /**
* 将一个long写入文件
*/
public final void writeLong(long v) throws IOException {
write((int)(v >>> 56) & 0xFF);
write((int)(v >>> 48) & 0xFF);
write((int)(v >>> 40) & 0xFF);
write((int)(v >>> 32) & 0xFF);
write((int)(v >>> 24) & 0xFF);
write((int)(v >>> 16) & 0xFF);
write((int)(v >>> 8) & 0xFF);
write((int)(v >>> 0) & 0xFF);
//written += 8;
} /**
* 将一个long写入文件
*/
public final void writeFloat(float v) throws IOException {
writeInt(Float.floatToIntBits(v));
} /**
* 将一个double写入文件。
*/
public final void writeDouble(double v) throws IOException {
writeLong(Double.doubleToLongBits(v));
} /**
* 将一个字符串转换成一串有序字节写入
*/
public final void writeBytes(String s) throws IOException {
int len = s.length();
byte[] b = new byte[len];
s.getBytes(0, len, b, 0);
writeBytes(b, 0, len);
} /**
* 将一个字符串以一串有序字符写入文件中
*/
public final void writeChars(String s) throws IOException {
int clen = s.length();
int blen = 2*clen;
byte[] b = new byte[blen];
char[] c = new char[clen];
s.getChars(0, clen, c, 0);
for (int i = 0, j = 0; i >> 8);
b[j++] = (byte)(c[i] >>> 0);
}
writeBytes(b, 0, blen);
} /**
* 调用DataOutputStream的 writeUTF(String str, DataOutput out) 将一个字符串写入文件。
*/
public final void writeUTF(String str) throws IOException {
DataOutputStream.writeUTF(str, this);
} private static native void initIDs(); private native void close0() throws IOException; static {
initIDs();
} }
更多IO内容:java_io 体系之目录
Java_io体系之RandomAccessFile简介、走进源码及示例——20的更多相关文章
- Java_io体系之PipedWriter、PipedReader简介、走进源码及示例——14
Java_io体系之PipedWriter.PipedReader简介.走进源码及示例——14 ——管道字符输出流.必须建立在管道输入流之上.所以先介绍管道字符输出流.可以先看示例或者总结.总结写的有 ...
- Java_io体系之BufferedWriter、BufferedReader简介、走进源码及示例——16
Java_io体系之BufferedWriter.BufferedReader简介.走进源码及示例——16 一:BufferedWriter 1.类功能简介: BufferedWriter.缓存字符输 ...
- Linux内核分析(一)---linux体系简介|内核源码简介|内核配置编译安装
原文:Linux内核分析(一)---linux体系简介|内核源码简介|内核配置编译安装 Linux内核分析(一) 从本篇博文开始我将对linux内核进行学习和分析,整个过程必将十分艰辛,但我会坚持到底 ...
- java 日志体系(四)log4j 源码分析
java 日志体系(四)log4j 源码分析 logback.log4j2.jul 都是在 log4j 的基础上扩展的,其实现的逻辑都差不多,下面以 log4j 为例剖析一下日志框架的基本组件. 一. ...
- ThreadLocal 简介 案例 源码分析 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- java io系列12之 BufferedInputStream(缓冲输入流)的认知、源码和示例
本章内容包括3个部分:BufferedInputStream介绍,BufferedInputStream源码,以及BufferedInputStream使用示例. 转载请注明出处:http://www ...
- java io系列13之 BufferedOutputStream(缓冲输出流)的认知、源码和示例
本章内容包括3个部分:BufferedOutputStream介绍,BufferedOutputStream源码,以及BufferedOutputStream使用示例. 转载请注明出处:http:// ...
- java io系列15之 DataOutputStream(数据输出流)的认知、源码和示例
本章介绍DataOutputStream.我们先对DataOutputStream有个大致认识,然后再深入学习它的源码,最后通过示例加深对它的了解. 转载请注明出处:http://www.cnblog ...
- Hadoop(一)Hadoop的简介与源码编译
一 Hadoop简介 1.1Hadoop产生的背景 1. HADOOP最早起源于Nutch.Nutch的设计目标是构建一个大型的全网搜索引擎,包括网页抓取.索引.查询等功能,但随着抓取网页数量的增加, ...
随机推荐
- WEB 小案例 -- 网上书城(四)
针对于这个小案例我们今天讲解结账操作,也是有关这个案例的最后一次博文,说实话这个案例的博文写的很糟糕,不知道该如何去表述自己的思路,所以内容有点水,其实说到底还是功力不够. 处理思路 点击结账,发送结 ...
- vue路由\导航刷新后:ative\localStorage\url截取参数
<el-menu :default-active="$route.path" router mode="horizontal"> <el-me ...
- 898 C. Phone Numbers
传送门 [http://codeforces.com/contest/898/problem/C] 题意 题意比较难理解直接看样例就知道了,给你个n接下来n行,每行包括一个名字和号码的数量,还有具体的 ...
- Pair Project1:电梯控制程序
12061199 程刚 && 12061204 黎柱金 一.结对编程的优缺点 结对编程相对于一个人的编程有更多的优点,缺点也有很大不同. 首先,优点: 结队可以让两人可以更好的协 ...
- Week7阅读笔记
关于银弹: Brooks在他最著名的这篇文章里指出,在软件开发过程里是没有万能的终杀性武器的,只有各种方法综合运用,才是解决之道.而各种声称如何如何神奇的理论或方法,都不是能杀死“软件危机”这头人狼的 ...
- Week 2 代码审查
我的伙伴是6班的小伙子潘礼鹏,经过几天的相处我觉得真的是说话很有趣的人,性格非常好,我们很划得来. 以下为我对他的代码的审查结果: VS2012与VS2013的兼容性 在这里写一个工具集的问题,不同的 ...
- 团队作业 week 14
0. 在吹牛之前,先回答这个问题: 如果你的团队来了一个新队员,有一台全新的机器, 你们是否有一个文档,只要设置了相应的权限,她就可以根据文档,从头开始搭建环境,并成功地把最新.最稳定版本的软件编译出 ...
- beta版说明书
项目名称:GoGoing 软件使用说明: 在主界面是可以点击选择景点门票区间来选择景点,同时也可搜索景点显示信息. 还可以通过定位功能显示附近景点. 点开门票区间后是一些景点的图片和简介,还可以通过距 ...
- 第七组团队项目——专业课程资源共享平台——需求分析&原型设计
一.项目目标.定位需求: (1)目标:在教师.学生之间建立一个综合的.全面的.快捷的.高效的免费课程和学习资源共享.交流与推荐的开放性平台,实现多维和动态的推荐与分类检索服务. (2)定位:学生与教师 ...
- BUAA软工个人作业Week3-案例分析
一. 调研评测 评测项目:为了联系移动和PC版,我同时下载了必应词典的Android版本和UWP版本,选择UWP的原因是想看看微软推广的UWP在微软自己的应用上的效果.当然主要是对安卓的测评(UWP用 ...