JAVA I/O系统 Thinking in Java 之 RandomAccessFile

2024-04-19 09:48

本文主要是介绍JAVA I/O系统 Thinking in Java 之 RandomAccessFile,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

RandomAccessFile是脱离InputStream和OutputStream单独存在的类。他实现了DataOutput, DataInput, Closeable三个类,封装了类似装饰器DataInputStream和DataOutputStream的数据类型转换功能,以及独有的在文件中寻找切入点的功能。它可以在一个文件中向前或向后移动,获取当前所处的文件位置,移动到某个位置,判断文件的大小。接下来看一下API。

方法名参数注释
  public RandomAccessFile(String name, String mode)

name 文件路径

mode 读写模式。(r   只读;rw  读写;rws 读写同步模式,同时同步文件数据和文件元数据; rwd 简单的读写同步模式,仅同步文件数据。)

创建一个RandomAccessFile
public RandomAccessFile(File file, String mode)

file 文件

mode 读写模式。(r   只读;rw  读写;rws 读写同步模式,同时同步文件数据和文件元数据; rwd 简单的读写同步模式,仅同步文件数据。)

创建一个RandomAccessFile
 public final FileDescriptor getFD()  获取文件描述符
public final FileChannel getChannel()  返回文件通道
 public int read() 读取下一个字节并转为int,如果没有可读取的字节则返回-1。
public int read(byte b[], int off, int len)

b 缓存字节数组

off 指定b中开始的位置

len 指定读取的字节数

读取len个字节存入b中的off开始的位置,返回实际读取的字节数
public int read(byte b[])b 缓存字节数组读取len个字节存入b中,返回实际读取的字节数
public final void readFully(byte b[])b 缓存字节数组将流中的字节全部读入b中。
public final void readFully(byte b[], int off, int len) 

b 缓存字节数组

off 指定b中开始的位置

len 指定读取的字节数

将流中的len个字节全部读入b中的off开始的位置,如果不够len个字节,抛出异常。
public int skipBytes(int n) n 跳跃的字节数 尝试跳跃n个字节,返回实际跳跃的字节
public void write(int b)b int类型的字节将b写入输出流中
public void write(byte b[])b 字节数组将b中的所有数据写入输出流中
public void write(byte b[], int off, int len)

b 字节数组

off 指定b中开始的位置

len 指定读取的字节数

将b中off开始的len个字节写入输出流中
public native long getFilePointer() 获取文件当前的访问位置。
public void seek(long pos)pos 要移动的位置将文件的访问位置移动到pos处。
public native long length()  获取文件长度
public native void setLength(long newLength)newLength 新的长度

设置文件长度。

如果新的长度小于旧的长度,文件将被截断;
如果文件当前的访问位置大于新的长度,那么设置完以后文件当前的访问位置改为新的文件长度;
 如果新的长度大于旧的长度,那么文件将本扩展,扩展的内容无法被解析。

public void close() 关闭流。
public final boolean readBoolean() 将下一个字节读为boolean返回
public final byte readByte() 读取下一个字节并转为byte返回
 public final int readUnsignedByte()  读取下一个字节,并直接强转为int返回。
