Hopefully someone has seen this before. I'm trying to copy all directory contents from the source to a different directory, and for this I started using the Commons FileUtils.copyDirectorytoDirectory method(File src, File dest). The code is pretty simple:
public static void copyDirtoDir(String src, String dest) {
File s = new File(src);
File d = new File(dest);
try {
FileUtils.copyDirectoryToDirectory(s, d);
} catch (IOException e) {
e.printStackTrace();
}
}
To run this test on Linux, I'm running the app as a JAR and passing the src and dest strings from the command line. The problem is that when I check the resulting directory size after execution, there's a huge difference in size (with the copied dir around twice the size of the original - checked using 'du -sh').
I then simply tried with nio.FileChannels, as follows:
public static void copyFile(File in, File out) throws IOException {
FileChannel source = new FileInputStream(in).getChannel();
FileChannel destination = new FileOutputStream(out).getChannel();
source.transferTo(0, source.size(), destination);
source.close();
destination.close();
}
Calling this method for every file inside the directory. The resulting size from this variation is also around twice the size of the original. If I do a listing of the directories' contents, they are the same.
Is there any missing parameter or something that could be causing this size difference?
Not sure what's going on, but you can use diff to diff directories. I'm sure that will pin down the differences easily.
The javadoc says that copyDirectoryToDirectory copies the source directory and all its contents to a directory of the same name in the specified destination directory.
Without seeing your directory structure, I'm guessing this may cause the double data. Any reason why you're not using the simple FileUtils.copyDirectory() ?
Related
This question already has answers here:
java.io.FileNotFoundException: the system cannot find the file specified
(8 answers)
Closed 4 years ago.
I have a csv file in the same path as everything else. Now, when I try to create a File object:
public void getMenu() {
File fileMenu = new File("FastFoodMenu.csv");
try {
Scanner inputStream = new Scanner(fileMenu);
while (inputStream.hasNext()) {
String data = inputStream.next();
System.out.println(data);
}
} catch (FileNotFoundException ex) {
Logger.getLogger(FileHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
it throws a FileNotFoundException.
the absolute path to all files in the project is:
C:\Users\kenyo\Documents\NetBeansProjects\OrderFastFood\src\fastfoodorderingsystem
I also checked the name a couple of times. fileMenu.exists() returns false.
First, in your root/working directory (in your case it's the folder containing your project), create a folder called 'menus', here you can store all your menus (so you can play around with multi-file input).
Second, move your FastFoodMenu.csv file to that menus folder.
The FastFoodMenu.csv relative path should now look like this: OrderFastFood\menus\FastFoodMenu.csv.
Third, get your working directory from the System properties. This is the folder in which your program is working in. Then, get a reference (File object) to the menus folder.
Lastly, get a reference to the file in question inside the menu folder. When you get to multi-file reading (and at some point, multi-folder reading), you're gonna want to get the files inside the menu folder as a list so that's why I say to just get the menus folder as it's own reference (or just get the file without the isolated reference to the parent aka '\menus\').
So your code should really look like this:
public void getMenu() {
final File workingDir = File(System.getProperty("user.dir"));
final File menusDir = File(workingDir, "menus");
final File fastFoodMenu = File(menusDir, "FastFoodMenu.csv");
try {
final FileInputStream fis = new FileInputStream(fastFoodMenu);
final BufferedInputStream bs = new BufferedInputStream(fis);
while((l = bs.readLine()) != null) {
System.out.println(l);
}
} catch(FileNotFoundException e) {
System.out.println(e.getMessage());
e.printStackTrace()
}
}
This is all psuedocode but that should at least get you started. Make sure to use BufferedInputStream for efficiency, and when reading files, always pass them into FileInputStream's. It's much better than using the Scanner class. I should also mention that when creating a File object, you're not actually creating a file. What you're doing is your're creating an object, giving it the data you want it to have (such as whether it's a folder, and if it is, what child files/folders do you want it to have, whether it's protected or not, hidden or not, etc) before actually telling the system to create the file with everything else.
Your csv file is probably at the wrong place. You're just specifying the file name, which is a relative path.
Relative paths are always resolved against the working directory of your application, not against the directory where your source file(s) are.
To solve the issue, you can
move the files to the real working directory.
use an absolute path (not advisable!)
specify the folder of your data files as program argument or in a config file (in your working directory)
put the files somewhere into the classpath of your application and load them from there via classloader. Note that files that are in your classpath are usually packed with your application and hence not easily modifiable by the user, so this solution doesn't work if the file must be changed by the user.
In Python the global variable __file__ is the full path of the current file.
System.getProperty("user.dir"); seems to return the path of the current working directory.
I want to get the path of the current .java, .class or package file.
Then use this to get the path to an image.
My project file structure in Netbeans looks like this:
(source: toile-libre.org)
Update to use code suggested from my chosen best answer:
// read image data from picture in package
try {
InputStream instream = TesseractTest.class
.getResourceAsStream("eurotext.tif");
bufferedImage = ImageIO.read(instream);
}
catch (IOException e) {
System.out.println(e.getMessage());
}
This code is used in the usage example from tess4j.
My full code of the usage example is here.
If you want to load an image file stored right next to your class file, use Class::getResourceAsStream(String name).
In your case, that would be:
try (InputStream instream = TesseractTest.class.getResourceAsStream("eurotext.tif")) {
// read stream here
}
This assumes that your build system copies the .tif file to your build folder, which is commonly done by IDEs, but requires extra setup in build tools like Ant and Gradle.
If you package your program to a .jar file, the code will still work, again assuming your build system package the .tif file next to the .class file.
Is there a way to get the file path of the .java file executed or compiled?
For completeness, the literal answer to your question is "not easily and not always".
There is a round-about way to find the source filename for a class on the callstack via StackFrameElement.getFileName(). However, the filename won't always be available1 and it won't necessarily be correct2.
Indeed, it is quite likely that the source tree won't be present on the system where you are executing the code. So if you needed an image file that was stashed in the source tree, you would be out of luck.
1 - It depends on the Java compiler and compilation options that you use. And potentially on other things.
2 - For example, the source tree can be moved or removed after compilation.
Andreas has described the correct way to solve your problem. Make sure that the image file is in your application's JAR file, and access it using getResource or getResourceAsStream. If your application is using an API that requires a filename / pathname in the file system, you may need to extract the resource from the JAR to a temporary file, or something like that.
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(getPackageParent(Main.class, false));
}
public static String getPackageParent(Class<?> cls, boolean include_last_dot)
throws Exception {
StringBuilder sb = new StringBuilder(cls.getPackage().getName());
if (sb.lastIndexOf(".") > 0)
if (include_last_dot)
return sb.delete(sb.lastIndexOf(".") + 1, sb.length())
.toString();
else
return sb.delete(sb.lastIndexOf("."), sb.length()).toString();
return sb.toString();
}
}
I am a real beginner at Java programming so I hope I'm not wasting anyone's time. I tried my best to research this but couldn't come up with a solution.
I am following the Lynda video series "Java Essential Training" and it's been very good so far. I am currently learning how to copy the contents of a text file onto a new text file. However, the video shows a alternative method by downloading commons IO from Apache commons and adding the .jar file to the project.
In the video the jar file was added to build path. My version of eclipse seemed to do it automatically as "Referenced Libraries" popped up, and when I tried to add it eclipse said it was already there.
I followed the video exactly. The code looks like this
package com.lynda.files;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
public class Main {
public static void main(String[] args) {
try {
File f1 = new File("loremipsum.txt");
File f2 = new File("target.txt");
FileUtils.copyDirectory(f1, f2);
System.out.println("File copied!");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
When I ran the code I got the message in console
java.io.IOException: Source 'loremipsum.txt' exists but is not a directory
at org.apache.commons.io.FileUtils.copyDirectory(FileUtils.java:1371)
at org.apache.commons.io.FileUtils.copyDirectory(FileUtils.java:1261)
at org.apache.commons.io.FileUtils.copyDirectory(FileUtils.java:1230)
at com.lynda.files.Main.main(Main.java:16)
In the code it says the FileUtils imported but eclipse tells me "The source attachment does not contain the source for file FileUtils.class". I tried to change the attached source but it gave me the error "Could not write to file BlahBlahBlah.classpath (Access is denied)
Hopefully I didn't drone on about something obvious and simple. I thought it best to be as clear as possible in case someone else has a similar problem.
Edit
I feel so stupid. Thank you for your help. I clicked on "copyDirectory" instead of "copyFile". Next time, instead of panicking, googling every line of error and asking people for help, I'll take the time to go through each line and think about what it does. Thanks to all of you for your help and patience.
See (http://commons.apache.org/proper/commons-io/javadocs/api-2.4/org/apache/commons/io/FileUtils.html#copyFile%28java.io.File,%20java.io.File%29)
Use FileUtils.copyFile(f1, f2); instead of FileUtils.copyDirectory(f1, f2);
The source and target File parameters of copyDirectory must be directories, but you are suppling text files.
public static void copyDirectory(File srcDir,File destDir)
throws IOException
Copies a whole directory to a new location preserving the file dates.
This method copies the specified directory and all its child directories and files to the specified destination. The destination is the new location and name of the directory.
The destination directory is created if it does not exist. If the destination directory did exist, then this method merges the source with the destination, with the source taking precedence.
Note: This method tries to preserve the files' last modified date/times using File.setLastModified(long), however it is not guaranteed that those operations will succeed. If the modification operation fails, no indication is provided.
Parameters:
srcDir - an existing directory to copy, must not be null
destDir - the new directory, must not be null
Throws:
NullPointerException - if source or destination is null
IOException - if source or destination is invalid
IOException - if an IO error occurs during copying
Since:
1.1
(Source)
I found this that may be of help to you:
copyFile(File srcFile, File destFile) Copies a file to a new location preserving the file date.
static void copyFile(File srcFile, File destFile, boolean preserveFileDate) Copies a file to a new location.
static long copyFile(File input, OutputStream output) Copy bytes from a File to an OutputStream.
static void copyFileToDirectory(File srcFile, File destDir) Copies a file to a directory preserving the file date.
static void copyFileToDirectory(File srcFile, File destDir, boolean preserveFileDate) Copies a file to a directory optionally preserving the file date.
Source
Although it's from the Apache site, it does talk about the Java classes.
Please read the error message again:
Source 'loremipsum.txt' exists but is not a directory
This is not exactly what you wrote in your subject. Indeed the file 'loremipsum.txt' exists but it not a directory. It is regular file. However you try to call FileUtils.copyDirectory() and pass this regular file to this method. But this method is not ready to work with files. It supports directories only. This is exactly what is written in error message.
EDIT
Now the question is why do you call method that definitely for intended for directories with parameters that are definitely files?
I am getting used to Java 7 and the new Files class.
I am writing a small application which, at some point, must replace the contents of a file.
I used a temporary file to avoid erasing the target file if somethign goes wrong. However, I'm always getting an AccessDeniedException when performing the actual copy.
Here is my code:
// Temporary file generation.
Path target = getCurrentConfigFile(); // Returns a path, works ok.
Path tempFile = Files.createTempFile("tempfile", null);
Files.write(tempFile, conf.getBytes(Charset.defaultCharset()), StandardOpenOption.WRITE);
// Actual copy.
Files.copy(tempFile, target, StandardCopyOption.REPLACE_EXISTING);
// Cleanup.
Files.delete(tempFile);
getCurrentConfigFile() handles the target file Path creation:
(... generates various strings from configuration parameters)
return FileSystems.getDefault().getPath(all, these, various, strings);
When I execute the code, it's through a .bat script, and I get the error both with a standard Command Prompt or elevation.
The target file is in C:\temp\tests, a directory I created with the same Windows user.
It seems the problem lies in reading from the temporary file, as writing directly to the target works.
Where should I look next?
Not an answer but too long for a comment. I run the code below (from the command line on Windows 7) and it works as expected:
public static void main(String[] args) throws IOException {
Path target = Paths.get("C:/temp/test.txt"); // Returns a path, works ok.
Path tempFile = Files.createTempFile("tempfile", null);
Files.write(tempFile, "abc".getBytes(UTF_8), StandardOpenOption.WRITE);
// Actual copy.
Files.copy(tempFile, target, StandardCopyOption.REPLACE_EXISTING);
// Cleanup.
Files.delete(tempFile);
}
so your problem is not with that code. It may be somewhere else in your code or due to the permissions on the files/folder you are using.
I have a little application which copy PDF files (subfolders) to a destination folder. But it works very slow, I would like to optimize it. Can you help me?
The code:
public void pdfFolderCopy(File src, File dest)
throws IOException {
if (src.isDirectory()) {
if (!dest.exists()) {
dest.mkdir();
}
String files[] = src.list();
for (String file : files) {
File srcFile = new File(src, file);
File destFile = new File(dest, file);
pdfFolderCopy(srcFile, destFile);
}
} else {
if (!dest.exists()) {
System.out.println("Copying: " + src);
//Use the Apache IO copyFile method:
FileUtils.copyFile(src, dest);
}
}
}
It is runs about one and a half minutes if every files are already exist. And about 5 minutes, if we need to copy about 500 files.
The only real time consuming task in your code is FileUtils.copyFile(). The necessary time will growing according to the number of files to copy and their size.
Regarding your code I would suggest to extract the check for dest directory since it shouldn't change during the copy process. Check and create the dest directory before you start pdfFolderCopy.
I'd try to simply invoke a process doing
/bin/cp -R -n src dest
where -R means recursive and -n means don't overwrite. There's a good chance that the OS can do this faster then you. No idea what's the corresponding command for Windows or other OS.
For this you need just
new ProcessBuilder()
.command("/bin/cp", "-R", "-n", src.toString(), dest.toString())
.start();
In case you want to do it in Java, I'd try some minor changes:
dest.mkdir() without any check works and might be a bit faster
listFiles might be faster than composing them manually (probably irrelevant)
once you've created a dest folder yourself, you don't need to check if there are any pre-existing files there
I guess, multithreading may lead to a nice speedup: Let the main thread create copying jobs and submit them to some executor (with some 4-8 threads).
Note that such multithreaded writes may lead to higher disk fragmentation, but I wouldn't care. If I had to, then I'd create file reding jobs instead, let them return the file content (n * 100 KB is nothing), and use a single writer thread.