-------android培训、java培训、期待与您交流! ----------
此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过getFilePointer
方法读取,并通过 seek
方法设置。
通常,如果此类中的所有读取例程在读取所需数量的字节之前已到达文件末尾,则抛出 EOFException
(是一种 IOException
)。如果由于某些原因无法读取任何字节,而不是在读取所需数量的字节之前已到达文件末尾,则抛出IOException
,而不是 EOFException
。需要特别指出的是,如果流已被关闭,则可能抛出 IOException
。
package com.hu;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* RandomAccessFile
*
* 该类不是算是IO体系中的子类。
* 而且直接继承自Object。
*
* 但是它是IIO包中的成员。因为它具备读和写的功能。
* 内部封装了一个数组,而且通过指针对数组的元素进行操作。
* 可以通过getFilePointer获取指针位置。
* 同时可以通过seek该表指针的位置。
*
* 其实完成读写的原理就是内部封装了字节输出流和输入流
*
* 通过鼓噪函数可以看出,该类只能操作文件
* @author Sunday
*
*/
public class RandomAccessFileDemo {
public static void main(String[] args) {
try {
// writeFile();
readFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void readFile() throws IOException{
RandomAccessFile raf = new RandomAccessFile("ran.txt", "rw");
byte[] buf = new byte[4];
raf.read(buf);
String name = new String(buf);
System.out.println("name="+name);
int age = raf.readInt();
System.out.println("age="+age);
raf.close();
}
public static void writeFile() throws IOException{
RandomAccessFile raf = new RandomAccessFile("ran.txt", "rw");
raf.write("李四".getBytes());
raf.writeInt(97);
raf.close();
}
}
利用RandomAccessFile,创建多线程下载文件:
public class Downloader {
public final static String DOWNLOAD_URL = "127.0.0.1";
public final static String DOWNLOAD_PORT = "8082";
private int fileLen;
private Handler handler;
private boolean exit;
File didiMusicFile = new File(Environment.getExternalStorageDirectory()
+ File.separator + "didiMusic");
private Lists lists;
int fileCount = 0;
Object object = new Object();
private int thCount=0;
private final static String TAG = "Downloader";
public Downloader(Context context, Handler handler, Lists lists) {
this.handler = handler;
this.lists = lists;
}
/**
* 多线程下载
*
* @param path
* 下载路径
* @param thCount
* 需要开启多少个线程
* @throws Exception
*/
public void download(String path, int thCount) {
this.thCount = thCount;
// String prex = "http://127.0.0.1:8082";
String uri = "http://" + DOWNLOAD_URL + ":" + DOWNLOAD_PORT + path;
try {
String temp = URLEncoder.encode(uri, "utf-8").replaceAll("\\+",
"%20");
uri = temp.replaceAll("%3A", ":").replaceAll("%2F", "/");
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Log.d(TAG, "get request uri:" + uri);
try {
URL url = new URL(uri);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.connect();
Log.d(TAG, "get responsed code:" + conn.getResponseCode());
// 设置超时时间
if (conn.getResponseCode() == 200) {
fileLen = conn.getContentLength();
Log.i(TAG, "get request file length:" + fileLen);
//内存不足,显示对话框
if(isShortMemory(fileLen/1024/1024)){
handler.sendEmptyMessage(5);
return;
}
String name = path.substring(path.lastIndexOf("/") + 1);
File file = new File(didiMusicFile, name);
if (!file.exists()) {
file.createNewFile();
}
RandomAccessFile raf = new RandomAccessFile(file, "rws");
raf.setLength(fileLen);
raf.close();
Log.i("file length:", "file 1 length:" + file.length());
// 计算每个线程下载的字节数
long partLen = (fileLen + thCount - 1) / thCount;
long startTemp = partLen;
for (int i = 0; i < thCount; i++) {
startTemp = partLen * i;
if (i == thCount - 1) {
long lastlen = fileLen - i * partLen;
new DownloadThread(url, file, startTemp, lastlen, i)
.start();
Log.i("tag", "lastlen" + lastlen + " " + i);
} else {
new DownloadThread(url, file, startTemp, partLen, i)
.start();
Log.i("tag", "partlen:" + partLen + " " + i);
}
}
Log.i("file length:", "file 2 length:" + file.length());
// new DownloadThread(url, file, partLen, partLen,2).start();
// new DownloadThread(url, file, partLen * 2, fileLen -
// partLen,3)
// .start();
} else {
Log.i(TAG, "code:" + conn.getResponseCode());
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
handler.sendEmptyMessage(3);
}
}
class DownloadThread extends Thread {
File file;
long start;
long fileLen;
URL url;
private int curr;
public DownloadThread(URL url, File file, long start, long fileLen,
int curr) {
// TODO Auto-generated constructor stub
this.url = url;
this.file = file;
this.start = start;
this.fileLen = fileLen;
this.curr = curr;
}
private synchronized void addFileCount(){
fileCount++;
Log.i(TAG, "fileCount:"+fileCount);
if (fileCount % thCount==0) {
// 下载完成,通知继续下载下一个任务
if (!getExit()) {
handler.sendEmptyMessage(4);
}
}
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
try {
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setReadTimeout(5000);
// 分段请求
conn.setRequestProperty("Range", "bytes=" + this.start + "-"
+ (this.start + fileLen - 1));
// 开始读写数据
InputStream in = conn.getInputStream();
RandomAccessFile raf = new RandomAccessFile(file, "rws");
Log.i("start", start + "");
raf.seek(start);
byte[] buff = new byte[1024 * 512];
int len = 0, lengthCount = 0;
while (!getExit() && ((len = in.read(buff)) != -1)) {
raf.write(buff, 0, len);
lengthCount += len;
Log.i(TAG, "thread:" + curr + "receive file length:"
+ lengthCount + " " + len);
if (lengthCount == fileLen) {
Log.i(TAG, "thread:" + curr
+ " receive total length:" + lengthCount);
break;
}
}
raf.close();
Log.i("file", file.length() + "");
conn.disconnect();
addFileCount();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 退出下载
*/
public void exit() {
this.exit = true;
}
public boolean getExit() {
return this.exit;
}
private boolean isShortMemory(int fileLen2){
return (Util.getSDFreeSize()-fileLen2)<100;
}