日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java复制文件_java多种文件复制方式以及效率比较

發(fā)布時間:2024/1/23 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java复制文件_java多种文件复制方式以及效率比较 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1.背景

java復(fù)制文件的方式其實有很多種,可以分為 - 傳統(tǒng)的字節(jié)流讀寫復(fù)制FileInputStream,FileOutputStream,BufferedInputStream,BufferedOutputStream - 傳統(tǒng)的字符流讀寫復(fù)制FileReader,FileWriter,BufferWriter,BufferedWriter,BufferedReader - NIO系列的FileChannel - FileChannel+緩沖 - java.nio.Files.copy() - 第三方包中的FileUtils.copy方法,比如org.apache.commons.io.FileUtils,org.codehaus.plexus.util.FileUtils等等.

所以呢,看看各種方法效率怎么樣,主要衡量的標(biāo)準(zhǔn)就是時間,另外的一些標(biāo)準(zhǔn)包括大文件的復(fù)制時的內(nèi)存溢出等問題.

2.概述

由于很多時候復(fù)制文件都包括了文件夾下的所有子目錄及文件的復(fù)制,所以作者采用的遍歷+復(fù)制方法去復(fù)制文件.就是把整個復(fù)制過程分為先遍歷,遍歷的過程中遇到文件夾就創(chuàng)建,遇到文件就調(diào)用不同的復(fù)制方法. 遍歷的5種方法:

- (1)File.listFiles()

- (2)File.list()

- (3)org.codehaus.plexus.util.FileUtils.getFiles()

- (4)org.apache.commons.io.FileUtils.listFiles()

- (5)java nio中的java.nio.file.Files.walkFileTree

復(fù)制的8種方法:

- (1)FileInputStream+FileOutputStream - (2)BufferedInputStream+BufferedOutputStream

- (3)FileReader+FileWriter

- (4)BufferedReader+BufferedWriter

- (5)FileChannel

- (6)FileChannel+buffer

- (7)org.apache.commons.io.FileUtils.copyFile()

- (8)java.nio.file.Files.copy()

另外作者不太想看控制臺.....所以配合了一點swing使用.

3.jar包

4.遍歷

(1)listFiles()

private static void traverseByListFiles(File srcFile,File desFile) throws IOException

{

if(srcFile.isDirectory())

{

File[] files = srcFile.listFiles();

assert files != null;

for(File file : files)

{

File desFileOrDir = new File(desFile.getAbsolutePath() + File.separator + file.getName());

if(file.isDirectory())

{

if(desFileOrDir.exists())

desFileOrDir.delete();

desFileOrDir.mkdirs();

}

traverseByListFiles(file, desFileOrDir);

}

}

else

{

copyFile(srcFile, desFile);

}

}

通過srcFile的listFiles()獲取所有的子文件與子文件夾,然后判斷是否是目錄 如果是目錄,首先判斷有沒有這個文件(有時候本來是文件夾但是卻存在同名的文件,就先刪除),再創(chuàng)建文件夾,然后遞歸執(zhí)行函數(shù). 如果不是目錄,直接把兩個File作為參數(shù)進行文件復(fù)制,里面用什么方法后面會設(shè)置.

(2)list()

private static void traverseByList(File srcFile,File desFile) throws IOException

{

if (srcFile.isDirectory())

{

String[] files = srcFile.list();

assert files != null;

for (String file : files)

{

File subSrcFile = new File(srcFile, file);

File subDesFile = new File(desFile, file);

if (subSrcFile.isDirectory())

{

if (subDesFile.exists())

subDesFile.delete();

subDesFile.mkdirs();

}

traverseByList(subSrcFile, subDesFile);

}

}

else

{

copyFile(srcFile, desFile);

}

}

list與第一種listFiles()類似,不過是String[],也是先判斷目錄,創(chuàng)建目錄,不是目錄直接復(fù)制

(3)org.codehaus.plexus.util.FileUtils.getFiles

private static void traverseByGetFiles(File srcFile, File desFile) throws IOException

{

if (srcFile.isDirectory())

{

java.util.List fileList = org.codehaus.plexus.util.FileUtils.getFiles(srcFile,null,null);

for (File file : fileList)

{

File desFileOrDir = new File(desFile.getAbsolutePath() + File.separator + file.getName());

if(file.isDirectory())

{

if(desFileOrDir.exists())

desFileOrDir.delete();

desFileOrDir.mkdirs();

}

traverseByListFiles(file, desFileOrDir);

}

}

else

{

copyFile(srcFile, desFile);

}

}

這是用了別人的工具類進行遍歷.

org.codehaus.plexus.util.FileUtils.getFiles(srcFile,null,null);

返回的結(jié)果的java.util.List

private static void traverseByCommonsIO(File srcFile, File desFile) throws IOException

