1. The background

Java copy files in a variety of ways, can be divided into

  • The traditional stream of bytes to read and write copy FileInputStream, FileOutputStream, BufferedInputStream, BufferedOutputStream
  • Traditional character copy FileReader flow, speaking, reading and writing, FileWriter, BufferWriter, BufferedWriter, BufferedReader
  • NIO series FileChannel
  • FileChannel + buffer
  • java.nio.Files.copy()
  • Third-party packages of FileUtils. Copy method, such as org.apache.com mons. IO. FileUtils, org. Codehaus. Breadth. Util. FileUtils and so on.

So, when looking at the efficiency of various methods, the main metric is time, and other criteria include issues such as memory overflow when copying large files.

Summary of 2.

Because most of the copied files include all the subdirectories under the folder and the copy of files, so the author adopts the traversal + copy method to copy files. That is, the whole replication process is divided into traversal first, traversal encountered folder on the creation of the process, encountered files on the call to different replication methods. 5 ways to traverse:

  • (1)File.listFiles()
  • (2)File.list()
  • (3)org.codehaus.plexus.util.FileUtils.getFiles()
  • (4)org.apache.commons.io.FileUtils.listFiles()
  • (5) Java nio in Java. Nio. File. The Files. The walkFileTree

8 ways to Copy:

  • (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()

Also the author does not want to see the console….. So a little bit of Swing usage.

3. The jar package

1.org.apache.commons 2.org.codehaus.plexus

4. Traversal

(1)listFiles()

 private static void traverseByListFiles(File srcFile,File desFile) throws IOException
{
	if(srcFile.isDirectory())
	{
		File[] files = srcFile.listFiles();
		assertfiles ! =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); }}Copy the code

Obtain all subfiles and subfolders from the listFiles() of srcFile, and then determine whether it is a directory. If it is a directory, first determine whether it is a file (sometimes it is a folder but there is a file with the same name, delete it first), then create a folder, and then recursively execute the function. If it is not a directory, directly take the two files as parameters to copy the File, which method will be set later.

(2)list()

private static void traverseByList(File srcFile,File desFile) throws IOException
{
	if (srcFile.isDirectory())
	{
		String[] files = srcFile.list();
		assertfiles ! =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); }}Copy the code

ListFiles () is the same as listFiles(), but is a String[]

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

private static void traverseByGetFiles(File srcFile, File desFile) throws IOException
{
	if (srcFile.isDirectory())
	{
		java.util.List<File> 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); }}Copy the code

This is traversal using someone else’s utility class.

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

Returns the result java.util.List

(4) the Commons. IO toolkit

private static void traverseByCommonsIO(File srcFile, File desFile) throws IOException
{
	if (srcFile.isDirectory())
	{
		Collection<File> 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); }}Copy the code

Use org.apache.com mons. IO. FileUtils listFiles method, parameter to directory traversal, a null and a false, the second parameter said filter, filter the specific file suffix, said the The type is String [], and the third Boolean parameter indicates whether subdirectories are accessed recursively.

(5)NIO–walkFileTree

Use the FileVisitor interface. SimpleFileVisitor is commonly used in practice.

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);
            returnFileVisitResult.CONTINUE; }}); }Copy the code

The FileVisitor interface defines four methods:

public interface FileVisitor<T>
{
	FileVisitResult preVisitDirectory(T dir,BasicFileAttributes attrs)
	{
		// The operation before accessing dir. The dir type is java.nio.path
	}
	
	FileVisitResult postVisitDirectory(T dir,BasicFileAttributes attrs)
	{
		// The operation after accessing dir
	}
	
	FileVisitResult visitFile(T file,BasicFileAttributes attrs)
	{
		// The operation when accessing file
	}
	
