copy files and directory in java - java

In my program I suppose to copy a directory to another directory with java. I did it but the only problem is that for the directories that are inside the source directory get copied but not the file inside them. Why?
This is the assigment:
Ask the user for the source directory and a destination. The source is the directory to be copied; the destination is the directory that will be the parent of the new copy.
First your program should make a new directory in the new location with the same name as the source directory. (You may need to do something special for root directories if you are copying an entire disk. A root directory has no parent directory, and often, no name.)
Then your program should create an array with File class objects for each item in the contents of the source directory, similar to what was done in DirectoryListDemo.
Next , it should iterate the array, and for each item in the array,
if it is a file, copy the file to the new directory using the copyFile() method taken from CopyFileDemoE.
if it is a directory, recursively call this method to copy the directory and all of its contents.
Here is the code:
package com.company;
import java.io.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception {
Scanner src = new Scanner(System.in);
System.out.println("Enter name of source directory to copy from: ");
String sourceFile= src.nextLine();
System.out.println("Enter name of destination directory to copy the files into: ");
String destinationFile = (src.nextLine()+"/"+sourceFile);
isDirFile(sourceFile, destinationFile);
}
public static void isDirFile(String source, String dest) throws Exception{
File sourceFile = new File ("C:/"+source);
File dirFile = new File (dest, new File(source).getName());
dirFile.mkdirs();
File[] entries;
if (dirFile.exists()){
if (sourceFile.isDirectory()){
entries = sourceFile.listFiles();
assert entries != null;
for (File entry:entries){
if(entry.isFile()){
copyFile(entry.getAbsolutePath(),dest);
}
else{
isDirFile(entry.getAbsolutePath(),dest);
}
}
}
}
else{
System.out.println("File does not exist");
}
}
public static void copyFile(String source, String destination) throws Exception{
File sourceFile;
File destFile;
FileInputStream sourceStream;
FileOutputStream destSteam;
BufferedInputStream bufferedSource = null;
BufferedOutputStream bufferedDestination = null;
try{
sourceFile = new File(source);
destFile = new File (destination, new File(source).getName());
sourceStream = new FileInputStream(sourceFile);
destSteam = new FileOutputStream(destFile);
bufferedSource = new BufferedInputStream(sourceStream, 8182);
bufferedDestination = new BufferedOutputStream(destSteam, 8182);
int transfer;
System.out.println("Beginning file copy: ");
System.out.println("\tcopying "+ source);
System.out.println("\tto "+destination);
while ((transfer = bufferedSource.read()) != -1){
bufferedDestination.write(transfer);
}
}
catch (IOException e){
e.printStackTrace();
System.out.println(" An unexpected I/O error occurred.");
}
finally {
if(bufferedSource != null){
bufferedSource.close();
}
if(bufferedDestination != null){
bufferedDestination.close();
}
System.out.println("Files closed. Copy complete.");
}
}
}

Related

Always receiving FileNotFoundException, even with file in SRC folder

I'm currently trying to write a program that will read in a file line by line and add each line to an arrayList. My other function is supposed to sort the items from that buffer, then write them to a text file. However, I keep getting a FileNotFoundException, even when my file is sitting in the src directory, as well as the directory with my .class file. My code is as follows
public static ArrayList<String> readDictionary(String filename,
ArrayList<String> buffer) throws IOException, FileNotFoundException {
File f = new File(filename);
Scanner fileIn = new Scanner(f);
//Scanner fileIn = new Scanner(new File(filename));
boolean add = true;
while (fileIn.hasNextLine() == true) {
for (String s : buffer) {
if (fileIn.nextLine().equals(s)) {
add = false;
}
}
if (add == true) {
buffer.add(fileIn.nextLine());
}
add = true;
}
fileIn.close();
return buffer;
}
public static void writeDictionary(String filename, ArrayList<String> buffer) throws IOException, FileNotFoundException {
File f = new File(filename);
Collections.sort(buffer, String.CASE_INSENSITIVE_ORDER);
Path file = Paths.get(filename);
Files.write(file, buffer);
}
public static void main(String[] args) throws IOException, FileNotFoundException{
ArrayList<String> buffer = new ArrayList<>();
readDictionary("inputtest.txt", buffer);
}
Exception in thread "main" java.io.FileNotFoundException: inputtest.txt (The system cannot find the file specified)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.util.Scanner.<init>(Scanner.java:611)
at UltimateDictionary.readDictionary(UltimateDictionary.java:18)
at UltimateDictionary.main(UltimateDictionary.java:46)
I tested this program by setting filename equal to "inputtest.txt", and that file is sitting in my src directory with the .java file, but it still throws the error. Also, how can I close the files? f.close() gives me an error.
The file in your src or .class directory, could only mean that the file is in classpath, while new File(filename); search the current working directory. To search classpath, change readDictionary method, after File f = new File(filename); add:
if (!f.exists()) {
URL url = <yourclassname>.class.getResource(filename);
if (url != null)
f = new File(url.getPath());
}
you have to use yourclassname.class because the method is static. Should work also:
if (url == null)
url = ClassLoader.getSystemResource(filename);