{

if (srcFile.isDirectory())

{

Collection files = org.apache.commons.io.FileUtils.listFiles(srcFile,null,false);

for (File file : files)

{

File desFileOrDir = new File(desFile.getAbsolutePath() + File.separator + file.getName());

if(file.isDirectory())

{

if(desFileOrDir.exists())

desFileOrDir.delete();

desFileOrDir.mkdirs();

}

traverseByCommonsIO(file, desFileOrDir);

}

}

else

{

copyFile(srcFile, desFile);

}

}

使用org.apache.commons.io.FileUtils的listFiles方法,參數(shù)為要遍歷的目錄,一個null和一個false,第二個參數(shù)表示過濾器,表示過濾出特定后綴名的文件,類型為String [],第三個布爾參數(shù)表示是否遞歸訪問子目錄.

(5)NIO--walkFileTree

利用FileVisitor這個接口.實際中常用SimpleFileVisitor.

private static void traverseByNIO2(File srcFile) throws IOException

{

java.nio.file.Files.walkFileTree(srcFile.toPath(), new SimpleFileVisitor<>() {

@Override

public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException

{

File d = new File(des.toString() + path.toAbsolutePath().toString().substring(src.toString().length()));

new File(d.toString().substring(0, d.toString().lastIndexOf(File.separator))).mkdirs();

copyFile(path.toFile(), d);

return FileVisitResult.CONTINUE;

}

});

}

FileVisitor接口定義了四個方法,分別為:

public interface FileVisitor