	FileVisitResult visitFileFailed(T file,BasicFileAttributes attrs)
	{
		// Failed to access file}}Copy the code

In the above example, visitFile is implemented, because it is only a copy operation. First check if it is the source directory path, and if not, create a folder and copy the file. Here said the return value FileVisitResult FileVisitResult is an enumeration type, according to the return value judgment whether to continue to traverse. FileVisitResult The value can be:

  • CONTINUE, CONTINUE to
  • End of TERMINNATE:
  • SKIP_SIBLINGS: Continue, skip the nodes in the same directory
  • SKIP_SUBTREE: Continues, skips subdirectories but accesses subfiles

5. Copy

(1)FileInputStream+FileOutputStream

The first is the classical byte stream FileInputStream+FileOutputStream. This is relatively simple, using FileInputStream to read and use FileOutputStream to write, but efficiency….. So-so.

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();
}
Copy the code

FileInputStream has three read methods:

input.read();
input.read(b);
input.read(b,off,len);
Copy the code

A.read()

Read byte by byte, return int, write directly with write(n);

int n = input.read();
output.write(n);
Copy the code

This is arguably the slowest of the three reads…. The author tried a file of about 2G and took about 10 minutes to copy 160M……

B.read(b)

The argument is a byte [], which buffers bytes into it and returns the number of bytes in the array, which is much faster than read().

byte [] b = new byte[1024];
while(input.read(b) ! = -1)
	output.write(b);
Copy the code

C.read(b,off,len)

This method is similar to read(b), which is equivalent to read(b,off,len) without the argument.

byte [] b = new byte[1024];
int n;
while((n = input.read(b,0.1024))! = -1)
	output.write(b,0,n);
Copy the code
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);
}
Copy the code

Both call the same readBytes():

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

As for efficiency… Take a look at the results (the author uses a small file in 10GB):

(2)BufferedInputStream+BufferedOutputStream

Buffer byte stream BufferedInputStream + BufferedOutputStream, than the FileInputStream, BufferedInputStream readers to read data from the buffer, the buffer is read data read from the file again, so than Fil EInputStream fast.

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();
}
Copy the code

I’ll also mention the three reads of BufferedInputStream (actually, there’s readN, and read(), which is definitely the slowest, and readN is rarely used by authors, so IT’s not listed).

read(b);
read(b,off,len);
readAllBytes();
Copy the code

A.read(b)

This is actually no different than the FileInputStream, just throw in an array of bytes.

B.read(b,off,len)

This… It’s no different than a FileInputStream

C.readAllBytes()

This will read all the bytes at once. But with this, it’s easy. It’s straightforward

output.write(input.readAllBytes());
Copy the code

But there’s a price:

Look at efficiency:

(3)FileReader+FileWriter

Char [] is used instead of byte[], which is read character by character, and byte[] is read byte by byte. Note that this cannot be used to read images, music, etc., otherwise the copied file will not open.

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();
}
Copy the code

(4)BufferedReader+BufferedWriter

Buffer BufferedReader + BufferedWriter character stream, speaking, reading and writing, BufferedReader than FileReader a readLine () method, which can be read in each row, will be faster than FileReader. The BufferedWriter provides a write(String) method, as well as write(String s,int OFF,int len). Again, this can’t be used to read images, etc.

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();
}
Copy the code

(5)NIO–FileChannel

Through FileChannel replication, the stream is first opened through FileInputStream and FileOutputStream, followed by the getChannel() method. Finally, transferTo() or transferFrom() is used to copy, which is very convenient and efficient.

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();
}
Copy the code

(6)NIO–FileChannel+ByteBuffer

Using FileInputStream and FileOutputStream to turn on FileChannel, it works with 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();
}
Copy the code

Flip means to turn over,

buffer.flip();
Copy the code

Change the Buffer from write mode to read mode, then write(Buffer), and then clear the Buffer. Look at the efficiency of these two methods:

In addition, the author finds that the “upper limit” of transferTo is 2G, that is, for a single file larger than 2G, it can copy at most 2G. So… There is no comparison for large files.

(7)FileUtils.copyFile()

This is a utility class, there is nothing to say, the argument is two files, one for the source and one for the target.

private static void copyByCommonsIO(File srcFile,File desFile) throws IOException
{
	FileUtils.copyFile(srcFile, desFile);
}
Copy the code

(8)Files.copy()

This is the official provided Files utility class. The first two parameters are Path, indicating the source and target respectively. You can set the third parameter (or omit), indicating the option. For example, you can set

