- 浏览: 107288 次
- 性别:
- 来自: 成都
文章分类
最新评论
RandomAccessFile
RandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,并进行读写了。这些记录的大小不必相同;但是其大小和位置必须是可知的。但是该类仅限于操作文件。
RandomAccessFile不属于InputStream和OutputStream类系的。实际上,除了实现DataInput和DataOutput接口之外(DataInputStream和DataOutputStream也实现了这两个接口),它和这两个类系毫不相干,甚至不使用InputStream和OutputStream类中已经存在的任何功能;它是一个完全独立的类,所有方法(绝大多数都只属于它自己)都是从零开始写的。这可能是因为RandomAccessFile能在文件里面前后移动,所以它的行为与其它的I/O类有些根本性的不同。总而言之,它是一个直接继承Object的,独立的类。
基本上,RandomAccessFile的工作方式是,把DataInputStream和DataOutputStream结合起来,再加上它自己的一些方法,比如定位用的getFilePointer( ),在文件里移动用的seek( ),以及判断文件大小的length( )、skipBytes()跳过多少字节数。此外,它的构造函数还要一个表示以只读方式("r"),还是以读写方式("rw")打开文件的参数 (和C的fopen( )一模一样)。它不支持只写文件。
只有RandomAccessFile才有seek搜寻方法,而这个方法也只适用于文件。BufferedInputStream有一个mark( )方法,你可以用它来设定标记(把结果保存在一个内部变量里),然后再调用reset( )返回这个位置,但是它的功能太弱了,而且也不怎么实用。
RandomAccessFile的绝大多数功能,但不是全部,已经被JDK 1.4的nio的"内存映射文件(memory-mapped files)"给取代了,你该考虑一下是不是用"内存映射文件"来代替RandomAccessFile了。
[java] view plaincopy
import java.io.IOException;
import java.io.RandomAccessFile;
public class TestRandomAccessFile {
public static void main(String[] args) throws IOException {
RandomAccessFile rf = new RandomAccessFile("rtest.dat", "rw");
for (int i = 0; i < 10; i++) {
//写入基本类型double数据
rf.writeDouble(i * 1.414);
}
rf.close();
rf = new RandomAccessFile("rtest.dat", "rw");
//直接将文件指针移到第5个double数据后面
rf.seek(5 *;
//覆盖第6个double数据
rf.writeDouble(47.0001);
rf.close();
rf = new RandomAccessFile("rtest.dat", "r");
for (int i = 0; i < 10; i++) {
System.out.println("Value " + i + ": " + rf.readDouble());
}
rf.close();
}
}
内存映射文件
内存映射文件能让你创建和修改那些因为太大而无法放入内存的文件。有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问。这种解决办法能大大简化修改文件的代码。
fileChannel.map(FileChannel.MapMode mode, long position, long size)将此通道的文件区域直接映射到内存中。注意,你必须指明,它是从文件的哪个位置开始映射的,映射的范围又有多大;也就是说,它还可以映射一个大文件的某个小片断。
MappedByteBuffer是ByteBuffer的子类,因此它具备了ByteBuffer的所有方法,但新添了force()将缓冲区的内容强制刷新到存储设备中去、load()将存储设备中的数据加载到内存中、isLoaded()位置内存中的数据是否与存储设置上同步。这里只简单地演示了一下put()和get()方法,除此之外,你还可以使用asCharBuffer( )之类的方法得到相应基本类型数据的缓冲视图后,可以方便的读写基本类型数据。
[java] view plaincopy
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class LargeMappedFiles {
static int length = 0x8000000; // 128 Mb
public static void main(String[] args) throws Exception {
// 为了以可读可写的方式打开文件,这里使用RandomAccessFile来创建文件。
FileChannel fc = new RandomAccessFile("test.dat", "rw").getChannel();
//注意,文件通道的可读可写要建立在文件流本身可读写的基础之上
MappedByteBuffer out = fc.map(FileChannel.MapMode.READ_WRITE, 0, length);
//写128M的内容
for (int i = 0; i < length; i++) {
out.put((byte) 'x');
}
System.out.println("Finished writing");
//读取文件中间6个字节内容
for (int i = length / 2; i < length / 2 + 6; i++) {
System.out.print((char) out.get(i));
}
fc.close();
}
}
尽管映射写似乎要用到FileOutputStream,但是映射文件中的所有输出 必须使用RandomAccessFile,但如果只需要读时可以使用FileInputStream,写映射文件时一定要使用随机访问文件,可能写时要读的原因吧。
该程序创建了一个128Mb的文件,如果一次性读到内存可能导致内存溢出,但这里访问好像只是一瞬间的事,这是因为,真正调入内存的只是其中的一小部分,其余部分则被放在交换文件上。这样你就可以很方便地修改超大型的文件了(最大可以到2 GB)。注意,Java是调用操作系统的"文件映射机制"来提升性能的。
RandomAccessFile类的应用:
[java] view plaincopy
/*
* 程序功能:演示了RandomAccessFile类的操作,同时实现了一个文件复制操作。
*/
package com.lwj.demo;
import java.io.*;
public class RandomAccessFileDemo {
public static void main(String[] args) throws Exception {
RandomAccessFile file = new RandomAccessFile("file", "rw");
// 以下向file文件中写数据
file.writeInt(20);// 占4个字节
file.writeDouble(8.236598);// 占8个字节
file.writeUTF("这是一个UTF字符串");// 这个长度写在当前文件指针的前两个字节处,可用readShort()读取
file.writeBoolean(true);// 占1个字节
file.writeShort(395);// 占2个字节
file.writeLong(2325451l);// 占8个字节
file.writeUTF("又是一个UTF字符串");
file.writeFloat(35.5f);// 占4个字节
file.writeChar('a');// 占2个字节
file.seek(0);// 把文件指针位置设置到文件起始处
// 以下从file文件中读数据,要注意文件指针的位置
System.out.println("——————从file文件指定位置读数据——————");
System.out.println(file.readInt());
System.out.println(file.readDouble());
System.out.println(file.readUTF());
file.skipBytes(3);// 将文件指针跳过3个字节,本例中即跳过了一个boolean值和short值。
System.out.println(file.readLong());
file.skipBytes(file.readShort()); // 跳过文件中“又是一个UTF字符串”所占字节,注意readShort()方法会移动文件指针,所以不用加2。
System.out.println(file.readFloat());
//以下演示文件复制操作
System.out.println("——————文件复制(从file到fileCopy)——————");
file.seek(0);
RandomAccessFile fileCopy=new RandomAccessFile("fileCopy","rw");
int len=(int)file.length();//取得文件长度(字节数)
byte[] b=new byte[len];
file.readFully(b);
fileCopy.write(b);
System.out.println("复制完成!");
}
}
RandomAccessFile 插入写示例:
[java] view plaincopy
/**
*
* @param skip 跳过多少过字节进行插入数据
* @param str 要插入的字符串
* @param fileName 文件路径
*/
public static void beiju(long skip, String str, String fileName){
try {
RandomAccessFile raf = new RandomAccessFile(fileName,"rw");
if(skip < 0 || skip > raf.length()){
System.out.println("跳过字节数无效");
return;
}
byte[] b = str.getBytes();
raf.setLength(raf.length() + b.length);
for(long i = raf.length() - 1; i > b.length + skip - 1; i--){
raf.seek(i - b.length);
byte temp = raf.readByte();
raf.seek(i);
raf.writeByte(temp);
}
raf.seek(skip);
raf.write(b);
raf.close();
} catch (Exception e) {
e.printStackTrace();
}
}
利用RandomAccessFile实现文件的多线程下载,即多线程下载一个文件时,将文件分成几块,每块用不同的线程进行下载。下面是一个利用多线程在写文件时的例子,其中预先分配文件所需要的空间,然后在所分配的空间中进行分块,然后写入:
[java] view plaincopy
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* 测试利用多线程进行文件的写操作
*/
public class Test {
public static void main(String[] args) throws Exception {
// 预分配文件所占的磁盘空间,磁盘中会创建一个指定大小的文件
RandomAccessFile raf = new RandomAccessFile("D://abc.txt", "rw");
raf.setLength(1024*1024); // 预分配 1M 的文件空间
raf.close();
// 所要写入的文件内容
String s1 = "第一个字符串";
String s2 = "第二个字符串";
String s3 = "第三个字符串";
String s4 = "第四个字符串";
String s5 = "第五个字符串";
// 利用多线程同时写入一个文件
new FileWriteThread(1024*1,s1.getBytes()).start(); // 从文件的1024字节之后开始写入数据
new FileWriteThread(1024*2,s2.getBytes()).start(); // 从文件的2048字节之后开始写入数据
new FileWriteThread(1024*3,s3.getBytes()).start(); // 从文件的3072字节之后开始写入数据
new FileWriteThread(1024*4,s4.getBytes()).start(); // 从文件的4096字节之后开始写入数据
new FileWriteThread(1024*5,s5.getBytes()).start(); // 从文件的5120字节之后开始写入数据
}
// 利用线程在文件的指定位置写入指定数据
static class FileWriteThread extends Thread{
private int skip;
private byte[] content;
public FileWriteThread(int skip,byte[] content){
this.skip = skip;
this.content = content;
}
public void run(){
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile("D://abc.txt", "rw");
raf.seek(skip);
raf.write(content);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
raf.close();
} catch (Exception e) {
}
}
}
}
}
RandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,并进行读写了。这些记录的大小不必相同;但是其大小和位置必须是可知的。但是该类仅限于操作文件。
RandomAccessFile不属于InputStream和OutputStream类系的。实际上,除了实现DataInput和DataOutput接口之外(DataInputStream和DataOutputStream也实现了这两个接口),它和这两个类系毫不相干,甚至不使用InputStream和OutputStream类中已经存在的任何功能;它是一个完全独立的类,所有方法(绝大多数都只属于它自己)都是从零开始写的。这可能是因为RandomAccessFile能在文件里面前后移动,所以它的行为与其它的I/O类有些根本性的不同。总而言之,它是一个直接继承Object的,独立的类。
基本上,RandomAccessFile的工作方式是,把DataInputStream和DataOutputStream结合起来,再加上它自己的一些方法,比如定位用的getFilePointer( ),在文件里移动用的seek( ),以及判断文件大小的length( )、skipBytes()跳过多少字节数。此外,它的构造函数还要一个表示以只读方式("r"),还是以读写方式("rw")打开文件的参数 (和C的fopen( )一模一样)。它不支持只写文件。
只有RandomAccessFile才有seek搜寻方法,而这个方法也只适用于文件。BufferedInputStream有一个mark( )方法,你可以用它来设定标记(把结果保存在一个内部变量里),然后再调用reset( )返回这个位置,但是它的功能太弱了,而且也不怎么实用。
RandomAccessFile的绝大多数功能,但不是全部,已经被JDK 1.4的nio的"内存映射文件(memory-mapped files)"给取代了,你该考虑一下是不是用"内存映射文件"来代替RandomAccessFile了。
[java] view plaincopy
import java.io.IOException;
import java.io.RandomAccessFile;
public class TestRandomAccessFile {
public static void main(String[] args) throws IOException {
RandomAccessFile rf = new RandomAccessFile("rtest.dat", "rw");
for (int i = 0; i < 10; i++) {
//写入基本类型double数据
rf.writeDouble(i * 1.414);
}
rf.close();
rf = new RandomAccessFile("rtest.dat", "rw");
//直接将文件指针移到第5个double数据后面
rf.seek(5 *;
//覆盖第6个double数据
rf.writeDouble(47.0001);
rf.close();
rf = new RandomAccessFile("rtest.dat", "r");
for (int i = 0; i < 10; i++) {
System.out.println("Value " + i + ": " + rf.readDouble());
}
rf.close();
}
}
内存映射文件
内存映射文件能让你创建和修改那些因为太大而无法放入内存的文件。有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问。这种解决办法能大大简化修改文件的代码。
fileChannel.map(FileChannel.MapMode mode, long position, long size)将此通道的文件区域直接映射到内存中。注意,你必须指明,它是从文件的哪个位置开始映射的,映射的范围又有多大;也就是说,它还可以映射一个大文件的某个小片断。
MappedByteBuffer是ByteBuffer的子类,因此它具备了ByteBuffer的所有方法,但新添了force()将缓冲区的内容强制刷新到存储设备中去、load()将存储设备中的数据加载到内存中、isLoaded()位置内存中的数据是否与存储设置上同步。这里只简单地演示了一下put()和get()方法,除此之外,你还可以使用asCharBuffer( )之类的方法得到相应基本类型数据的缓冲视图后,可以方便的读写基本类型数据。
[java] view plaincopy
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class LargeMappedFiles {
static int length = 0x8000000; // 128 Mb
public static void main(String[] args) throws Exception {
// 为了以可读可写的方式打开文件,这里使用RandomAccessFile来创建文件。
FileChannel fc = new RandomAccessFile("test.dat", "rw").getChannel();
//注意,文件通道的可读可写要建立在文件流本身可读写的基础之上
MappedByteBuffer out = fc.map(FileChannel.MapMode.READ_WRITE, 0, length);
//写128M的内容
for (int i = 0; i < length; i++) {
out.put((byte) 'x');
}
System.out.println("Finished writing");
//读取文件中间6个字节内容
for (int i = length / 2; i < length / 2 + 6; i++) {
System.out.print((char) out.get(i));
}
fc.close();
}
}
尽管映射写似乎要用到FileOutputStream,但是映射文件中的所有输出 必须使用RandomAccessFile,但如果只需要读时可以使用FileInputStream,写映射文件时一定要使用随机访问文件,可能写时要读的原因吧。
该程序创建了一个128Mb的文件,如果一次性读到内存可能导致内存溢出,但这里访问好像只是一瞬间的事,这是因为,真正调入内存的只是其中的一小部分,其余部分则被放在交换文件上。这样你就可以很方便地修改超大型的文件了(最大可以到2 GB)。注意,Java是调用操作系统的"文件映射机制"来提升性能的。
RandomAccessFile类的应用:
[java] view plaincopy
/*
* 程序功能:演示了RandomAccessFile类的操作,同时实现了一个文件复制操作。
*/
package com.lwj.demo;
import java.io.*;
public class RandomAccessFileDemo {
public static void main(String[] args) throws Exception {
RandomAccessFile file = new RandomAccessFile("file", "rw");
// 以下向file文件中写数据
file.writeInt(20);// 占4个字节
file.writeDouble(8.236598);// 占8个字节
file.writeUTF("这是一个UTF字符串");// 这个长度写在当前文件指针的前两个字节处,可用readShort()读取
file.writeBoolean(true);// 占1个字节
file.writeShort(395);// 占2个字节
file.writeLong(2325451l);// 占8个字节
file.writeUTF("又是一个UTF字符串");
file.writeFloat(35.5f);// 占4个字节
file.writeChar('a');// 占2个字节
file.seek(0);// 把文件指针位置设置到文件起始处
// 以下从file文件中读数据,要注意文件指针的位置
System.out.println("——————从file文件指定位置读数据——————");
System.out.println(file.readInt());
System.out.println(file.readDouble());
System.out.println(file.readUTF());
file.skipBytes(3);// 将文件指针跳过3个字节,本例中即跳过了一个boolean值和short值。
System.out.println(file.readLong());
file.skipBytes(file.readShort()); // 跳过文件中“又是一个UTF字符串”所占字节,注意readShort()方法会移动文件指针,所以不用加2。
System.out.println(file.readFloat());
//以下演示文件复制操作
System.out.println("——————文件复制(从file到fileCopy)——————");
file.seek(0);
RandomAccessFile fileCopy=new RandomAccessFile("fileCopy","rw");
int len=(int)file.length();//取得文件长度(字节数)
byte[] b=new byte[len];
file.readFully(b);
fileCopy.write(b);
System.out.println("复制完成!");
}
}
RandomAccessFile 插入写示例:
[java] view plaincopy
/**
*
* @param skip 跳过多少过字节进行插入数据
* @param str 要插入的字符串
* @param fileName 文件路径
*/
public static void beiju(long skip, String str, String fileName){
try {
RandomAccessFile raf = new RandomAccessFile(fileName,"rw");
if(skip < 0 || skip > raf.length()){
System.out.println("跳过字节数无效");
return;
}
byte[] b = str.getBytes();
raf.setLength(raf.length() + b.length);
for(long i = raf.length() - 1; i > b.length + skip - 1; i--){
raf.seek(i - b.length);
byte temp = raf.readByte();
raf.seek(i);
raf.writeByte(temp);
}
raf.seek(skip);
raf.write(b);
raf.close();
} catch (Exception e) {
e.printStackTrace();
}
}
利用RandomAccessFile实现文件的多线程下载,即多线程下载一个文件时,将文件分成几块,每块用不同的线程进行下载。下面是一个利用多线程在写文件时的例子,其中预先分配文件所需要的空间,然后在所分配的空间中进行分块,然后写入:
[java] view plaincopy
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* 测试利用多线程进行文件的写操作
*/
public class Test {
public static void main(String[] args) throws Exception {
// 预分配文件所占的磁盘空间,磁盘中会创建一个指定大小的文件
RandomAccessFile raf = new RandomAccessFile("D://abc.txt", "rw");
raf.setLength(1024*1024); // 预分配 1M 的文件空间
raf.close();
// 所要写入的文件内容
String s1 = "第一个字符串";
String s2 = "第二个字符串";
String s3 = "第三个字符串";
String s4 = "第四个字符串";
String s5 = "第五个字符串";
// 利用多线程同时写入一个文件
new FileWriteThread(1024*1,s1.getBytes()).start(); // 从文件的1024字节之后开始写入数据
new FileWriteThread(1024*2,s2.getBytes()).start(); // 从文件的2048字节之后开始写入数据
new FileWriteThread(1024*3,s3.getBytes()).start(); // 从文件的3072字节之后开始写入数据
new FileWriteThread(1024*4,s4.getBytes()).start(); // 从文件的4096字节之后开始写入数据
new FileWriteThread(1024*5,s5.getBytes()).start(); // 从文件的5120字节之后开始写入数据
}
// 利用线程在文件的指定位置写入指定数据
static class FileWriteThread extends Thread{
private int skip;
private byte[] content;
public FileWriteThread(int skip,byte[] content){
this.skip = skip;
this.content = content;
}
public void run(){
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile("D://abc.txt", "rw");
raf.seek(skip);
raf.write(content);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
raf.close();
} catch (Exception e) {
}
}
}
}
}
发表评论
-
java远程调试(转载)
2012-12-29 16:43 864新接手的项目采用的是Maven作为编译管理工具,项目内容则是按 ... -
将秒转换成日期格式的java方法:
2012-12-29 12:01 928package net.blogjava.frankieg ... -
java对世界各个时区(TimeZone)的通用转换处理方法(转载)
2012-12-25 15:24 945在进行国际性软件项目开发的过程中,有时候会碰到一些比较特殊的要 ... -
java-WEB中的过滤器Filter
2012-09-18 22:58 1425过滤器是一个程序,它先于与之相关的s ... -
java-例子:MVC模式,用jstl和el输出数据到jsp页面.
2012-09-09 23:57 1611例子:利用session完成购物车. domain: pac ... -
java中的el——表达式语言
2012-09-09 23:36 830EL 全名为 Expression Lang ... -
java-下载图片(正则表达式、HttpURLConnection、流、socket综合运用)
2012-08-26 22:22 1260package cn.itcast.httpserver; ... -
java-用HttpURLConnection发送Http请求.
2012-08-26 22:00 685注意:利用URL发送的请求,服务器只返回实体部分,不包括htt ... -
java-模拟tomcat服务器
2012-08-26 21:57 1093模拟tomcat服务器端代码示例:package cd.itc ... -
java-SAX解析XML示例
2012-08-25 19:13 789JAVA 解析 XML 通常有两种方式:DOM 和SAX ... -
java-增强for循环示例
2012-08-25 19:14 795package cd.itcast.day1; impo ... -
java-反射示例
2012-08-24 14:13 669package cd.itcast.day1; im ... -
java-可变参数示例
2012-08-24 14:07 509package cd.itcast.day1; pu ... -
java-枚举示例
2012-08-24 14:04 666package cd.itcast.day1; /* ... -
java-注解annotation
2012-08-24 13:54 685package cd.itcast.day2; impo ... -
Java-dom编程:操作xml
2012-08-24 13:47 711package cd.itcast.day3.xmldom; ...
相关推荐
使用RandomAccessFile流将一个文本文件读出,并导致写入到另一个文件当中。
RandomAccessFile类的用法.docRandomAccessFile类的用法.docRandomAccessFile类的用法.doc
Java中正确使用RandomAccessFile向文件中写入中文
RandomAccessFile(下).mp4
在JAVA程序设计不少涉及到对文件的读写操作,本例针对这方面的问题,介绍RandomAccessFile类的文件读写操作,文件中包含有1个java文件和1个class文件
文件操作——File 、 RandomAccessFile(上).mp4
RandomAccessFile处理文件的案例
NIO_RandomAccessFile_多线程读本地CSV文件(java==> google guava包ListenableFuture) reader里有个main函数,更改文件路径后,直接运行即可
因为使用其他文件流修改文件时是整体的替换,导致SVN上传上去后是整个文件都修改了,所以需要增量修改,这个demo是使用RandomAccessFile增量修改,只修改指定的行,很实用
花1K内存实现高效I-O的RandomAccessFile类 自己搜搜这个关键字. 我主要是用来优化Android上多线程断点下载的写文件效率 RandomAccessFile是操作硬盘的,比操作内存的数据慢了几百万倍, 所有有人做出优化,我特上传...
文件操作——File 、 RandomAccessFile(上).mp4
RandomAccessFile 解决乱码
【IT十八掌徐培成】Java基础第16天-01.RandomAccessFile.zip
RandomAccessFile随机文本,使用多线程处理复制文件
体会RandomAccessFile随机访问文件的用法
java api中的java.io.RandomAccessFile类实现文件的随机写入.
NULL 博文链接:https://baihe747.iteye.com/blog/2124747
NULL 博文链接:https://x7700.iteye.com/blog/1003918
递归 正则表达示 RandomAccessFile 结合
RandomAccessFile 对文件操作,很好用的哟