{

FileVisitResult preVisitDirectory(T dir,BasicFileAttributes attrs)

{

//訪問dir前的操作,dir類型一般為java.nio.Path }

FileVisitResult postVisitDirectory(T dir,BasicFileAttributes attrs)

{

//訪問dir后的操作 }

FileVisitResult visitFile(T file,BasicFileAttributes attrs)

{

//訪問file時的操作 }

FileVisitResult visitFileFailed(T file,BasicFileAttributes attrs)

{

//訪問file失敗時的操作 }

}

在上面的例子中只是實現(xiàn)了visitFile,因為只是復(fù)制操作,首先判斷是否是源目錄的路徑,不是的話創(chuàng)建文件夾再復(fù)制文件. 這里說一下返回值FileVisitResult.FileVisitResult是一個枚舉類型,根據(jù)返回值判斷是否繼續(xù)遍歷. FileVisitResult可取值: - CONTINUE:繼續(xù) - TERMINNATE:結(jié)束 - SKIP_SIBLINGS:繼續(xù),跳過同一目錄的節(jié)點 - SKIP_SUBTREE:繼續(xù),跳過子目錄,但會訪問子文件

5.復(fù)制

(1)FileInputStream+FileOutputStream

首先是經(jīng)典的字節(jié)流FileInputStream+FileOutputStream,這個比較簡單,使用FileInputStream讀取后使用FileOutputStream寫入,不過效率嘛.....一般般.

private static void copyByFileStream(File srcFile,File desFile) throws IOException

{

FileInputStream inputStream = new FileInputStream(srcFile);

FileOutputStream outputStream = new FileOutputStream(desFile);

byte [] b = new byte[1024];

while(inputStream.read(b) != -1)

{

outputStream.write(b);

addCopySize();

}

inputStream.close();

outputStream.close();

}

這里說一下三個read方法的區(qū)別,FileInputStream有三個read方法:

input.read();

input.read(b);

input.read(b,off,len);

A.read()

逐個字節(jié)進行讀取,返回int,寫入時直接使用write(n);

int n = input.read();

output.write(n);

這個可以說是三個read中最慢的....作者試了一個2G左右的文件,用了大概10分鐘才復(fù)制160M......

B.read(b)

參數(shù)是一個byte [],將字節(jié)緩沖到其中,返回數(shù)組的字節(jié)個數(shù),這個比read()快很多.

byte [] b = new byte[1024];

while(input.read(b) != -1)

output.write(b);

C.read(b,off,len)

這個方法其實和read(b)差不多,read(b)相當(dāng)于省略了參數(shù)的read(b,off,len).

byte [] b = new byte[1024];

int n;

while((n = input.read(b,0,1024))!=-1)

output.write(b,0,n);

public int read(byte b[], int off, int len) throws IOException

{

return readBytes(b, off, len);

}

public int read(byte b[]) throws IOException

{

return readBytes(b, 0, b.length);

}

這兩個都是調(diào)用一樣的readBytes():

private native int readBytes(byte b[], int off, int len) throws IOException;

至于效率...可以看看結(jié)果(作者用的是10G內(nèi)的小文件):

可以看到,沒有哪個一定比另外一個更快(不過最后一個誤差有點太大了?7G不夠的文件.). 采用哪一個建議自己去測試,畢竟這存在很多誤差,比如文件,java版本,機器本身等等,僅供參考.

(2)BufferedInputStream+BufferedOutputStream

緩沖字節(jié)流BufferedInputStream+BufferedOutputStream,相比起FileInputStream,BufferedInputStream讀取時會先從緩沖區(qū)讀取數(shù)據(jù),緩沖區(qū)無可讀數(shù)據(jù)再從文件讀取,所以會比FileInputStream快.

private static void copyByBufferStream(File srcFile,File desFile) throws IOException

{

BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(srcFile));

BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(desFile));

byte [] b = new byte[1024];

while(inputStream.read(b) != -1)

{

addCopySize();

outputStream.write(b);

}

inputStream.close();

outputStream.close();

}

這里也說一下BufferedInputStream的三個read(實際上還有,還有readN,與read(),read()肯定最慢,readN作者很少用,所以就沒列出來了)

read(b);

read(b,off,len);

readAllBytes();

A.read(b)

這個其實和FileInputStream的那個沒啥區(qū)別,把一個字節(jié)數(shù)組仍進去就好了.

B.read(b,off,len)

這個....也和FileInputStream那個沒啥區(qū)別,不說了

C.readAllBytes()

這個一次可以讀取所有的字節(jié).不過用這個雖然省事,可以直接

output.write(input.readAllBytes());

但是呢,有代價的:

會出現(xiàn)OutOfMemory錯誤,就是對于大文件還是老老實實分開吧,不要"一口搞定","多吃幾口".

看看效率:

readAllBytes對于大文件(作者這個是5G內(nèi)的文件)直接爆內(nèi)存....

readAllBytes()又爆了.....這個才2G不到的文件...readAllBytes()看來不是很給力啊....不過對于小文件效率還可以接受.

(3)FileReader+FileWriter

字符流讀寫FileReader+FileWriter,相比起字節(jié)流的read,基本上把byte[]換成char[]即可,因為是逐個字符讀取,而字節(jié)流是逐個字節(jié)讀取因此采用byte[]. 注意這個不能用來讀取圖片,音樂等文件,不然復(fù)制出來的文件打不開.

private static void copyByFileReader(File srcFile,File desFile) throws IOException

{

FileReader reader = new FileReader(srcFile);

FileWriter writer = new FileWriter(desFile);

char [] c = new char[1024];

while(reader.read(c) != -1)

{

addCopySize();

writer.write(c);

}

reader.close();

writer.close();

}

(4)BufferedReader+BufferedWriter

緩沖字符流讀寫B(tài)ufferedReader+BufferedWriter,BufferedReader相比起FileReader有一個readLine()方法,可以每行讀入,會比FileReader快.對應(yīng)的BufferedWriter提供了write(String)方法,當(dāng)然也有write(String s,int off,int len).同樣這個不能用來讀取圖片等.

private static void copyByBufferReader(File srcFile,File desFile) throws IOException

{

BufferedReader reader = new BufferedReader(new FileReader(srcFile));

BufferedWriter writer = new BufferedWriter(new FileWriter(desFile));

char [] c = new char[1024];

while(reader.read(c) != -1)

{

addCopySize();

writer.write(c);

}

reader.close();

writer.close();

}

(5)NIO--FileChannel

通過FileChannel復(fù)制,首先通過FileInputStream與FileOutputStream打開流,再用getChannel()方法.最后使用transferTo()或transferFrom()進行復(fù)制,一條語句即可,十分方便,而且效率很高.

private static void copyByFileChannel(File srcFile,File desFile) throws IOException

{

FileChannel srcChannel = new FileInputStream(srcFile).getChannel();

FileChannel desChannel = new FileOutputStream(desFile).getChannel();

srcChannel.transferTo(0,srcChannel.size(),desChannel);

srcChannel.close();

desChannel.close();

}

另外感謝評論(感謝cls)指出,FileChannel只能復(fù)制2G以內(nèi)的文件,因為源碼有如下判斷:

int var8 = (int)Math.min(var3, 2147483647L);

(6)NIO--FileChannel+ByteBuffer

在利用了FileInputStream與FileOutputStream打開了FileChannel的基礎(chǔ)上,配合ByteBuffer使用.

private static void copyByFileChannelWithBuffer(File srcFile,File desFile) throws IOException

{

FileChannel srcChannel = new FileInputStream(srcFile).getChannel();

FileChannel desChannel = new FileOutputStream(desFile).getChannel();

ByteBuffer buffer = ByteBuffer.allocateDirect(1024);

while(srcChannel.read(buffer) != -1)

{

buffer.flip();

desChannel.write(buffer);

buffer.clear();

addCopySize();

}

srcChannel.close();

desChannel.close();

}

flip的意思是"翻轉(zhuǎn)",

buffer.flip();

把Buffer從寫模式變?yōu)樽x模式,接著write(buffer),再把buffer清空. 看看這兩種方法效率:

另外作者發(fā)現(xiàn)transferTo的"上限"為2G,就是對于大于2G的單個文件最多最能復(fù)制2個G. 所以...對于大文件沒有可比性了.

(7)FileUtils.copyFile()

這是工具類,沒啥好說的,參數(shù)是兩個File,分別表示源與目標(biāo).

private static void copyByCommonsIO(File srcFile,File desFile) throws IOException

{

FileUtils.copyFile(srcFile, desFile);

}

(8)Files.copy()

這是官方提供的Files工具類,前兩個參數(shù)為Path,分別表示源與目標(biāo),可以設(shè)置第三個參數(shù)(或者省略),表示選項.例如可以設(shè)置

StandardCopyOption.REPLACE_EXISTING

private static void copyByFiles(File srcFile,File desFile) throws IOException

{

Files.copy(srcFile.toPath(), desFile.toPath(), StandardCopyOption.REPLACE_EXISTING);

}

注意Files.copy會保持文件的隱藏屬性,原來是隱藏的文件復(fù)制后也是隱藏的.以上7種則不會.

6.其他

(1)swing布局

A.網(wǎng)格布局

主JFrame采用了網(wǎng)格布局

setLayout(new GridLayout(3,1,5,3));

三行一列,因為只要三個按鈕,選擇源文件(夾),選擇目標(biāo)文件夾,選擇遍歷方式. 選擇遍歷方式/復(fù)制方式的JFrame同樣適用了網(wǎng)格布局:

showTraverseMethod.setLayout(new GridLayout(5,1,3,3));

showCopyMethod.setLayout(new GridLayout(4,2,5,5));

B.居中

setBounds(

(int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2) - 200,

(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2) - 200,

400, 400);

高400,寬400,利用ToolKit.getDefaultToolKit().getScreenSize()獲取屏幕的高度和寬度實現(xiàn)居中.

C.組件的添加與刪除

由于在主JFrame中只有三個按鈕,選擇完遍歷方式后需要更新這個組件,作者的做法是先刪除這個組件在添加組件:

traverseMethodButton.setVisible(false);

remove(traverseMethodButton);

add(copyMethodButton);

copyMethodButton.setVisible(true);

設(shè)置它不可見再刪除,再添加另一組件,再設(shè)置可見.

(2)進度條

進度條這個東西把作者搞得很慘啊......其實就是新建一個線程就可以了. 核心代碼為:

new Thread(

() ->

{

int percent;

while ((percent = getCopyPercent()) < 100)

{

try

{

Thread.sleep(100);

}

catch(InterruptedException e)

{

e.printStackTrace();

}

copyProgressBar.setValue(percent);

}

}

).start();

作者的JProgressBar是直接添加在一個JFrame中的,不用什么太復(fù)雜的布局. 獲取百分比后調(diào)用setValue(),一定要新建一個線程操作,不然不能正常顯示進度條. 另外復(fù)制的操作建議使用SwingWorker.

SwingWorker copyTask = new SwingWorker<>()

{

@Override

protected String doInBackground()

{

try

{

if (traverseMethod[0])

traverseByListFiles(src, des);

else if (traverseMethod[1])

traverseByList(src, des);

else if (traverseMethod[2])

traverseByGetFiles(src, des);

else if (traverseMethod[3])

traverseByCommonsIO(src, des);

else if (traverseMethod[4])

traverseByNIO2(src);

else

{

showProgressBar.dispose();

showMessage("遍歷失敗,找不到遍歷方法");

}

}

catch (IOException e)

{

e.printStackTrace();

showProgressBar.dispose();

showMessage("未知錯誤復(fù)制失敗");

}

finish(start);

return null;

}

};

copyTask.execute();

7.測試

說了那么多來點實際的. (以下所有的測試都是刪除復(fù)制的文件后再進行新一次的復(fù)制.)

(1)1G文件

文件的話其實縱向比較即可,因為基本不用怎么遍歷,橫向比較可以勉強看作求平均值. 對于非文本文件,FileReader/Writer和BufferedReader/Writer沒有太大的參考意義,比如復(fù)制視頻文件是打不開的,而且復(fù)制出來的文件會變大.對于單文件Files.copy的性能非常好,java的nio果然厲害.

(2)10G文件

這個10G的文件是文本文件. 現(xiàn)在可以看看FileChannel的這一行,明顯所花的時間要比其他要少,為什么呢? 因為文件大于2G.FileChannel的trasferTo方法只能寫入最多2G的文件,所以對于大于2G的文件復(fù)制出來只有2G,因此FileChannel的這一行沒有太大可比性.對于文本文件,BufferedReader/Writer的復(fù)制速度是最快的了,其次是FileInput/OutputStream.對于單個大文件,apache的FileUtils與NIO的Files.copy的速度比FileInputStream慢啊...

(3)1G目錄

對于目錄的話可以考慮放棄BufferedReader與FileReader了,除非全部是文本文件,否則推薦使用BufferedInput/OutputStream與Files.copy()進行復(fù)制,工具類FileUtils的復(fù)制方法表現(xiàn)還是不錯的,但相比起java標(biāo)準(zhǔn)的Files.copy效率都差了. 對于FileChannel與配合緩沖使用的FileChannel,1G的話好像不相上下. 遍歷方式的話...可以看到plexus的遍歷方法表現(xiàn)差距很大,而apache的listFiles或者java nio的walkFileTree比較穩(wěn)定且速度還可以,推薦使用這兩種方式遍歷目錄.

(4)10G目錄

FileReader與BufferedReader這兩行可以忽略了.對于小文件用FileChannel的話還是不錯的,對于大文件一定要用FileChannel的話可以配合ByteBuffer使用,不過從數(shù)據(jù)上看效果比BufferedInput/OutputStream要低. 再看看org.apache.commons.io.FileUtils與java.nio.file.Files的copy,差別不太,效果接近,但在1G的時候差距有點大. 遍歷方式的話,java nio的walkFileTrees最快.

當(dāng)然這些測試僅供參考,具體使用哪一個要看看具體環(huán)境,另外這種方式把遍歷與復(fù)制分開,apache的FileUtils有方法可以直接復(fù)制目錄的,因此,使用哪個更合適還需要個人具體測試.

8.源碼

作者比較偷懶全部仍在一個文件了.七百行.

import java.awt.*;

import javax.swing.*;

import java.nio.*;

import java.nio.channels.*;

import java.io.*;

import java.nio.file.*;

import java.nio.file.attribute.*;

import java.util.*;

import org.apache.commons.io.*;

public class Test extends JFrame

{

public static final long serialVersionUID = 12398129389122L;

private JFrame showTraverseMethod = new JFrame("遍歷方式");

private JFrame showCopyMethod = new JFrame("復(fù)制方式");

private JButton traverseMethodButton = new JButton("請選擇遍歷方式");

private JButton copyMethodButton = new JButton("請選擇復(fù)制方式");

private JButton copyButton = new JButton("開始復(fù)制");

private JButton traverseByListFiles = new JButton("File.listFiles()");

private JButton traverseByList = new JButton("File.list()");

private JButton traverseByGetFiles = new JButton("(plexus)getFiles()");

private JButton traverseByCommonsIO = new JButton("Commons IO");

private JButton traverseByNIO2 = new JButton("NIO2");

private JButton copyByFileStream = new JButton("File stream");

private JButton copyByBufferStream = new JButton("Buffer stream");

private JButton copyByFileReader = new JButton("File reader");

private JButton copyByBufferReader = new JButton("Buffer reader");

private JButton copyByFileChannel = new JButton("File channel");

private JButton copyByFileChannelWithBuffer = new JButton("File channel with buffer");

private JButton copyByCommonsIO = new JButton("Commons IO");

private JButton copyByFiles = new JButton("Files.copy");

public Test()

{

JButton src = new JButton("選擇源文件(夾)");

src.addActionListener(

event ->

{

JFileChooser fileChooser = new JFileChooser();

fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);

fileChooser.showDialog(new Label(), "選擇文件(夾)");

FilesCopy.setSrc(fileChooser.getSelectedFile());

}

);

JButton des = new JButton("選擇目標(biāo)文件夾");

des.addActionListener(

event ->

{

JFileChooser fileChooser = new JFileChooser();

fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);

fileChooser.showDialog(new JLabel(),"選擇文件夾");

FilesCopy.setDes(fileChooser.getSelectedFile());

}

);

traverseMethodButton.addActionListener(

event ->

{

traverseByListFiles.addActionListener(

e->

{

FilesCopy.setTraverseByListFiles();

showTraverseMethod.dispose();

}

);

traverseByList.addActionListener(

e ->

{

FilesCopy.setTraverseByList();

showTraverseMethod.dispose();

}

);

traverseByGetFiles.addActionListener(

e ->

{

FilesCopy.setTraverseByGetfiles();

showTraverseMethod.dispose();

}

);

traverseByCommonsIO.addActionListener(

e ->

{

FilesCopy.setTraverseByCommonsIO();

showTraverseMethod.dispose();

}

);

traverseByNIO2.addActionListener(

e ->

{

FilesCopy.setTraverseByNIO2();

showTraverseMethod.dispose();

}

);

showTraverseMethod.setLayout(new GridLayout(5,1,3,3));

showTraverseMethod.setTitle("遍歷方式");

showTraverseMethod.setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2) - 200,

(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2) - 200, 400, 400);

showTraverseMethod.setVisible(true);

showTraverseMethod.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

showTraverseMethod.add(traverseByListFiles);

showTraverseMethod.add(traverseByList);

showTraverseMethod.add(traverseByGetFiles);

showTraverseMethod.add(traverseByCommonsIO);

showTraverseMethod.add(traverseByNIO2);

traverseMethodButton.setVisible(false);

remove(traverseMethodButton);

add(copyMethodButton);

copyMethodButton.setVisible(true);

}

);

