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

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

Java判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

Java中ArrayList和LinkedList有什么区别举例详解

《Java中ArrayList和LinkedList有什么区别举例详解》:本文主要介绍Java中ArrayList和LinkedList区别的相关资料,包括数据结构特性、核心操作性能、内存与GC影... 目录一、底层数据结构二、核心操作性能对比三、内存与 GC 影响四、扩容机制五、线程安全与并发方案六、工程

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

Spring AI集成DeepSeek的详细步骤

《SpringAI集成DeepSeek的详细步骤》DeepSeek作为一款卓越的国产AI模型,越来越多的公司考虑在自己的应用中集成,对于Java应用来说,我们可以借助SpringAI集成DeepSe... 目录DeepSeek 介绍Spring AI 是什么?1、环境准备2、构建项目2.1、pom依赖2.2