StandardCopyOption.REPLACE_EXISTING
Copy the code
private static void copyByFiles(File srcFile,File desFile) throws IOException
{
	Files.copy(srcFile.toPath(), desFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
Copy the code

Note that files. copy keeps the hidden property of Files, and Files that were originally hidden are also hidden after copying. These seven do not.

6. Other

(1) the swing layout

A. Grid layout

The main JFrame uses a grid layout

setLayout(new GridLayout(3.1.5.3));
Copy the code

Three rows a column, because only three buttons, select the source file (folder), select the target folder, select the traversal mode. The traversal/copy JFrame option also applies to grid layouts:

showTraverseMethod.setLayout(new GridLayout(5.1.3.3));
showCopyMethod.setLayout(new GridLayout(4.2.5.5));
Copy the code

B. in the middle

setBounds(
(int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2) - 200,
(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2) - 200.400.400);
Copy the code

400, 400, wide use of the ToolKit. GetDefaultToolKit () getScreenSize () to obtain the height and width of the screen center.

C. Add and delete components

Since there are only three buttons in the main JFrame, the component needs to be updated after selecting the traversal mode. The author’s approach is to delete the component first and add the component:

traverseMethodButton.setVisible(false);
remove(traverseMethodButton);
add(copyMethodButton);
copyMethodButton.setVisible(true);
Copy the code

Make it invisible and remove it, add another component, and make it visible.

(2) the progress bar

The progress bar is messing up the author…… Just create a new thread. The core code is:

new Thread(
	() ->
	{
		int percent;
		while ((percent = getCopyPercent()) < 100)
		{
			try
			{
				Thread.sleep(100);
			}
			catch(InterruptedException e)
			{
				e.printStackTrace();
			}
			copyProgressBar.setValue(percent);
		}
	}
).start();
Copy the code

The author’s JProgressBar is added directly to a JFrame, without any complicated layout. Call setValue() after you get the percentage, you must create a new thread to operate, otherwise the progress bar will not display properly. In addition, SwingWorker is recommended for replication operations.

SwingWorker<String,Object> copyTask = new SwingWorker<>()
{
	@Override
	protected String doInBackground(a)
	{
		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("Traversal failed, traversal method not found"); }}catch (IOException e)
		{
			e.printStackTrace();
			showProgressBar.dispose();
			showMessage("Unknown error replication failed");
		}
		finish(start);
		return null; }}; copyTask.execute();Copy the code

7. Test

Having said that, let’s be realistic. (All of the following tests delete the copied file and then make a new copy.)

(1) 1 g file

1G file File.listFiles() File.list() plexus.util.FileUtils.getFiles() commons.io.FileUtils.listFiles Files.walkFileTree
FileIntput/OutputStream 20.189 s 21.152 s 18.249 s 20.131 s 21.782 s
BufferedInput/OuputStream 17.761 s 23.786 s 22.118 s 19.646 s 16.806 s
FileReader/Writer 61.334 s 58.3 s 58.904 s 58.679 s 55.762 s
BufferedReader/Writer 63.287 s 59.546 s 56.664 s 58.212 s 59.884 s
FileChannel 20.097 s 22.272 s 22.751 s 22.765 s 20.291 s
FileChannel+ByteBuffer 18.857 s 22.489 s 23.148 s 22.337 s 17.213 s
FileUtils.copyFile 25.398 s 21.95 s 22.808 s 25.325 s 22.483 s
Files.copy 16.272 s 14.166 s 17.057 s 14.987 s 10.653 s

In fact, the vertical comparison can be, because there is no need to traverse, horizontal comparison can be reluctantly regarded as an average. For non-text files,FileReader/Writer and BufferedReader/Writer are not very useful. For example, copying a video file cannot be opened, and the copied file will become larger. Very good performance for single-file files.copy, and Java NIO is awesome.

(2) 10 g files