copyMethodButton.addActionListener(

event ->

{

copyByFileStream.addActionListener(

e ->

{

FilesCopy.setCopyByFileStream();

showCopyMethod.dispose();

}

);

copyByBufferStream.addActionListener(

e ->

{

FilesCopy.setCopyByBufferStream();

showCopyMethod.dispose();

}

);

copyByFileReader.addActionListener(

e ->

{

FilesCopy.setCopyByFileReader();

showCopyMethod.dispose();

}

);

copyByBufferReader.addActionListener(

e ->

{

FilesCopy.setCopyByBufferReader();

showCopyMethod.dispose();

}

);

copyByFileChannel.addActionListener(

e ->

{

FilesCopy.setCopyByFileChannel();

showCopyMethod.dispose();

}

);

copyByFileChannelWithBuffer.addActionListener(

e ->

{

FilesCopy.setCopyByFileChannelWithBuffer();

showCopyMethod.dispose();

}

);

copyByCommonsIO.addActionListener(

e ->

{

FilesCopy.setCopyByCommonsIO();

showCopyMethod.dispose();

}

);

copyByFiles.addActionListener(

e ->

{

FilesCopy.setCopyByFiles();

showCopyMethod.dispose();

}

);

showCopyMethod.setLayout(new GridLayout(4,2,5,5));

showCopyMethod.setTitle("復(fù)制方式");

showCopyMethod.setBounds(

(int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2) - 200,

(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2) - 200, 400, 400);

showCopyMethod.setVisible(true);

showCopyMethod.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

showCopyMethod.add(copyByFileStream);

showCopyMethod.add(copyByBufferStream);

showCopyMethod.add(copyByFileReader);

showCopyMethod.add(copyByBufferReader);

showCopyMethod.add(copyByFileChannel);

showCopyMethod.add(copyByFileChannelWithBuffer);

showCopyMethod.add(copyByCommonsIO);

showCopyMethod.add(copyByFiles);

copyMethodButton.setVisible(false);

remove(copyMethodButton);

add(copyButton);

copyButton.setVisible(true);

}

);

