Standard Concise Way to Copy a File in Java

Standard concise way to copy a file in Java?

As toolkit mentions above, Apache Commons IO is the way to go, specifically FileUtils.copyFile(); it handles all the heavy lifting for you.

And as a postscript, note that recent versions of FileUtils (such as the 2.0.1 release) have added the use of NIO for copying files; NIO can significantly increase file-copying performance, in a large part because the NIO routines defer copying directly to the OS/filesystem rather than handle it by reading and writing bytes through the Java layer. So if you're looking for performance, it might be worth checking that you are using a recent version of FileUtils.

How to copy file from one location to another location?

You can use this (or any variant):

Files.copy(src, dst, StandardCopyOption.REPLACE_EXISTING);

Also, I'd recommend using File.separator or / instead of \\ to make it compliant across multiple OS, question/answer on this available here.

Since you're not sure how to temporarily store files, take a look at ArrayList:

List<File> files = new ArrayList();
files.add(foundFile);

To move a List of files into a single directory:

List<File> files = ...;
String path = "C:/destination/";
for(File file : files) {
Files.copy(file.toPath(),
(new File(path + file.getName())).toPath(),
StandardCopyOption.REPLACE_EXISTING);
}

Java copy file from folder to another folder with different name

Files.copy() requires the first two parameters to be of type Path.

You need to construct those from your strings i.e.

Path input = Paths.get(config.getValue("pathTemplate"));
Path output = Paths.get(config.getValue("pathOut"));
Files.copy(input, output, REPLACE_EXISTING);

How copy files bigger than 4.3 GB in java

POSIX (and thus Unix) systems are allowed to impose a maximum length on the path (what you get from File.getPath() or the components of a path (the last of which you can get with File.getName()). You might be seeing this problem because of the long name for the file.

In that case, the file open operating system call will fail with an ENAMETOOLONG error code.

However, the message "File too large" is typically associated with the ´EFBIG´ error code. That is more likely to result from a write system call:

An attempt was made to write a file that exceeds the implementation-dependent maximum file size or the process' file size limit.

Perhaps the file is being opened for appending, and the implied lseek to the end of the file is giving the EFBIG error.

In the end, you could try other methods of copying if it has to do something with your RAM.

Also another option could be that the disk is full.

To copy files there are basically four ways [and it turns out streams is the fastest on a basic level] :

Copy with streams:

private static void copyFileUsingStream(File source, File dest) throws IOException {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(source);
os = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
} finally {
is.close();
os.close();
}
}

Copy with Java NIO classes:

private static void copyFileUsingChannel(File source, File dest) throws IOException {
FileChannel sourceChannel = null;
FileChannel destChannel = null;
try {
sourceChannel = new FileInputStream(source).getChannel();
destChannel = new FileOutputStream(dest).getChannel();
destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
}finally{
sourceChannel.close();
destChannel.close();
}
}

Copy with Apache Commons IO FileUtils:

private static void copyFileUsingApacheCommonsIO(File source, File dest) throws IOException {
FileUtils.copyFile(source, dest);
}

and your Method by using Java 7 and the Files class:

private static void copyFileUsingJava7Files(File source, File dest) throws IOException {
Files.copy(source.toPath(), dest.toPath());
}

Edit 1:
as suggested in the comments, here are three SO-questions, which cover the problem and explain the four different methodes of copying better:

  • Standard concise way to copy a file in Java?
  • File copy/move methods and approaches explanation, comparison
  • Reading and writing a large file using Java NIO

Thanks to @jww for pointing it out

Use FileChannel or Files.copy to copy file inside jar

You're barking up the wrong tree. Files.copy has nothing whatsoever to do with support (or lack thereof) of chinese characters, and java does support full unicode pathnames. Yes, it's clear your code isn't currently working as designed, and it can be fixed, but the problem isn't Files.copy.

Sidenote: Your code is broken

Main.class.getResourceAsStream is the correct way to pull resources from your codebase, however, this is a resource, and therefore, you must close it. Wrap it in a try block, that's the smart way to do it.

Objects.requireNonNull should not be used here - its purpose is to forcibly throw a NullPointerException. That's all it does. This code will already throw an NPE if somehow that resource is missing. This means the requireNonNull is completely pointless (it is enforcing a thing that already happens), and if you want clean code, either is inappropriate: You should be rethrowing with an exception that properly conveys the notion that the app is broken.

However, that isn't a good idea either: We don't throw exceptions for bugs or broken deployments. If you think you should, then you should wrap every line of code in your entire java project with a try/catch block, after all, evidently we can't assume anything. We can't even assume java.lang.String is available at run time - clearly this is not a sustainable point of view. In other words, you may safely assume that the resource couldn't possibly not be there for the purposes of exception flow.

Thus, we get to this much simpler and safer code:

try (var in = Main.class.getResourceAsStream("/amres/core/template.xlsx")) {
Files.copy(in, Paths.get("C:/我的/test.xlsx"), StandardCopyOption.REPLACE_EXISTING);
}

Note that in general, catching an exception and handling it with e.printStackTrace() is also just bad, in all cases: You're printing the exception to a place it probably shouldn't go, tossing useful info such as the causal chain, and then letting code exception continue even though your code's state is clearly in an unexpected and therefore unknown state. The best general solution is to actually throws the exception onwards. If that is not feasible or you just don't want to care about it right now and thus relying on your IDE's auto-fixes and not bothering to edit anything, then at least fix your IDE's auto-fixer to emit non-idiotic code. throw new RuntimeException("uncaught", e) is the proper 'I do not want to care about this right now' fillin. So, fix your IDE. It's generally in the settings, under 'template'.

What could be causing this

Every single time chars turn to bytes or vice versa, charset encoding is involved. Filenames look like characters and certainly when you write code, you're writing characters, and when you see the text of the NoSuchFileException, that's characters - but what about all the stuff in between? In addition, names in file systems themselves are unclear: Some filesystem names are byte-based. For example, Apple's APFS is entirely bytebased. File names just are bytes, and the idea of rendering these bytes onto the screen (and translating e.g. touch foobar.txt on the command line onto the byte sequence value for the file name) are done with UTF-8 merely by convention. In contrast some file systems encode this notion of a set encoding directly into its APIs. Best bet is to UTF_8 all the things, that's the least chance of things going awry.

So, let's go through the steps:

  1. You write java code in a text editor. You write characters.
  2. File content is, universally, byte based, on all file systems. Therefore, when you hit the 'save' shortcut in your text editor, your characters are converted into bytes. Check that your editor is configured in UTF-8 mode. Alternatively, use backslash-u escapes to avoid the issue.
  3. You compile this code. Probably with javac, ecj, or something based on one of those two. They read in a file (so, bytes), but parse the input as characters, therefore conversion is happening. Ensure that javac/ecj is invoked with the --encoding UTF-8 parameter. If using a build tool such as maven or gradle, ensure this is explicitly configured.
  4. That code is run and prints its error to a console. A console shows it to you. The console is converting bytes (because app output is a byte-based stream) to chars in order to show it to you. Is it configured to do this using UTF-8? Check the terminal app's settings.

Check all the bolded items, 95%+ chance you'll fix your problem by doing this.



Related Topics



Leave a reply



Submit