本文主要是介绍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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!