10G file File.listFiles() File.list() plexus.util.FileUtils.getFiles() commons.io.FileUtils.listFiles Files.walkFileTree
FileIntput/OutputStream 171.427 s 173.146 s 172.611 s 184.182 s 250.251 s
BufferedInput/OuputStream 203.509 s 174.792 s 167.727 s 177.451 s 217.53 s
FileReader/Writer 187.55 s 169.306 s 226.571 s 168.982 s 218.303 s
BufferedReader/Writer 155.134 s 165.883 s 166.192 s 176.488 s 206.306 s
FileChannel 34.48 s 35.445 s 43.896 s 41.827 s 41.755 s
FileChannel+ByteBuffer 175.632 s 167.091 s 178.455 s 182.977 s 183.763 s
FileUtils.copyFile 203.997 s 206.623 s 201.01 s 213.949 s 208.739 s
Files.copy 209.898 s 186.889 s 244.355 s 222.336 s 244.68 s

This 10GB file is a text file. Now if you look at the FileChannel line, it obviously takes less time than the others. Why? FileChannel’s trasferTo method can only write files up to 2G, so files up to 2G will be copied, so the FileChannel line is not very comparable. For text files,BufferedReader/Writer is the fastest copy, followed by FileInput/OutputStream. Apache FileUtils and NIO files.copy are slower than FileInputStream for large Files.

(3) 1 g directory

1G dir File.listFiles() File.list() plexus.util.FileUtils.getFiles() commons.io.FileUtils.listFiles Files.walkFileTree
FileIntput/OutputStream 23.549 s 99.386 s 143.388 s 13.451 s 10.773 s
BufferedInput/OuputStream 6.306 s 59.458 s 20.704 s 6.668 s 6.616 s
FileReader/Writer 49.059 s 103.257 s 51.995 s 49.729 s 51.509 s
BufferedReader/Writer 59.932 s 127.359 s 51.731 s 51.418 s 50.317 s
FileChannel 40.082 s 71.713 s 17.617 s 15.782 s 19.777 s
FileChannel+ByteBuffer 33.355 s 83.845 s 19.68 s 10.288 s 17.152 s
FileUtils.copyFile 24.163 s 63.979 s 8.277 s 6.115 s 19.513 s
Files.copy 14.528 s 28.215 s 6.578 s 5.883 s 7.502 s

Words can consider to give up BufferedReader and FileReader for catalog, unless all text Files, otherwise, it is recommended to use BufferedInput/OutputStream and Files. The copy () to copy, utility class FileUtils replication methods or performance Nice, but not as efficient as the Java standard files.copy. For FileChannel and FileChannel used with buffering,1G seems to be about the same. Traversal… It can be seen that the performance of Plexus traversal method differs greatly, while Apache listFiles or Java NIO walkFileTree is relatively stable and the speed is acceptable. It is recommended to traverse the directory in these two ways.

(4) 10 g directory

10G dir File.listFiles() File.list() plexus.util.FileUtils.getFiles() commons.io.FileUtils.listFiles Files.walkFileTree
FileIntput/OutputStream 216.822 s 228.792 s 227.908 s 240.042 s 191.863 s
BufferedInput/OuputStream 218.599 s 210.941 s 207.375 s 213.991 s 167.614 s
FileReader/Writer 536.747 s 550.755 s 550.415 s 548.881 s 516.684 s
BufferedReader/Writer 587.612 s 552.55 s 549.716 s 553.484 s 498.18 s
FileChannel 115.126 s 117.538 s 117.456 s 118.207 s 97.626 s
FileChannel+ByteBuffer 225.887 s 224.932 s 222.077 s 223.812 s 180.177 s
FileUtils.copyFile 233.724 s 230.199 s 232.133 s 223.286 s 189.737 s
Files.copy 229.819 s 227.562 s 226.793 s 226.78 s 181.071 s

The FileReader and BufferedReader lines can be ignored. For small files with FileChannel words is good, for larger files must use FileChannel words can be used with ByteBuffer, but statistically effect is lower than BufferedInput/OutputStream. Look at org.apache.com mons. IO. FileUtils with Java nio. File. Copy of Files, the difference is not too, effect is close to, but at the time of 1 g gap a little big. WalkFileTrees in Java nio are the fastest.