Copying saved files from a List<File> into a directory recursively in java

I have searched for this answer and I have tried to solve the problem but I can't. I got and Exception of type
No fue posible copiar los archivos. Motivo: C:\Test1 (Acceso denegado)java.io.FileNotFoundException: C:\Test1 (Acceso denegado)
java.io.FileNotFoundException: C:\Test1 (Acceso denegado)
Translated would be something like "It was not possible copying the files. Motive: (Access denied)".
What I am trying to do is to copy a List into a directory recursively.
I could simply copy the files recursively (I already did that) but the requirements are to copy all into a List and then do whatever I want (copy, delete, etc) with the records in the list.
My List contains this records:
C:\Test\Carpeta_A
C:\Test\Carpeta_A\Entrenamiento_1.txt
C:\Test\Carpeta_A\Requerimientos.txt
C:\Test\Carpeta_B
C:\Test\Carpeta_B\queries.txt
C:\Test\Things.txt
Here is my code:
This is the main method.. it calls a method for listing and saving the files and directories and then calls the method for copying the files into another directory preserving my main structure:
public static void main(String[] args) throws IOException
{
String fuente = "C:/Test";
String ruta = "C:/Test1";
teeeeeest listing = new teeeeeest();
List<File> files = listing.getFileListing(fuente);
listing.copyDirectories(files, ruta);
}
public List<File> getFileListing( String fuente ) throws FileNotFoundException
{
List<File> result = getFileListingNoSort(fuente);
Collections.sort(result);
return result;
}
private List<File> getFileListingNoSort( String fuente ) throws FileNotFoundException
{
File source = new File(fuente);
List<File> result = new ArrayList<>();
File[] filesAndDirs = source.listFiles();
List<File> filesDirs = Arrays.asList(filesAndDirs);
for(File file : filesDirs) {
result.add(file); //always add, even if directory
String s = file.getPath().trim();
if (! file.isFile()) {
//must be a directory
//recursive call!
List<File> deeperList = getFileListingNoSort(s);
result.addAll(deeperList);
}
}
return result;
}
public static void copyDirectories(List<File> files, String destiny)
throws IOException
{
InputStream in = null;
OutputStream out = null;
File targetPath = new File(destiny);
System.out.println(targetPath.getPath());
for(int i = 0; i < files.size(); i++)
{
File temp = new File(files.get(i).toString());
//System.out.println(temp.getPath());
try
{
if(temp.isDirectory())
{
if(!targetPath.exists())
{
targetPath.mkdir();
}
File[] filesAndDirs = temp.listFiles();
List<File> filesDirs = Arrays.asList(filesAndDirs);
for(File file : filesDirs)
{
if (! file.isFile())
{
//must be a directory
//recursive call!
copyDirectories(filesDirs,destiny);
}
}
}
else
{
in = new FileInputStream(files.get(i).toString());
out = new FileOutputStream(targetPath);
System.out.println(temp.getPath());
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0)
{
out.write(buf, 0, len);
}
}
}
catch(Exception e)
{
System.err.println("No fue posible copiar los archivos. Motivo: " + e.getMessage() + e);
e.printStackTrace();
}
}
}
It would be very bad of me to just paste the working code here, it will not help you to think about what the problems are. I will try to give you enough without giving everything: Please mark my answer as accepted if it helps you.
1: You should not sort the file listing. The order the files are read in is important so that you don't get files before directories in your list. That said, it doesn't matter if you sort them because the shorter names, which are the directories, will appear first anyway. Still, don't do work you shouldn't be doing. Remove the getFileListing method and use only the getFileListingNoSort.
List<File> files = listing.getFileListingNoSort(fuente);
2: You need to pass both the source and the destination directories to copyDirectories so that you can make a destination filename from the source filename.
listing.copyDirectories(files, fuente, ruta);
3: You need to create a destination file out of the source filename. There may be better ways, but using simple String parsing will do the trick:
File temp = files.get(i);
String destFileName = destiny + temp.toString().substring(source.length());
File destFile = new File(destFileName);
4: You must create the new directories based on the new destFile. You are using the targetPath, which is only the base directory, not the new directory that needs to be created.
if(!destFile.exists())
{
destFile.mkdir();
}
5: After you make the destination directory, there is nothing else to do. Remove all that code after that up to the 'else'
6: Your outfile should be the new destFile you created.
out = new FileOutputStream(destFile);
7: close your input and output streams or the file copies will not be complete.
in.close();
out.close();
That should get you going. Use an IDE if you can so that you can step through the program with a debugger and see what's happening.
In your copyDirectories method calls the destiny is always the same value, even in recursive calls. You are copying all the files to the same destination file.

Why doesn't cant it copy folders and only does files

I have a method that takes source address, destination address and an ArrayList, then it goes through the giver Source folder and check each file with the ArrayList items and if they have the same name, then it copies the the destination with the exact same folder structure (so it makes folders in needed). All works till here. But it gives error if the item of the ArrayList is a folder name. Some how It can't find that folder, and comes up with errors.
Here is my code:
public class Syncer {
public static void main(String[] args) {
File source = new File("D:\\Documents\\A X");
File destination = new File("D:\\Documents\\A X Sample");
ArrayList<String> list = new ArrayList<String>();
list.add("third");
folderCrawler(source, destination, list);
}
public static void folderCrawler(File src, File dest, ArrayList<String> filesToCopy){
if(src.isDirectory()){
String[] children = src.list();
for(String file:children){
if(filesToCopy.contains(file)){
File from = new File(src, file);
File to = new File(dest, file);
dest.mkdirs();
try{
copy(from, to);
}catch(IOException e){
e.printStackTrace();
System.exit(0);
}
}
else{System.out.println("Not Found");}
}
for (int i=0; i<children.length; i++){
folderCrawler(new File(src, children[i]), new File(dest, children[i]), filesToCopy);
}
}
}
public static void copy(File src, File dest) throws IOException{
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dest);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
System.out.println("Copied: " + src.getName());
in.close();
out.close();
}
}
It does compile and goes down the list till it finds the array item same as the current source, and then stops.
Error:
java.io.FileNotFoundException: D:\Documents\A X\folder2\tohi\third (Access is denied)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at syncer.Syncer.copy(Syncer.java:61)
at syncer.Syncer.folderCrawler(Syncer.java:45)
at syncer.Syncer.folderCrawler(Syncer.java:55)
at syncer.Syncer.folderCrawler(Syncer.java:55)
at syncer.Syncer.main(Syncer.java:31)
In my other mathchine I get same error but it is (Is a directory) instead of (Access denied).
So any idea to make it work even if a folder is given. So it will copy the folder with its inner files ?
Sorry, I don' have enough rep to comment.
Have a look at apache commons FileUtils. They have a lot of copy functions so you don't have to implement them yourself.

Reading HDFS and local files in Java

I want to read file paths irrespective of whether they are HDFS or local. Currently, I pass the local paths with the prefix file:// and HDFS paths with the prefix hdfs:// and write some code as the following
Configuration configuration = new Configuration();
FileSystem fileSystem = null;
if (filePath.startsWith("hdfs://")) {
fileSystem = FileSystem.get(configuration);
} else if (filePath.startsWith("file://")) {
fileSystem = FileSystem.getLocal(configuration).getRawFileSystem();
}
From here I use the API's of the FileSystem to read the file.
Can you please let me know if there is any other better way than this?
Does this make sense,
public static void main(String[] args) throws IOException {
Configuration conf = new Configuration();
conf.addResource(new Path("/hadoop/projects/hadoop-1.0.4/conf/core-site.xml"));
conf.addResource(new Path("/hadoop/projects/hadoop-1.0.4/conf/hdfs-site.xml"));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the file path...");
String filePath = br.readLine();
Path path = new Path(filePath);
FileSystem fs = path.getFileSystem(conf);
FSDataInputStream inputStream = fs.open(path);
System.out.println(inputStream.available());
fs.close();
}
You don't have to put that check if you go this way. Get the FileSystem directly from Path and then do whatever you feel like.
You can get the FileSystem by the following way:
Configuration conf = new Configuration();
Path path = new Path(stringPath);
FileSystem fs = FileSystem.get(path.toUri(), conf);
You do not need to judge if the path starts with hdfs:// or file://. This API will do the work.
Please check the code snippet below that list files from HDFS path; namely the path string that starts with hdfs://. If you can provide Hadoop configuration and local path it will also list files from local file system; namely the path string that starts with file://.
//helper method to get the list of files from the HDFS path
public static List<String> listFilesFromHDFSPath(Configuration hadoopConfiguration, String hdfsPath,
boolean recursive)
{
//resulting list of files
List<String> filePaths = new ArrayList<String>();
FileSystem fs = null;
//try-catch-finally all possible exceptions
try
{
//get path from string and then the filesystem
Path path = new Path(hdfsPath); //throws IllegalArgumentException, all others will only throw IOException
fs = path.getFileSystem(hadoopConfiguration);
//resolve hdfsPath first to check whether the path exists => either a real directory or o real file
//resolvePath() returns fully-qualified variant of the path
path = fs.resolvePath(path);
//if recursive approach is requested
if (recursive)
{
//(heap issues with recursive approach) => using a queue
Queue<Path> fileQueue = new LinkedList<Path>();
//add the obtained path to the queue
fileQueue.add(path);
//while the fileQueue is not empty
while (!fileQueue.isEmpty())
{
//get the file path from queue
Path filePath = fileQueue.remove();
//filePath refers to a file
if (fs.isFile(filePath))
{
filePaths.add(filePath.toString());
}
else //else filePath refers to a directory
{
//list paths in the directory and add to the queue
FileStatus[] fileStatuses = fs.listStatus(filePath);
for (FileStatus fileStatus : fileStatuses)
{
fileQueue.add(fileStatus.getPath());
} // for
} // else
} // while
} // if
else //non-recursive approach => no heap overhead
{
//if the given hdfsPath is actually directory
if (fs.isDirectory(path))
{
FileStatus[] fileStatuses = fs.listStatus(path);
//loop all file statuses
for (FileStatus fileStatus : fileStatuses)
{
//if the given status is a file, then update the resulting list
if (fileStatus.isFile())
filePaths.add(fileStatus.getPath().toString());
} // for
} // if
else //it is a file then
{
//return the one and only file path to the resulting list
filePaths.add(path.toString());
} // else
} // else
} // try
catch(Exception ex) //will catch all exception including IOException and IllegalArgumentException
{
ex.printStackTrace();
//if some problem occurs return an empty array list
return new ArrayList<String>();
} //
finally
{
//close filesystem; not more operations
try
{
if(fs != null)
fs.close();
} catch (IOException e)
{
e.printStackTrace();
} // catch
} // finally
//return the resulting list; list can be empty if given path is an empty directory without files and sub-directories
return filePaths;
} // listFilesFromHDFSPath
If you really want to work with java.io.File API then the following method will help you list files only from local file system; namely path string that starts with file://.
//helper method to list files from the local path in the local file system
public static List<String> listFilesFromLocalPath(String localPathString, boolean recursive)
{
//resulting list of files
List<String> localFilePaths = new ArrayList<String>();
//get the Java file instance from local path string
File localPath = new File(localPathString);
//this case is possible if the given localPathString does not exit => which means neither file nor a directory
if(!localPath.exists())
{
System.err.println("\n" + localPathString + " is neither a file nor a directory; please provide correct local path");
//return with empty list
return new ArrayList<String>();
} // if
//at this point localPath does exist in the file system => either as a directory or a file
//if recursive approach is requested
if (recursive)
{
//recursive approach => using a queue
Queue<File> fileQueue = new LinkedList<File>();
//add the file in obtained path to the queue
fileQueue.add(localPath);
//while the fileQueue is not empty
while (!fileQueue.isEmpty())
{
//get the file from queue
File file = fileQueue.remove();
//file instance refers to a file
if (file.isFile())
{
//update the list with file absolute path
localFilePaths.add(file.getAbsolutePath());
} // if
else //else file instance refers to a directory
{
//list files in the directory and add to the queue
File[] listedFiles = file.listFiles();
for (File listedFile : listedFiles)
{
fileQueue.add(listedFile);
} // for
} // else
} // while
} // if
else //non-recursive approach
{
//if the given localPathString is actually a directory
if (localPath.isDirectory())
{
File[] listedFiles = localPath.listFiles();
//loop all listed files
for (File listedFile : listedFiles)
{
//if the given listedFile is actually a file, then update the resulting list
if (listedFile.isFile())
localFilePaths.add(listedFile.getAbsolutePath());
} // for
} // if
else //it is a file then
{
//return the one and only file absolute path to the resulting list
localFilePaths.add(localPath.getAbsolutePath());
} // else
} // else
//return the resulting list; list can be empty if given path is an empty directory without files and sub-directories
return localFilePaths;
} // listFilesFromLocalPath
This work.
package com.leerhdfs;
//import org.apache.commons.io.IOUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.util.Progressable;
import java.io.*;
import java.net.URI;
import java.nio.charset.StandardCharsets;
public class ReadWriteHDFSExample {
public static void main(String[] args) throws IOException {
Path inFile = new Path(args[0]);
String destinosrc = args[1];
//InputStream in = new BufferedInputStream(new FileInputStream(localsrc));
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(destinosrc), conf);
FSDataInputStream in = fs.open(inFile);
//Progressable ir viendo aumento 10%, 20%, 30%
OutputStream out = fs.create(new Path(destinosrc), new Progressable() {
public void progress() {
System.out.println("Leyendo y escribiendo...");
}
});
IOUtils.copyBytes(in ,out, 4096, true);
in.close();
}
}

How to zip only .txt file in a folder using java?

here i'm trying to zip only .txt file in a folder using java.
My code here was found with google and works perfectly but only for a specified .txt file.
Thank you.
import java.util.*;
import java.util.zip.*;
import java.io.*;
public class ZipFile
{
public static void main(String[] args) {
ZipOutputStream out = null;
InputStream in = null;
try {
File inputFile1 = new File("c:\\Target\\target.txt");// here i want to say only the directroy where .txt files are stored
File outputFile = new File("c:\\Target\\Archive_target.zip");//here i want to put zipped file in a different directory
OutputStream rawOut = new BufferedOutputStream(new FileOutputStream(outputFile));
out = new ZipOutputStream(rawOut);
InputStream rawIn = new FileInputStream(inputFile1);
in = new BufferedInputStream(rawIn);
ZipEntry entry = new ZipEntry("c:\\Target\\target.txt");
out.putNextEntry(entry);
byte[] buf = new byte[2048];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
}
catch(IOException e) {
e.printStackTrace();
}
finally {
try {
if(in != null) {
in.close();
}
if(out != null) {
out.close();
}
}
catch(IOException ignored)
{ }
}
}
}
You need to use File.list(...) to get a list of all the text files in the folder. Then you create a loop to write each file to the zip file.
I just add these lines just after
"File outputFile = new File("c:\Target\Archive_target.zip");
from my previous code.
code added:
File Dir = new File("c:/Target");
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return !name.startsWith(".txt");
}
};
String[] children = Dir.list(filter);
You can get a list of all text files in your directory by using the following method of the File class:
String[] list(FilenameFilter filter)
Create a File object that points to your DIRECTORY (I know it sounds illogical, but that's the way it is- you can test if it is a directory using isDirectory()) and then use the FilenameFilter to say, for example, accept this file if its name contain ".txt"
Create a FilenameFilter that accepts only *.txt file , and then just use
list = File.list(yourNameFilter);
and then just add all the files in the list to the zip file

Categories