Skip to content

Commit

Permalink
[FS] Speed up LocalFile.copy() by using Java-NIO's Files.copy()
Browse files Browse the repository at this point in the history
Using Files.copy() can be significantly faster than reading the content
from a source InputStream and writing it to a target OutputStream.

The only drawback of using using Files.copy() is that continuous
progress reporting during the copy operation is not possible. For small
files (which are copied in short time) this is not really a relevant and
for large files the performance gain outweighs the loss of fine-grained
progress information.
  • Loading branch information
HannesWell committed Jul 23, 2024
1 parent 33aba47 commit 034c7cc
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class Messages extends NLS {
public static String failedCreateWrongType;
public static String failedCreateAccessDenied;
public static String failedMove;
public static String failedCopy;
public static String failedReadDuringWrite;
public static String fileExists;
public static String fileNotFound;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@
import java.io.OutputStream;
import java.net.URI;
import java.nio.file.AccessDeniedException;
import java.nio.file.CopyOption;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
Expand Down Expand Up @@ -149,6 +151,27 @@ public void copy(IFileStore destFile, int options, IProgressMonitor monitor) thr
super.copy(destFile, options, monitor);
}

private static final CopyOption[] NO_OVERWRITE = {StandardCopyOption.COPY_ATTRIBUTES};
private static final CopyOption[] OVERWRITE_EXISTING = {StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING};

@Override
protected void copyFile(IFileInfo sourceInfo, IFileStore destination, int options, IProgressMonitor monitor) throws CoreException {
if (destination instanceof LocalFile target) {
try {
boolean overwrite = (options & EFS.OVERWRITE) != 0;
Files.copy(this.file.toPath(), target.file.toPath(), overwrite ? OVERWRITE_EXISTING : NO_OVERWRITE);
} catch (FileAlreadyExistsException e) {
Policy.error(EFS.ERROR_EXISTS, NLS.bind(Messages.fileExists, target.filePath), e);
} catch (IOException e) {
Policy.error(EFS.ERROR_WRITE, NLS.bind(Messages.failedCopy, this.filePath, target.filePath), e);
} finally {
IProgressMonitor.done(monitor);
}
} else {
super.copyFile(sourceInfo, destination, options, monitor);
}
}

@Override
public void delete(int options, IProgressMonitor monitor) throws CoreException {
if (monitor == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ deleteProblem = Problems encountered while deleting files.
deleting = Deleting: {0}.
failedCreateAccessDenied=Cannot create file, access denied: {0}.
failedCreateWrongType=Cannot create file because existing file of wrong type exists: {0}.
failedMove = Critical failure moving: {0} to: {1}. Content is lost.
failedMove = Critical failure moving '{0}' to '{1}'. Content is lost.
failedCopy = Could not copy file '{0}' to '{1}'.
failedReadDuringWrite = Could not read from source when writing file: {0}
fileExists = File already exists on disk: {0}.
fileNotFound = File not found: {0}.
Expand Down

0 comments on commit 034c7cc

Please sign in to comment.