Of course, these tests are for reference only, depending on your environment, and this method is separate from copying. Apache FileUtils has a method for copying directories directly, so it’s up to you to test which one is more appropriate.

8. The source code

The author is more lazy and still all in one file. Line seven hundred.

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("Traversal mode");
    private JFrame showCopyMethod = new JFrame("Mode of replication");

    private JButton traverseMethodButton = new JButton("Please select traversal mode");
    private JButton copyMethodButton = new JButton("Please select replication mode");
    private JButton copyButton = new JButton("Start copying");

    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(a)
    {
        JButton src = new JButton("Select source file (folder)");
        src.addActionListener(
            event ->
            {
                JFileChooser fileChooser = new JFileChooser();
                fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
                fileChooser.showDialog(new Label(), "Select File (Folder)"); FilesCopy.setSrc(fileChooser.getSelectedFile()); }); JButton des =new JButton("Select destination folder");
        des.addActionListener(
            event ->
            {
                JFileChooser fileChooser = new JFileChooser();
                fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
                fileChooser.showDialog(new JLabel(),"Select folder"); 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("Traversal mode");
                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("Mode of replication");
                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."Please select source file (folder) and target folder first!"); }); setLayout(new GridLayout(3.1.5.3));
        setTitle("Copy file");
        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) {
        newTest(); }}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(a)
    {
        return (int)(desSize * 100.0 / srcSize);
    }

    private static void addCopySize(a) {
        desSize += 1024L;
    }

    public static void setTraverseByListFiles(a)
    {
        traverseMethod[0] = true;
    }

    private static void traverseByListFiles(File srcFile,File desFile) throws IOException
    {
        if(srcFile.isDirectory())
        {
            File[] files = srcFile.listFiles();
            assertfiles ! =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(a)
    {
        traverseMethod[1] = true;
    }

    private static void traverseByList(File srcFile,File desFile) throws IOException
    {
        if (srcFile.isDirectory())
        {
            String[] files = srcFile.list();
            assertfiles ! =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(a)
    {
        traverseMethod[2] = true;
    }

    private static void traverseByGetFiles(File srcFile, File desFile) throws IOException
    {
        if (srcFile.isDirectory())
        {
            java.util.List<File> 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(a)
    {
        traverseMethod[3] = true;
    }

    private static void traverseByCommonsIO(File srcFile, File desFile) throws IOException
    {
        if (srcFile.isDirectory())
        {
            Collection<File> 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(a)
    {
        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);
                returnFileVisitResult.CONTINUE; }}); }public static void setCopyByFileStream(a)
    {
        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(a)
    {
        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(a)
    {
        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(a)
    {
        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(a)
    {
        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(a)
    {
        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(a)
    {
        copyMethod[6] = true;
    }

    private static void copyByCommonsIO(File srcFile,File desFile) throws IOException
    {
        FileUtils.copyFile(srcFile, desFile);
    }

    public static void setCopyByFiles(a)
    {
        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("Replication failed, unable to find replication method.");
    }

    private static void showMessage(String message)
    {
        JOptionPane.showMessageDialog(null, message);
    }

    public static boolean haveSelectedSrcAndDes(a)
    {
        returnsrc ! =null&& des ! =null;
    }

    public static void copy(a)
    {
        long start = System.currentTimeMillis();
        if(haveSelectedSrcAndDes())
        {
            if(src.isFile())
            {
                des = new File(des.getAbsolutePath()+File.separator+src.getName());
            }
            SwingWorker<String,Object> copyTask = new SwingWorker<>()
            {
                @Override
                protected String doInBackground(a)
                {
                    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("Traversal failed, traversal method not found"); }}catch (IOException e)
                    {
                        e.printStackTrace();
                        showProgressBar.dispose();
                        showMessage("Unknown error replication failed");
                    }
                    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("Copy Progress");
                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("Copying");
                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("Copying"+text[index++]);
                                else
                                    index = 0; } } ).start(); }}}private static void finish(long start)
    {
        long end = System.currentTimeMillis();
        showProgressBar.dispose();
        showMessage("Copy succeeded." + (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; }}Copy the code