public final short readShort() 读取之后的两个字节,然后按顺序拼接高低位转short类型返回。
public final int readUnsignedShort() 读取下两个字节,按顺序拼接高低位以int形式返回。
public final char readChar() 读取下两个字节,按顺序拼接高低位以char形式返回。
public final int readInt() 读取下四个字节,按高低位顺序拼接为int类型返回。
public final long readLong() 读取8个字节,按高低位顺序相加转为long返回。
public final float readFloat()  读取4个字节,按高低位顺序相加为int后,通过 Float.intBitsToFloat()方法转为float返回。
public final double readDouble() 读取8个字节,按高低位顺序相加为long后,通过  Double.longBitsToDouble()方法转为double返回。
public final String readLine() 读取下一行数据为字符串,每一个字节被转为字符行并且将高八位设置为0,该方法不支持国际字符Unicode编码。
public final String readUTF() 以UTF-8编码读取为字符串。
public final void writeBoolean(boolean v)v 写入的boolean将一个boolean写入。
public final void writeByte(int v) v 写入的byte的int值将一个int值(这里假设输入的是个byte类型范围的值),然后按照两个字节高位在前的顺序写入输出流中。如果超过byte范围,则将int的第四个字节写入。
public final void writeShort(int v)v 写入的short的int值将一个int值(这里假设输入的是个short类型范围的值),然后按照两个字节高位在前的顺序写入输出流中。如果超过short范围,则将int的第三个字节和第四个字节写入。
public final void writeChar(int v)v 写入的char的int值将一个int值(这里假设输入的是个char类型范围的值),然后按照两个字节高位在前的顺序写入输出流中。如果超过char范围,则将int的第三个字节和第四个字节写入。
public final void writeInt(int v)v 写入的int 将一个int值,然后按照四个字节高位在前的顺序写入输出流中。
public final void writeLong(long v)v 写入的long将一个long值,然后按照八个字节高位在前的顺序写入输出流中。
public final void writeFloat(float v)v 写入的float将一个float 通过Float.floatToIntBits()转为int字节,然后按照四个字节高位在前的顺序写入输出流中。
public final void writeDouble(double v)v 写入的double将一个double通过Double.doubleToLongBits()转为long字节,然后按照八个字节高位在前的顺序写入输出流中。
public final void writeBytes(String s)s 写入的字符串将字符串作为字节序列写入文件。每个字符串中的字符按顺序通过丢弃高8位。从文件当前位置开始写入。
public final void writeChars(String s) s 写入的字符串将字符串以字符数组的形式写入输出流中
 public final void writeUTF(String str)str 写入的字符串将字符串以UTF-8的格式写入输出流中。

源码:

