RandomAccessFile##
RandomAccessFile类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为 文件指针 ;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。
*该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法设置。
RandomAccessFile实现了数据输入输出流的接口;可以随机存储硬盘的文件,但是来自网络的文件就不行
RandomAccessFile的工作方式是,把DataInputStream和DataOutputStream结合起来,再加上它自己的一些方法,比如定位用的getFilePointer( ),在文件里移动用的seek( ),以及判断文件大小的length( )、skipBytes()跳过多少字节数。此外,它的构造函数还要一个表示以只读方式("r"),还是以读写方式("rw")打开文件
package randomfile;
import java.io.RandomAccessFile;
public class Example {
public static void main(String[] args) throws Exception {
RandomAccessFile afile = new RandomAccessFile("randomfile", "rw");
String[] type = new String[4];
type[0] = "php";
type[1] = "java";
type[2] = "c++";
type[3] = "测试中文adc";
afile.writeUTF(type[0]);
afile.writeUTF(type[1]);
afile.writeUTF(type[2]);
afile.writeUTF(type[3]);
afile.seek(afile.length());
afile.writeUTF("c");
afile.seek(0);
while(afile.getFilePointer()<afile.length()){
System.out.println(afile.readUTF());
}
}
}
以上 代码实现的是文件后面追加
这里有个问题:使用writeUTF 会导致文字乱码(我已经指定编码是UTF-8) 在我电脑中显示的是:
解决方法是 尽量用 write(byte[]) 这个方法写 原理参考:
1、String.getBytes()将会按照当前系统默认的encoding方式获得字符串的 Bytes,RandomAccessFile.write(byte[])将这个byte数组正确写入。由于写入的实际就是Windows平台的 nativecode编码,所以文件还能够被正确的阅读。
2、RandomAccessFile.writeBytes(String)将字符串的各个字符(当然是用unicode编码的)的高8位去掉,写入文件。
3、RandomAccessFile.writeChars(String)将字符串的各个字符按照unicode的编码,以Big-endian的方式写入文件。Windows平台上默认文件的编码方式为Little-endian,所以用写字板打开看到的是乱码,但是如果我们用浏览器打开这个文件(testWriteChars.dat)并指定编码方式为Unicode Big-endian,就能看到正常的“中”字了。
4、RandomAccessFile.writeUTF(String)首先写入00 03表示其后将写入3个实际的字节,然后写入“中”的UTF-8编码:E4 B8 AD
通过上面的分析,我建议如果使用RandomAccessFile来写入中文的话,最好用 RandomAccessFile.write(String.getBytes())的方式,如果为了保险起见,还可以进一步指定运行平台的默认 nativecode编码方式,例如使用:RandomAccessFile.write(String.getBytes("gb2312"))
参考 http://www.osedu.net/article/linux/2011-06-30/250.html
RandomAccessFile 随意写测试:
package randomfile;
import java.io.RandomAccessFile;
public class Example {
public static void main(String[] args) throws Exception {
RandomAccessFile afile = new RandomAccessFile("randomfile", "rw");
String[] type = new String[4];
type[0] = "php";
type[1] = "java";
type[2] = "c++";
type[3] = "测试中文adc";
afile.write(type[0].getBytes());
afile.write(type[1].getBytes());
afile.write(type[2].getBytes());
afile.write(type[3].getBytes());
afile.seek(0);
afile.write("c".getBytes());
afile.seek(0);
byte[] buffer = new byte[1024];
int readCount = 0;
while ((readCount=afile.read(buffer))!=-1) {
System.out.print(new String(buffer,0,readCount));
}
}
}
这里可以看出RandomAccessFile 写的时候会覆盖以前的内容
RandomAccessFile 实现插入
package randomfile;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
public class Example2 {
public static void main(String[] args) throws Exception {
File temp = File.createTempFile("test", "temp");
temp.deleteOnExit();
FileInputStream fin = new FileInputStream(temp);
FileOutputStream fout = new FileOutputStream(temp);
RandomAccessFile rFile = new RandomAccessFile("randomfile", "rw");
rFile.seek(0);
byte[] buffer=new byte[1024];
int readCount=0;
while((readCount=rFile.read(buffer))!=-1){
fout.write(buffer, 0, readCount);
}
rFile.seek(0);
rFile.write("test插入".getBytes());
while((readCount=fin.read(buffer))!=-1){
rFile.write(buffer, 0, readCount);
}
}
}
这里使用了File的临时文件:
File 的 createTempFile() 方法
该方法有两种调用方式:
createTempFile(String prefix, String suffix);
在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称。
createTempFile(String prefix, String suffix, File directory);
在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。
File file2 = new File("D: emp");// D;/temp 为一个目录
File tempFile1= file2.createTempFile("msg", ".tmp",file2);
File tempFile2 = file2.createTempFile("msg", ".tmp");
System.out.println(tempFile2.getAbsolutePath());
可以这么认为,createTempFile() 方法,在指定的目录下创建一个temp文件,directory 类型为File ,如果路径不存在,则创建失败。createTempFile(String prefix, String suffix);方法默认的保存路径为:C:Documents and SettingsAdministratorLocal SettingsTemp 。
可以看出其实插入操作 只要数据上了一定大小,是很耗费时间的和内存的(临时的文件的内存)
可以尝试使用RandomAccessFile实现多线程的续点下载
**RandomAccessFile的绝大多数功能,但不是全部,已经被JDK 1.4的nio的"内存映射文件(memory-mapped files)"给取代了,你该考虑一下是不是用"内存映射文件"来代替RandomAccessFile了。 **