copyButton.addActionListener(

event ->

{

if(FilesCopy.haveSelectedSrcAndDes())

{

FilesCopy.copy();

copyButton.setVisible(false);

remove(copyButton);

add(traverseMethodButton);

traverseMethodButton.setVisible(true);

}

else

JOptionPane.showMessageDialog(null,"請先選擇源文件(夾)與目標(biāo)文件夾!");

}

);

setLayout(new GridLayout(3,1,5,3));

setTitle("復(fù)制文件");

setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2) - 200,

(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2) - 200, 400, 400);

setVisible(true);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

add(src);

add(des);

add(traverseMethodButton);

}

public static void main(String[] args) {

new Test();

}

}

class FilesCopy

{

private static File src = null;

private static File des = null;

private static long desSize = 0;

private static long srcSize = 0;

private static boolean [] traverseMethod = {false,false,false,false,false,false};

private static boolean[] copyMethod = { false, false, false, false, false, false ,false,false};

private static JFrame showProgressBar = new JFrame();

private static JProgressBar copyProgressBar = new JProgressBar();

private static JTextField textField = new JTextField();

private static int index = 0;

private static int getCopyPercent()

{

return (int)(desSize * 100.0 / srcSize);

}

private static void addCopySize() {

desSize += 1024L;

}

public static void setTraverseByListFiles()

{

traverseMethod[0] = true;

}

private static void traverseByListFiles(File srcFile,File desFile) throws IOException

{

if(srcFile.isDirectory())

{

File[] files = srcFile.listFiles();

assert files != null;

for(File file : files)

{

File desFileOrDir = new File(desFile.getAbsolutePath() + File.separator + file.getName());

if(file.isDirectory())

{

if(desFileOrDir.exists())

desFileOrDir.delete();

desFileOrDir.mkdirs();

}

traverseByListFiles(file, desFileOrDir);

}

}

else {

copyFile(srcFile, desFile);

}

}

public static void setTraverseByList()

{

traverseMethod[1] = true;

}

private static void traverseByList(File srcFile,File desFile) throws IOException

{

if (srcFile.isDirectory())

{

String[] files = srcFile.list();

assert files != null;

for (String file : files)

{

File subSrcFile = new File(srcFile, file);

File subDesFile = new File(desFile, file);

if (subSrcFile.isDirectory())

{

if (subDesFile.exists())

subDesFile.delete();

subDesFile.mkdirs();

}

traverseByList(subSrcFile, subDesFile);

}

}

else

{

copyFile(srcFile, desFile);

}

}

public static void setTraverseByGetfiles()

{

traverseMethod[2] = true;

}

private static void traverseByGetFiles(File srcFile, File desFile) throws IOException

{

if (srcFile.isDirectory())

{

java.util.List fileList = org.codehaus.plexus.util.FileUtils.getFiles(srcFile,null,null);

for (File file : fileList)

{

File desFileOrDir = new File(desFile.getAbsolutePath() + File.separator + file.getName());

if(file.isDirectory())

{

if(desFileOrDir.exists())

desFileOrDir.delete();

desFileOrDir.mkdirs();

}

traverseByListFiles(file, desFileOrDir);

}

}

else

{

copyFile(srcFile, desFile);

}

}

public static void setTraverseByCommonsIO()

{

traverseMethod[3] = true;

}

private static void traverseByCommonsIO(File srcFile, File desFile) throws IOException

{

if (srcFile.isDirectory())

{

Collection files = org.apache.commons.io.FileUtils.listFiles(srcFile,null,false);

for (File file : files)

{

File desFileOrDir = new File(desFile.getAbsolutePath() + File.separator + file.getName());

if(file.isDirectory())

{

if(desFileOrDir.exists())

desFileOrDir.delete();

desFileOrDir.mkdirs();

}

traverseByCommonsIO(file, desFileOrDir);

}

}

else {

copyFile(srcFile, desFile);

}

}

public static void setTraverseByNIO2()

{

traverseMethod[4] = true;

}

private static void traverseByNIO2(File srcFile) throws IOException

{

java.nio.file.Files.walkFileTree(srcFile.toPath(), new SimpleFileVisitor<>() {

@Override

public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {

File d = new File(des.toString() + path.toAbsolutePath().toString().substring(src.toString().length()));

new File(d.toString().substring(0, d.toString().lastIndexOf(File.separator))).mkdirs();

copyFile(path.toFile(), d);

return FileVisitResult.CONTINUE;

}

});

}

public static void setCopyByFileStream()

{

copyMethod[0] = true;

}

private static void copyByFileStream(File srcFile,File desFile) throws IOException

{

FileInputStream inputStream = new FileInputStream(srcFile);

FileOutputStream outputStream = new FileOutputStream(desFile);

byte [] b = new byte[1024];

while(inputStream.read(b) != -1)

{

outputStream.write(b);

addCopySize();

}

inputStream.close();

outputStream.close();

}

public static void setCopyByBufferStream()

{

copyMethod[1] = true;

}

private static void copyByBufferStream(File srcFile,File desFile) throws IOException

{

BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(srcFile));

BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(desFile));

