Java file copy fails - java

I have written a very simple Java program to copy a file passed as an argument to the /tmp directory. The program produces several Java exceptions.
public class CopyFile {
public static void main(String[] args) throws IOException {
String fqp2File = "";
if (new File(args[0]).isFile()) {
fqp2File = args[0];
}
else {
System.out.println("Passed argument is not a file");
}
copy(fqp2File, "/tmp");
}
private static boolean copy(String from, String to) throws IOException{
Path src = Paths.get(from);
Path dest = Paths.get(to);
try {
Files.copy(src, dest, StandardCopyOption.REPLACE_EXISTING);
return true;
} catch (IOException ioe) {
System.err.format("I/O Error when copying file");
ioe.printStackTrace();
return false;
}
}
}
When I run this program I get these errors:
java -jar CopyFile.jar /home/downloads/dfA485MVSZ.ncr.pwgsc.gc.ca.1531160874.13500750
I/O Error when copying filejava.nio.file.FileSystemException: /tmp:
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:103)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:114)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:119)
at sun.nio.fs.UnixCopyFile.copy(UnixCopyFile.java:578)
at sun.nio.fs.UnixFileSystemProvider.copy(UnixFileSystemProvider.java:265)
at java.nio.file.Files.copy(Files.java:1285)
at ca.gc.ssc.gems.esnap.cipo.CopyFile.copy(CopyFile.java:39)
at ca.gc.ssc.gems.esnap.cipo.CopyFile.main(CopyFile.java:31)

To test your code I used C:/tmp/test.txt; as your args[0]. I fixed the issue by giving the output a filename to write to shown below:
Path dest = Paths.get(to);
to
Path dest = Paths.get(to, "test2.txt");
And it now successfully copied the file into that name, you can modify the filename however you want or add logic to change filename automatically.

Related

Copy all files from Source to Destination Java

I have to code a java method public void public void copyTo(Path rSource, Path rDest) that copies all files from existing directory rSource to a new directory rDest with the same name. rSource must exist and rDest must not exist, runtime exception if not true. I can't seem to make it work, help!
What I tried :
public void copyTo(Path rSource, Path rDest){
if(!(Files.exists(rSource) && Files.isDirectory(rSource)) || (Files.exists(rDest))){
throw new RuntimeException();
}
try {
Files.createDirectory(rDest);
if(Files.exists(rDest)){
try(DirectoryStream<Path> stream = Files.newDirectoryStream(rSource)) {
for(Path p : stream) {
System.out.println(p.toString());
Files.copy(p, rDest);
}
} catch( IOException ex) {
}
}
} catch (IOException e) {
}
}
Files.copy() at least takes two parameters, source and destination files path or stream. The problem in your case is that you are passing rDest folder Path, not the actual file Path. Just modify the code inside your for loop to append the files name from the source to the destination folder Path:
Path newFile = Paths.get(rDest.toString() + "/" + p.getFileName());
Files.copy(p, newFile);
Correct me if I'm wrong

Moving a directory in java throws java.nio.file.FileAlreadyExistsException

