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全局域名替换的实现

《SpringBoot全局域名替换的实现》本文主要介绍了SpringBoot全局域名替换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录 项目结构⚙️ 配置文件application.yml️ 配置类AppProperties.Ja

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

JavaScript中的高级调试方法全攻略指南

《JavaScript中的高级调试方法全攻略指南》什么是高级JavaScript调试技巧,它比console.log有何优势,如何使用断点调试定位问题,通过本文,我们将深入解答这些问题,带您从理论到实... 目录观点与案例结合观点1观点2观点3观点4观点5高级调试技巧详解实战案例断点调试:定位变量错误性能分

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

SpringBoot实现不同接口指定上传文件大小的具体步骤

《SpringBoot实现不同接口指定上传文件大小的具体步骤》:本文主要介绍在SpringBoot中通过自定义注解、AOP拦截和配置文件实现不同接口上传文件大小限制的方法,强调需设置全局阈值远大于... 目录一  springboot实现不同接口指定文件大小1.1 思路说明1.2 工程启动说明二 具体实施2

Java实现在Word文档中添加文本水印和图片水印的操作指南

《Java实现在Word文档中添加文本水印和图片水印的操作指南》在当今数字时代,文档的自动化处理与安全防护变得尤为重要,无论是为了保护版权、推广品牌,还是为了在文档中加入特定的标识,为Word文档添加... 目录引言Spire.Doc for Java:高效Word文档处理的利器代码实战:使用Java为Wo

SpringBoot日志级别与日志分组详解

《SpringBoot日志级别与日志分组详解》文章介绍了日志级别(ALL至OFF)及其作用,说明SpringBoot默认日志级别为INFO,可通过application.properties调整全局或... 目录日志级别1、级别内容2、调整日志级别调整默认日志级别调整指定类的日志级别项目开发过程中,利用日志

Java中的抽象类与abstract 关键字使用详解

《Java中的抽象类与abstract关键字使用详解》:本文主要介绍Java中的抽象类与abstract关键字使用详解,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、抽象类的概念二、使用 abstract2.1 修饰类 => 抽象类2.2 修饰方法 => 抽象方法,没有

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版