byte [] b = new byte[1024];

while(inputStream.read(b) != -1)

{

addCopySize();

outputStream.write(b);

}

inputStream.close();

outputStream.close();

}

public static void setCopyByFileReader()

{

copyMethod[2] = true;

}

private static void copyByFileReader(File srcFile,File desFile) throws IOException

{

FileReader reader = new FileReader(srcFile);

FileWriter writer = new FileWriter(desFile);

char [] c = new char[1024];

while(reader.read(c) != -1)

{

addCopySize();

writer.write(c);

}

reader.close();

writer.close();

}

public static void setCopyByBufferReader()

{

copyMethod[3] = true;

}

private static void copyByBufferReader(File srcFile,File desFile) throws IOException

{

BufferedReader reader = new BufferedReader(new FileReader(srcFile));

BufferedWriter writer = new BufferedWriter(new FileWriter(desFile));

char [] c = new char[1024];

while(reader.read(c) != -1)

{

addCopySize();

writer.write(c);

}

reader.close();

writer.close();

}

public static void setCopyByFileChannel()

{

copyMethod[4] = true;

}

private static void copyByFileChannel(File srcFile,File desFile) throws IOException

{

FileChannel srcChannel = new FileInputStream(srcFile).getChannel();

FileChannel desChannel = new FileOutputStream(desFile).getChannel();

srcChannel.transferTo(0,srcChannel.size(),desChannel);

srcChannel.close();

desChannel.close();

}