package java.io;import java.nio.channels.FileChannel;
import sun.nio.ch.FileChannelImpl;/*** @since   JDK1.0*/public class RandomAccessFile implements DataOutput, DataInput, Closeable {private FileDescriptor fd;private FileChannel channel = null;private boolean rw;/*** The path of the referenced file* (null if the stream is created with a file descriptor)*/private final String path;private Object closeLock = new Object();private volatile boolean closed = false;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** @param      name   目标文件地址* @param      mode   模式* mode r   只读*      rw  读写*      rws 读写同步模式,同时同步文件数据和文件元数据*      rwd 简单的读写同步模式,仅同步文件数据。* @revised 1.4* @spec JSR-51*/public RandomAccessFile(String name, String mode)throws FileNotFoundException{this(name != null ? new File(name) : null, mode);}/*** 创建一个RandomAccessFile** @param      name   目标文件地址* @param      mode   模式* mode r   只读*      rw  读写*      rws 读写同步模式,同时同步文件数据和文件元数据*      rwd 简单的读写同步模式,仅同步文件数据。* @revised 1.4* @spec JSR-51*/public RandomAccessFile(File file, String mode)throws FileNotFoundException{//如果文件不存在,则name为nullString 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;elseimode = -1;}}//如果模式不正确,抛出异常if (imode < 0)throw new IllegalArgumentException("Illegal mode \"" + mode+ "\" must be one of "+ "\"r\", \"rw\", \"rws\","+ " or \"rwd\"");//检查文件的权限SecurityManager security = System.getSecurityManager();if (security != null) {security.checkRead(name);if (rw) {security.checkWrite(name);}}//确保文件存在if (name == null) {throw new NullPointerException();}//确保文件可用if (file.isInvalid()) {throw new FileNotFoundException("Invalid file path");}//新建一个文件描述符fd = new FileDescriptor();fd.attach(this);path = name;open(name, imode);}/*** 获取文件描述符*/public final FileDescriptor getFD() throws IOException {if (fd != null) {return fd;}throw new IOException();}/*** 返回文件通道** @since 1.4* @spec JSR-51*/public final FileChannel getChannel() {synchronized (this) {if (channel == null) {channel = FileChannelImpl.open(fd, path, true, rw, this);}return channel;}}/*** 本地方法打开文件并返回文件描述符,如果是读写模式,则以读写模式打开,否则以只读模式打开。** @param name the name of the file* @param mode the mode flags, a combination of the O_ constants*             defined above*/private native void open0(String name, int mode)throws FileNotFoundException;/*** 包装open0方法,以允许检测。** @param name the name of the file* @param mode the mode flags, a combination of the O_ constants*             defined above*/private void open(String name, int mode)throws FileNotFoundException {open0(name, mode);}// 'Read' primitives/*** 读取下一个字节并转为int,如果没有可读取的输入流,这个方法将阻塞。** @return     返回下一个字节,如果没有可读取的字节则返回-1.*/public int read() throws IOException {return read0();}private native int read0() throws IOException;/*** 本地方法,读取len个字节存入b中的off开始的位置,返回实际读取的字节数*/private native int readBytes(byte b[], int off, int len) throws IOException;/*** 读取len个字节存入b中的off开始的位置,返回实际读取的字节数*/public int read(byte b[], int off, int len) throws IOException {return readBytes(b, off, len);}/*** 读取len个字节存入b中,返回实际读取的字节数*/public int read(byte b[]) throws IOException {return readBytes(b, 0, b.length);}/***  将流中的字节全部读入b中。*/public final void readFully(byte b[]) throws IOException {readFully(b, 0, b.length);}/*** 将流中的len个字节全部读入b中的off开始的位置,如果不够len个字节,抛出异常。*/public final void readFully(byte b[], int off, int len) throws IOException {int n = 0;do {int count = this.read(b, off + n, len - n);if (count < 0)throw new EOFException();n += count;} while (n < len);}/*** 尝试跳跃n个字节,返回实际跳跃的字节*/public int skipBytes(int n) throws IOException {long pos;long len;long newpos;if (n <= 0) {return 0;}pos = getFilePointer();len = length();newpos = pos + n;if (newpos > len) {newpos = len;}seek(newpos);/* return the actual number of bytes skipped */return (int) (newpos - pos);}/*** 将b写入输出流中*/public void write(int b) throws IOException {write0(b);}private native void write0(int b) throws IOException;/*** 将b中off开始的len个字节写入输出流中*/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中off开始的len个字节写入输出流中*/public void write(byte b[], int off, int len) throws IOException {writeBytes(b, off, len);}/*** 获取文件当前的访问位置。*/public native long getFilePointer() throws IOException;/*** 将文件的访问位置移动到pos处。*/public void seek(long pos) throws IOException {if (pos < 0) {throw new IOException("Negative seek offset");} else {seek0(pos);}}private native void seek0(long pos) throws IOException;/*** 获取文件长度*/public native long length() throws IOException;/*** 设置文件长度。* 如果新的长度小于旧的长度,文件将被截断;* 如果文件当前的访问位置大于新的长度,那么设置完以后文件当前的访问位置改为新的文件长度;* 如果新的长度大于旧的长度,那么文件将本扩展,扩展的内容无法被解析。** @param      newLength    The desired length of the file* @exception  IOException  If an I/O error occurs* @since      1.2*/public native void setLength(long newLength) throws IOException;/*** 关闭流。** @revised 1.4* @spec JSR-51*/public void close() throws IOException {synchronized (closeLock) {if (closed) {return;}closed = true;}if (channel != null) {channel.close();}fd.closeAll(new Closeable() {public void close() throws IOException {close0();}});}/*** 将下一个字节读为boolean返回** @return     the {@code boolean} value read.* @exception  EOFException  if this file has reached the end.* @exception  IOException   if an I/O error occurs.*/public final boolean readBoolean() throws IOException {int ch = this.read();if (ch < 0)throw new EOFException();return (ch != 0);}/*** 读取下一个字节并转为byte返回*/public final byte readByte() throws IOException {int ch = this.read();if (ch < 0)throw new EOFException();return (byte)(ch);}/*** 读取下一个字节,并直接强转为int返回。*/public final int readUnsignedByte() throws IOException {int ch = this.read();if (ch < 0)throw new EOFException();return ch;}/*** 读取之后的两个字节,然后按顺序拼接高低位转short类型返回。*/public final short readShort() throws IOException {int ch1 = this.read();int ch2 = this.read();if ((ch1 | ch2) < 0)throw new EOFException();return (short)((ch1 << 8) + (ch2 << 0));}/*** 读取下两个字节,按顺序拼接高低位以int形式返回。*/public final int readUnsignedShort() throws IOException {int ch1 = this.read();int ch2 = this.read();if ((ch1 | ch2) < 0)throw new EOFException();return (ch1 << 8) + (ch2 << 0);}/*** 读取下两个字节,按顺序拼接高低位以char形式返回。*/public final char readChar() throws IOException {int ch1 = this.read();int ch2 = this.read();if ((ch1 | ch2) < 0)throw new EOFException();return (char)((ch1 << 8) + (ch2 << 0));}/*** 读取下四个字节,按高低位顺序拼接为int类型返回。*/public final int readInt() throws IOException {int ch1 = this.read();int ch2 = this.read();int ch3 = this.read();int ch4 = this.read();if ((ch1 | ch2 | ch3 | ch4) < 0)throw new EOFException();return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));}/*** 读取8个字节,按高低位顺序相加转为long返回。*/public final long readLong() throws IOException {return ((long)(readInt()) << 32) + (readInt() & 0xFFFFFFFFL);}/*** 读取4个字节,按高低位顺序相加为int后,通过 Float.intBitsToFloat()方法转为float返回。*/public final float readFloat() throws IOException {return Float.intBitsToFloat(readInt());}/*** 读取8个字节,按高低位顺序相加为long后,通过  Double.longBitsToDouble()方法转为double返回。*/public final double readDouble() throws IOException {return Double.longBitsToDouble(readLong());}/*** 读取下一行数据为字符串,每一个字节被转为字符行并且将高八位设置为0,该方法不支持国际字符Unicode编码。*** @return     the next line of text from this file, or null if end*             of file is encountered before even one byte is read.* @exception  IOException  if an I/O error occurs.*/public final String readLine() throws IOException {StringBuffer input = new StringBuffer();int c = -1;boolean eol = false;while (!eol) {switch (c = read()) {case -1:case '\n':eol = true;break;case '\r':eol = true;long cur = getFilePointer();if ((read()) != '\n') {seek(cur);}break;default:input.append((char)c);break;}}if ((c == -1) && (input.length() == 0)) {return null;}return input.toString();}/*** 以UTF-8编码读取为字符串。** @return     a Unicode string.* @exception  EOFException            if this file reaches the end before*               reading all the bytes.* @exception  IOException             if an I/O error occurs.* @exception  UTFDataFormatException  if the bytes do not represent*               valid modified UTF-8 encoding of a Unicode string.* @see        java.io.RandomAccessFile#readUnsignedShort()*/public final String readUTF() throws IOException {return DataInputStream.readUTF(this);}/*** 将一个boolean写入。** @param      v   a {@code boolean} value to be written.* @exception  IOException  if an I/O error occurs.*/public final void writeBoolean(boolean v) throws IOException {write(v ? 1 : 0);//written++;}/*** 将一个int值(这里假设输入的是个byte类型范围的值),然后按照两个字节高位在前的顺序写入输出流中。如果超过byte范围,则将int的第四个字节写入。** @param      v   a {@code byte} value to be written.* @exception  IOException  if an I/O error occurs.*/public final void writeByte(int v) throws IOException {write(v);//written++;}/*** 将一个int值(这里假设输入的是个short类型范围的值),然后按照两个字节高位在前的顺序写入输出流中。如果超过short范围,则将int的第三个字节和第四个字节写入。** @param      v   a {@code short} to be written.* @exception  IOException  if an I/O error occurs.*/public final void writeShort(int v) throws IOException {write((v >>> 8) & 0xFF);write((v >>> 0) & 0xFF);//written += 2;}/*** 将一个int值(这里假设输入的是个char类型范围的值),然后按照两个字节高位在前的顺序写入输出流中。如果超过char范围,则将int的第三个字节和第四个字节写入。** @param      v   a {@code char} value to be written.* @exception  IOException  if an I/O error occurs.*/public final void writeChar(int v) throws IOException {write((v >>> 8) & 0xFF);write((v >>> 0) & 0xFF);//written += 2;}/***  将一个int值,然后按照四个字节高位在前的顺序写入输出流中。** @param      v   an {@code int} to be written.* @exception  IOException  if an I/O error occurs.*/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值,然后按照八个字节高位在前的顺序写入输出流中。** @param      v   a {@code long} to be written.* @exception  IOException  if an I/O error occurs.*/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;}/*** 将一个float 通过Float.floatToIntBits()转为int字节,然后按照四个字节高位在前的顺序写入输出流中。** @param      v   a {@code float} value to be written.* @exception  IOException  if an I/O error occurs.* @see        java.lang.Float#floatToIntBits(float)*/public final void writeFloat(float v) throws IOException {writeInt(Float.floatToIntBits(v));}/*** 将一个double通过Double.doubleToLongBits()转为long字节,然后按照八个字节高位在前的顺序写入输出流中。** @param      v   a {@code double} value to be written.* @exception  IOException  if an I/O error occurs.* @see        java.lang.Double#doubleToLongBits(double)*/public final void writeDouble(double v) throws IOException {writeLong(Double.doubleToLongBits(v));}/*** 将字符串作为字节序列写入文件。每个字符串中的字符按顺序通过丢弃高8位。从文件当前位置开始写入。** @param      s   a string of bytes to be written.* @exception  IOException  if an I/O error occurs.*/@SuppressWarnings("deprecation")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 < clen; i++) {b[j++] = (byte)(c[i] >>> 8);b[j++] = (byte)(c[i] >>> 0);}writeBytes(b, 0, blen);}/*** 将字符串以UTF-8的格式写入输出流中。* @param      str   a string to be written.* @exception  IOException  if an I/O error occurs.*/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();}
}

 

这篇关于JAVA I/O系统 Thinking in Java 之 RandomAccessFile的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/917204

相关文章

SpringBoot结合Docker进行容器化处理指南

《SpringBoot结合Docker进行容器化处理指南》在当今快速发展的软件工程领域,SpringBoot和Docker已经成为现代Java开发者的必备工具,本文将深入讲解如何将一个SpringBo... 目录前言一、为什么选择 Spring Bootjavascript + docker1. 快速部署与

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

Spring Boot spring-boot-maven-plugin 参数配置详解(最新推荐)

《SpringBootspring-boot-maven-plugin参数配置详解(最新推荐)》文章介绍了SpringBootMaven插件的5个核心目标(repackage、run、start... 目录一 spring-boot-maven-plugin 插件的5个Goals二 应用场景1 重新打包应用

SpringBoot+EasyExcel实现自定义复杂样式导入导出

《SpringBoot+EasyExcel实现自定义复杂样式导入导出》这篇文章主要为大家详细介绍了SpringBoot如何结果EasyExcel实现自定义复杂样式导入导出功能,文中的示例代码讲解详细,... 目录安装处理自定义导出复杂场景1、列不固定,动态列2、动态下拉3、自定义锁定行/列,添加密码4、合并

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

Java中读取YAML文件配置信息常见问题及解决方法

《Java中读取YAML文件配置信息常见问题及解决方法》:本文主要介绍Java中读取YAML文件配置信息常见问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要... 目录1 使用Spring Boot的@ConfigurationProperties2. 使用@Valu

创建Java keystore文件的完整指南及详细步骤

《创建Javakeystore文件的完整指南及详细步骤》本文详解Java中keystore的创建与配置,涵盖私钥管理、自签名与CA证书生成、SSL/TLS应用,强调安全存储及验证机制,确保通信加密和... 目录1. 秘密键(私钥)的理解与管理私钥的定义与重要性私钥的管理策略私钥的生成与存储2. 证书的创建与

浅析Spring如何控制Bean的加载顺序

《浅析Spring如何控制Bean的加载顺序》在大多数情况下,我们不需要手动控制Bean的加载顺序,因为Spring的IoC容器足够智能,但在某些特殊场景下,这种隐式的依赖关系可能不存在,下面我们就来... 目录核心原则:依赖驱动加载手动控制 Bean 加载顺序的方法方法 1:使用@DependsOn(最直

SpringBoot中如何使用Assert进行断言校验

《SpringBoot中如何使用Assert进行断言校验》Java提供了内置的assert机制,而Spring框架也提供了更强大的Assert工具类来帮助开发者进行参数校验和状态检查,下... 目录前言一、Java 原生assert简介1.1 使用方式1.2 示例代码1.3 优缺点分析二、Spring Fr

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon