开始处理
作为一个停留在JDK1.6版本的老Javaer来说,做这件事第一印象就是File#listFiles方法,来动手。
public static void main(String[] args) {
System.out.println("系统启动");
FileTravel travel = new FileTravel(new File("D:/"));
long start = System.currentTimeMillis();
travel.travel();
long end = System.currentTimeMillis();
System.out.println("耗时:" + ((end - start) / 1000));
}
public class FileTravel {
public boolean finish = false;
public File currentFile = null;
public int currentForderCnt = 0;
public int currentFileCnt = 0;
private File forder = null;
public FileTravel(File forder) {
this.forder = forder;
}
public void travel() {
List<FileObject> list = new ArrayList<>();
travel(forder, list);
}
private void travel(File file, List<FileObject> list) {
Queue<File> queue = new LinkedList<>();
queue.offer(file);
File temp = null;
while (true) {
temp = queue.poll();
currentFile = temp;
currentForderCnt++;
if (temp == null) {
break;
}
File[] files = temp.listFiles();
if (files == null) {
continue;
}
for (File subFile : files) {
if (subFile.isDirectory()) {
queue.offer(subFile);
} else {
FileObject obj = new FileObject(subFile.getName(), subFile.length(), subFile.getAbsolutePath());
list.add(obj);
currentFileCnt++;
}
}
}
finish = true;
}
}
我了个叉,竟然需要10多分钟还没有计算完,我竟然还不知道处理到哪里了。那么我搞一个监控线程,来看看到底是出错了,还是卡死了。
new Thread(new WatchThread(travel)).start();
public class WatchThread implements Runnable {
private FileTravel travel = null;
public WatchThread(FileTravel travel) {
this.travel = travel;
}
@Override
public void run() {
while (!travel.finish) {
System.out.println("=============");
System.out.println("当前文件:" + travel.currentFile);
System.out.println("当前目录数:" + travel.currentForderCnt);
System.out.println("当前文件数:" + travel.currentFileCnt);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
原来一直在跑,就是数据量太大了,跑不过来。
为了解决问题,网上查找资料。找到了几个C#的代码,用来处理NTFS磁盘的。抱着对Java的信息,最后决定使用新版本的JDK7带的nio来试试。
public static void main(String[] args) {
System.out.println("系统启动");
FileTravel travel = new FileTravel(new File("D:/"));
long start = System.currentTimeMillis();
new Thread(new WatchThread(travel)).start();
travel.travel();
long end = System.currentTimeMillis();
System.out.println("耗时:" + ((end - start) / 1000));
}
public class FileTravelNIO {
private File forder = null;
public boolean finish = false;
public List<FileObject> list = new ArrayList<>();
public FileTravelNIO(File forder) {
this.forder = forder;
}
public void travel() throws IOException {
travel(forder, list);
}
private void travel(File file, List<FileObject> list) throws IOException {
Path path = Paths.get(file.getAbsolutePath());
SimpleFileVisitor<Path> finder = new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
File tempFile = file.toFile();
FileObject obj = new FileObject(tempFile.getName(), tempFile.length(), tempFile.getAbsolutePath());
list.add(obj);
return super.visitFile(file, attrs);
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
System.out.println("处理文件失败:" + file.toFile());
return FileVisitResult.CONTINUE;
}
};
java.nio.file.Files.walkFileTree(path, finder);
finish = true;
}
}
public class WatchThreadNIO implements Runnable {
private FileTravelNIO travel = null;
public WatchThreadNIO(FileTravelNIO travel) {
this.travel = travel;
}
@Override
public void run() {
while (!travel.finish) {
System.out.println("=============");
System.out.println("当前处理文件数量:" + travel.list.size());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
神奇的一幕出现了
处理本地磁盘D,耗时109秒,190万的文件数量。磁盘为NTFS
处理移动硬盘F,耗时1860秒,202万的文件数量。磁盘为extFat
结论:
1、NIO比IO性能提高极大
2、磁盘的格式对结果有影响
网友评论