public static void setCopyByFileChannelWithBuffer()

{

copyMethod[5] = true;

}

private static void copyByFileChannelWithBuffer(File srcFile,File desFile) throws IOException

{

FileChannel srcChannel = new FileInputStream(srcFile).getChannel();

FileChannel desChannel = new FileOutputStream(desFile).getChannel();

ByteBuffer buffer = ByteBuffer.allocateDirect(1024);

while(srcChannel.read(buffer) != -1)

{

buffer.flip();

desChannel.write(buffer);

buffer.clear();

addCopySize();

}

srcChannel.close();

desChannel.close();

}

public static void setCopyByCommonsIO()

{

copyMethod[6] = true;

}

private static void copyByCommonsIO(File srcFile,File desFile) throws IOException

{

FileUtils.copyFile(srcFile, desFile);

}

public static void setCopyByFiles()

{

copyMethod[7] = true;

}

private static void copyByFiles(File srcFile,File desFile) throws IOException

{

Files.copy(srcFile.toPath(), desFile.toPath(), StandardCopyOption.REPLACE_EXISTING);

}

public static void setSrc(File srcFile) {

src = srcFile;

if(srcFile.isDirectory())

srcSize = org.apache.commons.io.FileUtils.sizeOfDirectory(srcFile);

else

srcSize = src.length();

}

