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如何根据word模板导出数据

《Java如何根据word模板导出数据》这篇文章主要为大家详细介绍了Java如何实现根据word模板导出数据,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... pom.XML文件导入依赖 <dependency> <groupId>cn.afterturn</groupId>

Java应用如何防止恶意文件上传

《Java应用如何防止恶意文件上传》恶意文件上传可能导致服务器被入侵,数据泄露甚至服务瘫痪,因此我们必须采取全面且有效的防范措施来保护Java应用的安全,下面我们就来看看具体的实现方法吧... 目录恶意文件上传的潜在风险常见的恶意文件上传手段防范恶意文件上传的关键策略严格验证文件类型检查文件内容控制文件存储

浅析Java如何保护敏感数据

《浅析Java如何保护敏感数据》在当今数字化时代,数据安全成为了软件开发中至关重要的课题,本文将深入探讨Java安全领域,聚焦于敏感数据保护的策略与实践,感兴趣的小伙伴可以了解下... 目录一、Java 安全的重要性二、敏感数据加密技术(一)对称加密(二)非对称加密三、敏感数据的访问控制(一)基于角色的访问

Java计算经纬度距离的示例代码

《Java计算经纬度距离的示例代码》在Java中计算两个经纬度之间的距离,可以使用多种方法(代码示例均返回米为单位),文中整理了常用的5种方法,感兴趣的小伙伴可以了解一下... 目录1. Haversine公式(中等精度,推荐通用场景)2. 球面余弦定理(简单但精度较低)3. Vincenty公式(高精度,

使用Java将实体类转换为JSON并输出到控制台的完整过程

《使用Java将实体类转换为JSON并输出到控制台的完整过程》在软件开发的过程中,Java是一种广泛使用的编程语言,而在众多应用中,数据的传输和存储经常需要使用JSON格式,用Java将实体类转换为J... 在软件开发的过程中,Java是一种广泛使用的编程语言,而在众多应用中,数据的传输和存储经常需要使用j

Java实现视频格式转换的完整指南

《Java实现视频格式转换的完整指南》在Java中实现视频格式的转换,通常需要借助第三方工具或库,因为视频的编解码操作复杂且性能需求较高,以下是实现视频格式转换的常用方法和步骤,需要的朋友可以参考下... 目录核心思路方法一:通过调用 FFmpeg 命令步骤示例代码说明优点方法二:使用 Jaffree(FF

Java实现图片淡入淡出效果

《Java实现图片淡入淡出效果》在现代图形用户界面和游戏开发中,**图片淡入淡出(FadeIn/Out)**是一种常见且实用的视觉过渡效果,它可以用于启动画面、场景切换、轮播图、提示框弹出等场景,通过... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细

Java如何用乘号来重复字符串的功能

《Java如何用乘号来重复字符串的功能》:本文主要介绍Java使用乘号来重复字符串的功能,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java乘号来重复字符串的功能1、利用循环2、使用StringBuilder3、采用 Java 11 引入的String.rep

SpringBoot中HTTP连接池的配置与优化

《SpringBoot中HTTP连接池的配置与优化》这篇文章主要为大家详细介绍了SpringBoot中HTTP连接池的配置与优化的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、HTTP连接池的核心价值二、Spring Boot集成方案方案1:Apache HttpCl

Spring Boot项目打包和运行的操作方法

《SpringBoot项目打包和运行的操作方法》SpringBoot应用内嵌了Web服务器,所以基于SpringBoot开发的web应用也可以独立运行,无须部署到其他Web服务器中,下面以打包dem... 目录一、打包为JAR包并运行1.打包为可执行的 JAR 包2.运行 JAR 包二、打包为WAR包并运行