最近突发奇想java能不能快速创建固定大小的文件,类似迅雷下载的时候会先创建一个和下载文件同样大小的文件占位,以避免空间不足下载失败。
在网上搜索一番发现提出这个问题的还真不少,但是很少就解决办法,最多的解决办法就是循环向文件里面入固定大小的空字节,但这个方法的弊端就是创建大文件很费力,我试了创建2GB的文件大概需要50秒左右,最快也要三四十秒,再大的文件就更慢了,这也许跟我电脑配置有关系,但是这跟迅雷那种瞬间创建文件实在是相差太多了。
这使得我很沮丧,但是昨天无意间发现java有一个类:FileChannel,查阅API发现通过这个类来实现复制文件比简单的循环读取写入可能会高效得多,很多操作系统可将字节直接从文件系统缓存传输到目标通道,而无需实际复制各字节。这使我想到使用它能不能快速的创建大文件呢!所以我写了一个测试方法,结果让我大吃一惊,创建一个2GB的大文件只需要90毫秒,你没看错,是毫秒,我试了创建更大的文件10GB,20GB,150GB,所用时间都是100毫秒左右,太令人吃惊了。这种快乐的事情当然要分享给大家了下面进入正题。
通过FileChannel类的 int write(ByteBuffer src, long position) throws IOException 方法可以在指定position位置写入字节,position大于文件长度的话,前面的部分会填充为空字节0。我们这种创建固定大小的空文件之需要在最后一个位置写入一个空字节0就可以使文件扩大到我们想要的长度,下面是我写的测试。
/**
* 创建固定大小的文件
* @param file
* @param length
* @throws IOException
*/
public static void createFixLengthFile(File file, long length) throws IOException{
long start = System.currentTimeMillis();
FileOutputStream fos = null;
FileChannel output = null;
try {
fos = new FileOutputStream(file);
output = fos.getChannel();
output.write(ByteBuffer.allocate(1), length-1);
} finally {
try {
if (output != null) {
output.close();
}
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println("total times "+(end-start));
}
写了这么多是想跟大家分享一下自己的发现与学习的过程,在技术的道路上充满乐趣,不断发现,不断探索,乐在其中。
2013-08-26:今天发现 RandomAccessFile 能够更方便,更直观的实现,两者效率相差无几,但这应该是更推荐的一种方式。
public static void create(File file, long length) throws IOException{
long start = System.currentTimeMillis();
RandomAccessFile r = null;
try {
r = new RandomAccessFile(file, "rw");
r.setLength(length);
} finally{
if (r != null) {
try {
r.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
long end = System.currentTimeMillis();
System.out.println(end-start);
}
假如帮到你的话,请留下你的评论。欢迎转载(请标明出处),希望能帮助到更多的人。
本文分享了使用Java的FileChannel类高效创建大文件的方法,相较于传统的循环读写方式,FileChannel类能显著提高创建速度,仅需毫秒级时间。文中还对比了RandomAccessFile的使用,并提供了具体的代码示例。
3319

被折叠的 条评论
为什么被折叠?