public static void setDes(File desFile) {

des = desFile;

desSize = 0;

}

public static void setSrc(Path srcPath)

{

setSrc(srcPath.toFile());

}

public static void setDes(Path desPath)

{

setDes(desPath.toFile());

}

private static void copyFile(File srcFile,File desFile) throws IOException

{

if (copyMethod[0])

copyByFileStream(srcFile,desFile);

else if (copyMethod[1])

copyByBufferStream(srcFile, desFile);

else if (copyMethod[2])

copyByFileReader(srcFile, desFile);

else if (copyMethod[3])

copyByBufferReader(srcFile, desFile);

else if (copyMethod[4])

copyByFileChannel(srcFile, desFile);

else if (copyMethod[5])

copyByFileChannelWithBuffer(srcFile, desFile);

else if (copyMethod[6])

copyByCommonsIO(srcFile, desFile);

else if (copyMethod[7])

copyByFiles(srcFile, desFile);

else

showMessage("復(fù)制失敗,找不到復(fù)制方法.");

}

private static void showMessage(String message)

{

JOptionPane.showMessageDialog(null, message);

}

public static boolean haveSelectedSrcAndDes()

{

return src != null && des != null;

}

public static void copy()

{

long start = System.currentTimeMillis();

if(haveSelectedSrcAndDes())

{

if(src.isFile())

{

des = new File(des.getAbsolutePath()+File.separator+src.getName());

}

SwingWorker copyTask = new SwingWorker<>()

{

@Override

protected String doInBackground()

{

try

{

if (traverseMethod[0])

traverseByListFiles(src, des);

else if (traverseMethod[1])

traverseByList(src, des);

else if (traverseMethod[2])

traverseByGetFiles(src, des);

else if (traverseMethod[3])

traverseByCommonsIO(src, des);

else if (traverseMethod[4])

traverseByNIO2(src);

else

{

showProgressBar.dispose();

showMessage("遍歷失敗,找不到遍歷方法");

}

}

catch (IOException e)

{

e.printStackTrace();

showProgressBar.dispose();

showMessage("未知錯誤復(fù)制失敗");

}

finish(start);

return null;

}

};

copyTask.execute();

if (!copyMethod[4] && !copyMethod[6] && !copyMethod[7])

{

copyProgressBar.setMinimum(0);

copyProgressBar.setMaximum(100);

copyProgressBar.setValue(0);

copyProgressBar.setVisible(true);

copyProgressBar.setStringPainted(true);

showProgressBar.add(copyProgressBar);

showProgressBar.setTitle("復(fù)制進度");

showProgressBar.setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2) - 150,

(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2) - 50, 300, 100);

showProgressBar.setVisible(true);

new Thread(

() ->

{

int percent;

while ((percent = getCopyPercent()) < 100)

{

try

{

Thread.sleep(100);

}

catch(InterruptedException e)

{

e.printStackTrace();

}

copyProgressBar.setValue(percent);

}

}

).start();

}

else

{

final String [] text = {".","..","...","....",".....",".......","......",".....","....","...","..","."};

textField.setVisible(true);

textField.setHorizontalAlignment(JTextField.CENTER);

textField.setEditable(false);

showProgressBar.add(textField);

showProgressBar.setTitle("復(fù)制中");

showProgressBar.setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2) - 120,

(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2) - 40, 240, 80);

showProgressBar.setVisible(true);

new Thread(

() ->

{

while (getCopyPercent() < 100)

{

try

{

Thread.sleep(400);

}

catch(InterruptedException e)

{

e.printStackTrace();

}

if(index < text.length)

textField.setText("復(fù)制中"+text[index++]);

else

index = 0;

}

}

).start();

}

}

}

private static void finish(long start)

{

long end = System.currentTimeMillis();

showProgressBar.dispose();

showMessage("復(fù)制成功,用時:" + (end - start) / 1000.0 + "s");

copyProgressBar.setVisible(false);

showProgressBar.remove(copyProgressBar);

textField.setVisible(false);

showProgressBar.remove(textField);

Arrays.fill(traverseMethod, false);

Arrays.fill(copyMethod, false);

des = src = null;

desSize = srcSize;

}

}

總結(jié)

以上是生活随笔為你收集整理的java复制文件_java多种文件复制方式以及效率比较的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。