最近做一个项目,需要多线程去创建文件。
用到RandomAccessFile类
RandomAccessFile是Java输入/输出流体系中功能最丰富的文件内容访问类,既可以读取文件内容,也可以向文件输出数据。与普通的输入/输出流不同的是,RandomAccessFile支持跳到文件任意位置读写数据,RandomAccessFile对象包含一个记录指针,用以标识当前读写处的位置,当程序创建一个新的RandomAccessFile对象时,该对象的文件记录指针对于文件头(也就是0处),当读写n个字节后,文件记录指针将会向后移动n个字节。除此之外,RandomAccessFile可以自由移动该记录指针
RandomAccessFile包含两个方法来操作文件记录指针:
- long getFilePointer():返回文件记录指针的当前位置
- void seek(long pos):将文件记录指针定位到pos位置
RandomAccessFile类在创建对象时,除了指定文件本身,还需要指定一个mode参数,该参数指定RandomAccessFile的访问模式,该参数有如下四个值:
- r:以只读方式打开指定文件。如果试图对该RandomAccessFile指定的文件执行写入方法则会抛出IOException
- rw:以读取、写入方式打开指定文件。如果该文件不存在,则尝试创建文件
- rws:以读取、写入方式打开指定文件。相对于rw模式,还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备,默认情形下(rw模式下),是使用buffer的,只有cache满的或者使用RandomAccessFile.close()关闭流的时候儿才真正的写到文件
- rwd:与rws类似,只是仅对文件的内容同步更新到磁盘,而不修改文件的元数据
以上我觉得比较重要,需要知道,不多说,上代码
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import java.io.File;
public class CreateFile extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = CreateFile.class.getSimpleName();
@Override
protected void onCreate(Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
setContentView(R.layout.create_file);
Button startButton = findViewById(R.id.create_file_button);
startButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
int threadNum = 8;
int fileSize = 1024 * 1024;
createFile(threadNum, fileSize);
}
private void createFile(int threadID, int fileSize) {
String folderPath = Environment.getExternalStorageDirectory().getPath() + File.separator + "demoTest" + File.separator;
Log.d(TAG, "create file path : " + folderPath);
File file = new File(folderPath);
if (!file.exists() && !file.isDirectory()) {
file.mkdirs();
}
//创建大小是1G的文件
MoreThreadCreateFile moreThreadCreateFile = new MoreThreadCreateFile(folderPath + "aa.txt", fileSize, threadID);
moreThreadCreateFile.start();
}
class MoreThreadCreateFile extends Thread {
private String mFilePath;
private int mFileSize;
private int mThreadNum;
MoreThreadCreateFile(String filePath, int fileSize, int threadNum) {
mFilePath = filePath;
mFileSize = fileSize;
mThreadNum = threadNum;
}
@Override
public void run() {
//todo
FileCreateThread[] threads = new FileCreateThread[mThreadNum];
try {
int blockSize = (mFileSize % mThreadNum) == 0 ? mFileSize / mThreadNum : mFileSize / mThreadNum + 1;
File file = new File(mFilePath);
for (int i = 0; i < threads.length; i++) {
threads[i] = new FileCreateThread(file, blockSize, i + 1);
threads[i].setName("Thread:" + i);
threads[i].start();
}
Log.d(TAG, "file create is complete!!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
import android.util.Log;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
class FileCreateThread extends Thread {
private static final String TAG = FileCreateThread.class.getSimpleName();
//线程创建的长度
private int mFileLenth;
//文件路径
private File mFile;
//线程ID
private int mThreadId;
//线程下载的长度
private int mBlockSize;
public FileCreateThread(File file, int blockSize, int threadId) {
mFile = file;
mBlockSize = blockSize;
mThreadId = threadId;
}
@Override
public void run() {
RandomAccessFile raf = null;
try {
int startPos = mBlockSize * (mThreadId - 1);//开始位置
int endPos = mBlockSize * mThreadId - 1; //结束位置
//文件的长度
mFileLenth = endPos - startPos;
Log.d(TAG, "mFileLenth =" + mFileLenth);
raf = new RandomAccessFile(mFile, "rwd");
raf.seek(startPos);
int len = 0;
while (len < mFileLenth / 128 + 1) {
raf.write(buffer1K());
len++;
}
isCompleted = true;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (raf != null) {
try {
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private byte[] buffer1K() {
byte[] by = new byte[128];
for (int item = 0; item < by.length; item++) {
by[item++] = 0x5;
by[item] = 0xA;
}
return by;
}
}
参考博客: