RandomAccessFile特点
1、只能访问文件,不能操作其他io设备
2、支持随机访问
3、在读写等长记录文件有优势
RandomAccessFile请注意乱码问题:
使用write(String.getBytes()), 能够正常写入
使用writeBytes(String), writeChars(String), writeUTF(String)均产生乱码。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案例一:
写一个线程,来接受主类传递过来的file,然后进行处理。这里使用的是使用write(String.getBytes()),不会有乱码
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.RandomAccessFile;
public class RandomThere02 extends Thread{
/*
*
*使用RandomAccessFile向数据库写入中文的时候,
*使用write(String.getBytes()), 能够正常写入
*使用writeBytes(String), writeChars(String), writeUTF(String)均产生乱码。
* */
File files;
int modules = 1;
// int num = 10;
public RandomThere02(File file,int m) {
files = file;
modules = m;
}
@Override
public void run() {
try {
RandomAccessFile rA = new RandomAccessFile(files,"rw");
String ss = "我是一只鱼---+\r\n";
//根据ss内容来计算指针的位置
rA.seek((modules-1)*ss.getBytes().length);
rA.write(ss.getBytes("gb2312"));
rA.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
主类代码
import java.io.File;
public class RandomAccessFileText02 {
/*
* RandomAccessFile随机文件读写
* */
static File file = new File("d://data//newhello.txt");
public static void main(String[] args) {
if(file.exists()){
file.delete();
}else {
System.out.println("dadfasfafsadf好烦啊");
new RandomThere02(file, 1).start();
new RandomThere02(file, 2).start();
new RandomThere02(file, 3).start();
new RandomThere02(file, 4).start();
new RandomThere02(file, 5).start();
}
}
}
结果:
RandomAccessFile案例二,实现多线程下载文件,并复制成一个新文件:
写一个线程,
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.RandomAccessFile;
public class RandomThere01 implements Runnable{
/*
*
*使用RandomAccessFile向数据库写入中文的时候,
*使用write(String.getBytes()), 能够正常写入
*使用writeBytes(String), writeChars(String), writeUTF(String)均产生乱码。
* */
private String source;
private String dest;
private int buflen=1024*1024;
private int threadnum;//定义线程个数
private Thread thread[];//定义线程数组
public RandomThere01(String source,String dest)
{
this.source=source;
this.dest=dest;
}
public RandomThere01(String source,String dest,int threadnum)
{
this.source=source;
this.dest=dest;
this.threadnum=threadnum;
}
public void getThread()
{
thread = new Thread[threadnum];
for(int i=0;i<thread.length;i++)
{
thread[i]=new Thread(this);
thread[i].setName(i+"");//设置线程的名字,用于区分其他线程
}
}
public void run()
{
int id=Integer.valueOf(Thread.currentThread().getName());
byte buffer[] = new byte [buflen];
try {
RandomAccessFile reader=new RandomAccessFile(source,"r");//为每个线程定义一个读取的对象
RandomAccessFile writer= new RandomAccessFile(dest,"rw");
long alone=reader.length()%threadnum==0?reader.length()/threadnum:((int)(Math.ceil((double)reader.length()/threadnum)));//计算每个线程应该读取的长度
long begin=id*alone; //第个线程读取文件的开始位置
reader.seek(begin);//定位到开始位置
writer.seek(begin);
long end=(begin+alone)>reader.length()?reader.length():(begin+alone);//计算每个线程的结束位置
while(begin<end)
{
int len=0;
if(begin+buflen<end)//如果可以装满一个缓冲区
{
len=reader.read(buffer);
}else
{
len=reader.read(buffer,0,(int)(end-begin));
}
writer.write(buffer,0,len);
begin+=len;
System.out.println("Thread-"+id+"get "+len);
}
}catch(Exception ex)
{
System.out.println(ex);
}
}
public int getThreadNumber()
{
return this.thread.length;
}
public void start()
{
for(int i=0;i<thread.length;i++)
thread[i].start();
}
}
主类代码
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileText01 {
public static void main(String[] args) throws Exception {
// 第一个参数,你的源文件,第二个参数:你需要复制的位置,第三个文件:开启多少个线程
long begin=System.currentTimeMillis();
RandomThere01 load = new RandomThere01("d:\\abc.txt","D:\\abc_new.txt",5);
//调用getThread()方法为每一个线程赋值,用于计算偏移量
load.getThread();
//开启线程进行数据下载
load.start();
//当完成下载我们计算一下我们所有的耗时
while(true)
{
if(Thread.activeCount()==1)
{
long end=System.currentTimeMillis();
System.out.println("多线程:Download successfully..."+(end-begin)+"ms");
break;
}
}
System.out.println("开始");
}
}
运行结果:成功