I am creating a rollback feature and here is what I have and wanna achieve:
a tmp folder is created in the same location as the data folder;
before doing any operation I copy all the contents from data folder to tmp folder (small amount of data).
On rollback I want to delete the data folder and rename tmp folder to data folder.
This is what I tried
String contentPath = "c:\\temp\\data";
String tmpContentPath = "c:\\temp\\data.TMP";
if (Files.exists(Paths.get(tmpContentPath)) && Files.list(Paths.get(tmpContentPath)).count() > 0) {
FileUtils.deleteDirectory(new File(contentPath));
Files.move(Paths.get(tmpContentPath), Paths.get(contentPath), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
}
but this throws FileAlreadyExistsException even though I deleted the target directory in the same method.
Once the program exits I don't see the c:\temp\data directory, so the directory is actually deleted.
Now if I try StandardCopyOption.ATOMIC_MOVE it throws an java.nio.file.AccessDeniedException.
What is the best way to move tmp dir to data dir in these kind of situations?
Actually in java 7 or above you can just use the Files to achieve the folder moving even there is a conflict, which means the target folder already exists.
private static void moveFolder(Path thePath, Path targetPath) {
if (Files.exists(targetPath)) { // if the target folder exists, delete it first;
deleteFolder(targetPath);
}
try {
Files.move(thePath, targetPath);
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
private static void deleteFolder(Path path) {
try {
if (Files.isRegularFile(path)) { // delete regular file directly;
Files.delete(path);
return;
}
try (Stream<Path> paths = Files.walk(path)) {
paths.filter(p -> p.compareTo(path) != 0).forEach(p -> deleteFolder(p)); // delete all the children folders or files;
Files.delete(path); // delete the folder itself;
}
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
Try This
public class MoveFolder
{
public static void main(String[] args) throws IOException
{
File sourceFolder = new File("c:\\temp\\data.TMP");
File destinationFolder = new File("c:\\temp\\data");
if (destinationFolder.exists())
{
destinationFolder.delete();
}
copyAllData(sourceFolder, destinationFolder);
}
private static void copyAllData(File sourceFolder, File destinationFolder)
throws IOException
{
destinationFolder.mkdir();
String files[] = sourceFolder.list();
for (String file : files)
{
File srcFile = new File(sourceFolder, file);
File destFile = new File(destinationFolder, file);
copyAllData(srcFile, destFile); //call recursive
}
}
}
Figured out the issue. In my code before doing a rollback, I am doing a backup, in that method I am using this section to do the copy
if (Files.exists(Paths.get(contentPath)) && Files.list(Paths.get(contentPath)).count() > 0) {
copyPath(Paths.get(contentPath), Paths.get(tmpContentPath));
}
Changed it to
try (Stream<Path> fileList = Files.list(Paths.get(contentPath))) {
if (Files.exists(Paths.get(contentPath)) && fileList.count() > 0) {
copyPath(Paths.get(contentPath), Paths.get(tmpContentPath));
}
}
to fix the issue

How to use a Path object as a String

I'm looking to try and create a Java trivia application that reads the trivia from separate question files in a given folder. My idea was to use the run() method in the FileHandler class to set every text file in the folder into a dictionary and give them integer keys so that I could easily randomize the order at which they appear in the game. I found a simple chunk of code that is able to step through the folder and get the paths of every single file, but in the form a Path class. I need the paths (or just the names) in the form a String class. Because I need to later turn them into a file class (which excepts a String Constructor, not a Path). Here is the chunk of code that walks through the folder:
public class FileHandler implements Runnable{
static Map<Integer, Path> TriviaFiles; //idealy Map<Integer, String>
private int keyChoices = 0;
public FileHandler(){
TriviaFiles = new HashMap<Integer, Path>();
}
public void run(){
try {
Files.walk(Paths.get("/home/chris/JavaWorkspace/GameSpace/bin/TriviaQuestions")).forEach(filePath -> {
if (Files.isRegularFile(filePath)) {
TriviaFiles.put(keyChoices, filePath);
keyChoices++;
System.out.println(filePath);
}
});
} catch (FileNotFoundException e) {
System.out.println("File not found for FileHandler");
} catch (IOException e ){
e.printStackTrace();
}
}
public static synchronized Path getNextValue(){
return TriviaFiles.get(2);
}
}
There is another class named TextHandler() which reads the individual txt files and turns them into questions. Here it is:
public class TextHandler {
private String A1, A2, A3, A4, question, answer;
//line = null;
public void determineQuestion(){
readFile("Question2.txt" /* in file que*/);
WindowComp.setQuestion(question);
WindowComp.setAnswers(A1,A2,A3,A4);
}
public void readFile(String toRead){
try{
File file = new File("/home/chris/JavaWorkspace/GameSpace/bin/TriviaQuestions",toRead);
System.out.println(file.getCanonicalPath());
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
question = br.readLine();
A1 = br.readLine();
A2 = br.readLine();
A3 = br.readLine();
A4 = br.readLine();
answer = br.readLine();
br.close();
}
catch(FileNotFoundException e){
System.out.println("file not found");
}
catch(IOException e){
System.out.println("error reading file");
}
}
}
There is stuff I didn't include in this TextHandler sample which is unimportant.
My idea was to use the determineQuestion() method to readFile(FileHandler.getNextQuestion).
I am just having trouble working around the Path to String discrepancy
Thanks a bunch.
You can simply use Path.toString() which returns full path as a String. But kindly note that if path is null this method can cause NullPointerException. To avoid this exception you can use String#valueOf instead.
public class Test {
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
Path path = Paths.get("/my/test/folder/", "text.txt");
String str = path.toString();
// String str = String.valueOf(path); //This is Null Safe
System.out.println(str);
}
}
Output
\my\test\folder\text.txt

IllegalStateException: Iterator already obtained [duplicate]

This question already has an answer here:
java.lang.IllegalStateException: Iterator already obtained
(1 answer)
Closed 7 years ago.
so I wrote a little Java program to test a little stack language I made vie various test file, but for some reason it won't work.
Here is the code:
import org.apache.commons.io.FilenameUtils;
import java.io.IOException;
import java.nio.file.*;
public class Main {
public static void run(DirectoryStream<Path> files) throws IOException {
for (Path f : files) {
String ext = FilenameUtils.getExtension(f.toString());
if (ext.equals("slang")) { // if extension "slang" run program slang with slang test file as argument and dump result int a file with the same base name but .test extension
Runtime.getRuntime().exec("java slang < " + f.getFileName() + " > " + FilenameUtils.getBaseName(f.toString()) + ".test");
}
}
}
public static void main(String[] args) {
try {
Runtime.getRuntime().exec("javac slang.java; "); // compile slang
} catch (IOException e) {
e.printStackTrace();
}
Path dir = Paths.get("C:\\Users\\Anton\\Documents\\TU Wien\\PK\\SS2015\\Abschlussaufgabe\\Slang\\progs");
try { //create list of all Files in test directory Files
DirectoryStream<Path> files = Files.newDirectoryStream(dir);
run(files); //run all needed files
compare(files); //compare all files
} catch (IOException | DirectoryIteratorException x) {
System.err.println(x);
x.printStackTrace();
}
}
public static void compare(DirectoryStream<Path> files) throws IOException {
for (Path f : files) {
String ext = FilenameUtils.getExtension(f.toString()); //is it a test file?
if (ext.equals("test")) {
String outputPath = FilenameUtils.getBaseName(f.toString()) + ".output"; //get path of output
Path output = Paths.get(outputPath);
if (!fileEquals(f, output)) { // compare them
System.err.println("Not Equal:" + f.getFileName()); // errormessage if fault, else just continue
}
}
//files.iterator().remove();
//files.iterator().next();
}
}
private static boolean fileEquals(Path p, Path q) throws IOException {
String contentP = new String(Files.readAllBytes(p)); //turn into string then compare, no idea whether best practice
String contentQ = new String(Files.readAllBytes(q));
return contentP.equals(contentQ);
}
}
When I run it, it throws "Exception in thread "main" java.lang.IllegalStateException: Iterator already obtained".
i already tried it with the iterator().remove and iterator().next, but it only leads to the application running longer before throwing the error.
Thank you for any help beforehand.
Addition: The error occures at the foreach loop through the DirectoryStream.
You have to call DirectoryStream<Path> files = Files.newDirectoryStream(dir); each time you iterate over the files.
Pls check this question...
java.lang.IllegalStateException: Iterator already obtained

How to display the contents of a directory

I need to write a recursive algorithm to display the contents of a directory in a computer's file system but I am very new to Java. Does anyone have any code or a good tutorial on how to access a directory in a file system with Java??
You can use the JFileChooser class, check this example.
Optionally you can also execute native commands like DIR , lsusing java , here is an example
This took me way too long to write and test, but here's something that should work.
Note: You can pass in either a string or file.
Note 2: This is a naive implementation. Not only is it single-threaded, but it does not check to see if files are links, and could get stuck in an endless loop due to this.
Note 3: The lines immediately after comments can be replaced with your own implementation.
import java.io.*;
public class DirectoryRecurser {
public static void parseFile(String filePath) throws FileNotFoundException {
File file = new File(filePath);
if (file.exists()) {
parseFile(file);
} else {
throw new FileNotFoundException(file.getPath());
}
}
public static void parseFile(File file) throws FileNotFoundException {
if (file.isDirectory()) {
for(File child : file.listFiles()) {
parseFile(child);
}
} else if (file.exists()) {
// Process file here
System.out.println(file.getPath());
} else {
throw new FileNotFoundException(file.getPath());
}
}
}
Which could then be called something like this (using a Windows path, because this Workstation is using Windows):
public static void main(String[] args) {
try {
DirectoryRecurser.parseFile("D:\\raisin");
} catch (FileNotFoundException e) {
// Error handling here
System.out.println("File not found: " + e.getMessage());
}
}
In my case, this prints out:
File not found: D:\raisin
because said directory is just one I made up. Otherwise, it prints out the path to each file.
Check out Apache Commons VFS: http://commons.apache.org/vfs/
Sample:
// Locate the Jar file
FileSystemManager fsManager = VFS.getManager();
FileObject jarFile = fsManager.resolveFile( "jar:lib/aJarFile.jar" );
// List the children of the Jar file
FileObject[] children = jarFile.getChildren();
System.out.println( "Children of " + jarFile.getName().getURI() );
for ( int i = 0; i < children.length; i++ )
{
System.out.println( children[ i ].getName().getBaseName() );
}
If you need to access files on a network drive, check out JCIFS: http://jcifs.samba.org/
check this out buddy
http://java2s.com/Code/Java/File-Input-Output/Traversingallfilesanddirectoriesunderdir.htm
public class Main {
public static void main(String[] argv) throws Exception {
}
public static void visitAllDirsAndFiles(File dir) {
System.out.println(dir);
if (dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
visitAllDirsAndFiles(new File(dir, children[i]));
}
}
}
}
For each file you need to check if it is a directory. If it is, you need to recurse. Here is some untested code, which should help:
public void listFiles(File f){
System.out.println(f.getAbsolutePath());
if(f.isDirectory()){
for (File i : f.listFiles()){
listFiles(i);
}
}
}

Categories