My goal is to write a Java program in Netbeans to copy a directory and all of its contents, including subdirectories and their contents. To do so, I first ask the user for source directory and destination where it will be copied. From here, my program should make a new directory in the new location with same name as the source directory. Then my program should create an array with File class objects for each item in the contents of the source directory. Next, I tried to iterate the array, and for each item - if it is a file, it should copy to the new directory- if it is a directory, it should recursively call this method to the copy the directory and all of its contents.
An extremely useful program if I could just get it to work correctly. It is difficult for me right now to understand the entire logic needed to make this program run efficiently.
When I run the program, it returns that the file cannot be found but this is just not true. So my code has to be wrong somewhere. Any help would be greatly appreciated guys.
Thank you.
package copydirectories;
/**
* CSCI 112, Ch. 18 Ex. 5
* #author zhughes3
* Last edited Tuesday, March 11th, 2014 # 9pm
*/
import java.io.*;
import java.util.Scanner;
public class CopyDirectories {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws Exception {
//Create a new instance of scanner to get user input
Scanner scanner = new Scanner (System.in);
//Ask user to input the directory to be copied
System.out.print("Input directory to be copied.");
//Save input as String
String dirName = scanner.nextLine();
//Ask user to input destination where direction will be copied
System.out.print("Input destination directory will be moved to.");
//Save input as String
String destName = scanner.nextLine();
//Run method to determine if it is a directory or file
isDirFile(dirName, destName);
}//end main
public static void isDirFile (String source, String dest) throws Exception{
//Create a File object for new directory in new location with same name
//as source directory
File dirFile = new File (dest + source);
//Make the new directory
dirFile.mkdir();
//Create an array of File class objects for each item in the source
//directory
File[] entries;
//If source directory exists
if (dirFile.exists()){
//If the source directory is a directory
if (dirFile.isDirectory()){
//Get the data and load the array
entries = dirFile.listFiles();
//Iterate the array using alternate for statement
for (File entry : entries){
if (entry.isFile()){
copyFile (entry.getAbsolutePath(), dest);
} //end if
else {
isDirFile (entry.getAbsolutePath(), dest);
} //end else if
}//end for
}//end if
}//end if
else {
System.out.println("File does not exist.");
} //end else
}
public static void copyFile (String source, String dest) throws Exception {
//declare Files
File sourceFile = null;
File destFile = null;
//declare stream variables
FileInputStream sourceStream = null;
FileOutputStream destStream = null;
//declare buffering variables
BufferedInputStream bufferedSource = null;
BufferedOutputStream bufferedDest = null;
try {
//Create File objects for source and destination files
sourceFile = new File (source);
destFile = new File (dest);
//Create file streams for the source and destination
sourceStream = new FileInputStream(sourceFile);
destStream = new FileOutputStream(destFile);
//Buffer the file streams with a buffer size of 8k
bufferedSource = new BufferedInputStream(sourceStream,8182);
bufferedDest = new BufferedOutputStream(destStream,8182);
//Use an integer to transfer data between files
int transfer;
//Alert user as to what is happening
System.out.println("Beginning file copy:");
System.out.println("\tCopying " + source);
System.out.println("\tTo " + dest);
//Read a byte while checking for End of File (EOF)
while ((transfer = bufferedSource.read()) !=-1){
//Write a byte
bufferedDest.write(transfer);
}//end while
}//end try
catch (IOException e){
e.printStackTrace();
System.out.println("An unexpected I/O error occurred.");
}//end catch
finally {
//close file streams
if (bufferedSource !=null)
bufferedSource.close();
if (bufferedDest !=null)
bufferedDest.close();
System.out.println("Your files have been copied correctly and "
+ "closed.");
}//end finally
}//end copyDir
}//end class
If you read through JavaDocs, you will see that mkdir...
Creates the directory named by this abstract pathname.
This is a little obscure, but basically, it will only create the last level of the directory. For example, if you have a path of C:\this\is\a\long\path, mkdir would only attempt to create the path directory at the end of C:\this\is\a\long, but if C:\this\is\a\long doesn't exist it will fail.
Instead, if you use mkdirs
Creates the directory named by this abstract pathname, including any
necessary but nonexistent parent directories. Note that if this
operation fails it may have succeeded in creating some of the
necessary parent directories.
I'd also be check the results of these methods, as they will indicate if the operation was successful or not
I think entries = dirFile.listFiles(); looks wrong, you should be listing the files from the source directory, not the destination...
Related
I am currently working on transferring a file from a server to a client via tcp connection. The file exists somewhere within a sharedroot directory of the server. This is the sample code of my upload method for server upload to client.
public void upload(String filename, DataOutputStream out) throws IOException {
File fname = null;
if (filename.contains(sharedroot)) { //this is if the client provides a proper filepath with the filename
fname = new File(filename);
}else { //if client only provides a filename without path
fname = new File(filename);
//"..\\..\\"+ //i was working around with this, but somehow just making the file whether or not it contains the sharedroot seems to give me the "best" output so far...
}
System.out.println(fname.getCanonicalPath());
if (fname.isDirectory()) {
System.out.println("File is a directory");
String quit = "404 not found";
sendOut(quit, out);
return;
}
String path = fname.getAbsolutePath();
System.out.println(path);
if (fname.isFile()) {
String canonpath = fname.getCanonicalPath();
if (canonpath.contains(sharedroot)) {
try {
FileInputStream in = new FileInputStream(fname);
byte[] buffer = new byte[1024];
out.writeInt(fname.getName().length());
out.write(fname.getName().getBytes(), 0, fname.getName().length()); // writes file name only, not
// including the path
long size = fname.length();
out.writeLong(size);
while (size > 0) {
int len = in.read(buffer, 0, buffer.length);
out.write(buffer, 0, len);
size -= len;
}
} catch (Exception e) {
System.out.println("Error occurred in uploading file to client. Please try again");
}
}else {
System.out.println("File not in shared directory");
String quit = "404 not found";
sendOut(quit, out);
}
}else {
System.out.println("File not exists");
String quit = "404 not found";
sendOut(quit, out);
}
}
The output given by getCanonicalPath() and getAbsolutePath() as seen below is wrong because it is checking inside the directory of my eclipse and not the sharedroot directory. How can I get the filepath of the file so that i can compare it to my sharedroot and ensure it exists within the sharedroot? The sharedroot would be for example: D:\seant\2uniFiles\1. FINE2005 Year 3
D:\seant\eclipse-workspace\DCN3005\Lecture 1 Exercise.pdf
D:\seant\eclipse-workspace\DCN3005\Lecture 1 Exercise.pdf
File not exists
Your creation of File does not specify a dedicated directory. There are two constructors requiring a (root) directory and a file name – one as File itself, the other as String. I assume one of your paths is relative but your else-branch creates the file the same way as the full qualified path. You should pass the sharedRoot instead as first parameter and the fileName as second.
File fname = null;
// sharedRoot is more like a constant and startsWith
// avoids reading somewhere else that looks similar
if (filename.startsWith(sharedRoot)) {
fname = new File(filename);
} else {
fname = new File(sharedRoot, filename);
}
In all other cases relative paths are relative to the root directory of the VM process – and I mean process. If for example a user starts this in the user's HOME directory it'll be relative to this. If an operating system task starts the VM it'll be relative to the OS process' root – which might be a Unix cron job or a Windows scheduling thing.
Maybe you introduce a sort of configuration of sharedRoot so you don't need to recompile if this changes in the future.
I am creating an application that automatically sorts and organizes files into a database. I have written my code to read files within the imported folder one at a time, and process them into the DB. However, I am having trouble looping this process, so that I can process files that are nested in any amount of folders within the original folder that the user wants to input.
I simply need to instruct my program to go back to a specific part of my code and start running from there again.
Another possible way to solve this issue would be to create a way to list out all of the individual files within folder (including all the files within subfolders), and I could easily fit that into my program too.
I tried using labeled continue, return, and break keywords based off of an answer I got online, but I never expected those to succeed in looping my code back to a specific spot.
JFileChooser chooser = new JFileChooser();
chooser.setSelectedFiles(null);
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
chooser.showOpenDialog(null);
//Getting file paths from within folder
File f = chooser.getSelectedFile();
String file = f.getAbsolutePath();
if (f.isDirectory()) {
//Need to loop back to here
File folder = new File(file);
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isDirectory()) {
//Code here is run if there is a folder within a folder. I tested it too
//I want the code here to loop back above where it says "Need to loop back to here"
}
if (listOfFiles[i].isFile()) { //Once I list the files from within the folder, their information gets assigned variable here, and the rest of my program sorts it and saves it to DB accordingly.
//Everything below here is not important, but it might be helpful to see what happens each file with the folders.
System.out.println(listOfFiles[i]);
String filename = (listOfFiles[i].getName()); //For Files
Long filemodified = (listOfFiles[i].lastModified());
String filepath = (listOfFiles[i].getAbsolutePath());
Long filesizeraw = (listOfFiles[i].length());
long filehashcode = (listOfFiles[i].hashCode());
String fileparent = (listOfFiles[i].getParent());
Currently, there is no error message. It would process any individual files directly in the imported file (not nested in any folder within the folder), but wouldn't get to any of the files that are in folders within folders.
Another possible way to solve this issue would be to create a way to list out all of the individual files within folder (including all the files within subfolders), and I could easily fit that into my program too
Although this doesn't do the SQLite inserts, the following class extracts a list (of File objects) the files (thus file name and path are available via the File object).
public class FTS {
private ArrayList<File> mFileList; //Resultant list of Files extracted
private String mBaseDirectory; // The Directory to search
private long mSubDirectoryCount; // The count of the subdirectories
//Constructor
public FTS(String directory) {
this.mBaseDirectory = directory;
this.mSubDirectoryCount = 0;
buildFileListing(this.mBaseDirectory);
}
//
private void buildFileListing(String directory) {
// Initialise the ArrayList for the result
if (mFileList == null) {
mFileList = new ArrayList(){};
}
//Get the File (directory to process)
File dir = new File(directory);
// Get the List of the Directories contents
String[] filelist = dir.list();
// If empty (null) then return
if (filelist == null) {
return;
}
// Loop through the directory list
for (String s: filelist) {
//get the current list item as a file
File f = new File(dir.getAbsolutePath() + File.separator + s);
// is it a file or directory?
if (f.isFile() && !f.isDirectory()) {
this.mFileList.add(f); // If a file then add the file to the extracted list
} else {
// If a directory then increment the count of the subdirectories processed
mSubDirectoryCount++;
// and then recursively call this method to process the directory
buildFileListing(f.getAbsolutePath());
}
}
}
// return the list of extracted files
public ArrayList<File> getFileList() {
return this.mFileList;
}
// return the number of sub-directories processed
public long getSubDirectoryCount() {
return this.mSubDirectoryCount;
}
}
An example usage of the above is :-
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
FTS fileTreeSearch;
String BaseDirectory = "E:" + File.separator;
List<File> files = (fileTreeSearch = new FTS(BaseDirectory)).getFileList();
System.out.println("Extracted " + String.valueOf(files.size()) + " files, from " + String.valueOf(fileTreeSearch.getSubDirectoryCount()) + " sub-directories of " + BaseDirectory);
/* this commented out code would process all the extracted files
for (File f: files) {
System.out.println("File is " + f.getName() + "\t\t path " + f.getAbsolutePath());
}
*/
}
}
Example output from running the above :-
Extracted 186893 files, from 54006 sub-directories of E:\
I'm trying to create a new text file in java by having the user input their desired file name. However, when I look in the directory for the file after I run the code once, it doesn't show up.
import java.util.Scanner;
import java.io.File;
public class TestFile {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter the desired name of your file: ");
String fileName = input.nextLine();
fileName = fileName + ".txt";
File file = new File(fileName);
}
}
Although, when I don't have the user input a file name and just have the code written with the name in quotation marks, the file ends up being created when I look back in the directory.
File file = new File("TestFile.txt")
Why won't it create a file when I try to use the String input from the user?
You must be mistaken because just calling new File(String) won't create a file. It will just create an instance of File class.
You need to call file.createNewFile().
Adding this at the end creates the file:-
if (file.createNewFile()) {
System.out.println("File created.");
} else {
System.out.println("File already exists.");
}
The following code worked for me:
Scanner input = new Scanner(System.in);
System.out.print("Enter the desired name of your file: ");
String fileName = input.nextLine();
fileName = fileName + ".txt";
File file = new File(fileName);
boolean isFileCreated = file.createNewFile(); // New change
System.out.print("Was the file created? -- ");
System.out.println(isFileCreated);
The only change made to your code is to call createNewFile method. This worked fine in all cases. Hope this helps.
From the API:
Atomically creates a new, empty file named by this abstract pathname
if and only if a file with this name does not yet exist. The check for
the existence of the file and the creation of the file if it does not
exist are a single operation that is atomic with respect to all other
filesystem activities that might affect the file. Note: this method
should not be used for file-locking, as the resulting protocol cannot
be made to work reliably. The FileLock facility should be used
instead.
Please use below code to solve your issue. You just have to call createNewFile() method it will create file in your project location. You can also provide the location where you want to create file otherwise it will create file at your project location to create file at specified location you have to provide location of your system like below
String fileLocation="fileLocation"+fileName;
File file = new File(fileLocation);
import java.util.Scanner;
import java.io.File;
public class TestFile {
public static void main(String[] args) throws IOException {
Scanner input = new Scanner(System.in);
System.out.print("Enter the desired name of your file: ");
String fileName = input.nextLine();
fileName = fileName + ".txt";
File file = new File(fileName);
file.createNewFile();
}
}
When faced with issues like this, it's really, really, really important to go hit the JavaDocs, because 90% of the time, it's just a misunderstanding of how the APIs work.
File is described as:
An abstract representation of file and directory pathnames.
This means that creating an instance of File does not create a file nor does the file have to exist, it's just away of describing a virtual concept of a file.
Further reading of the docs would have lead you to File#createNewFile which is described as doing:
Atomically creates a new, empty file named by this abstract pathname if and only if a file with this name does not yet exist. The check for the existence of the file and the creation of the file if it does not exist are a single operation that is atomic with respect to all other filesystem activities that might affect the file.
When you initialize your File file = new File("TestFile.txt"), it is not created yet.
You should write something to your file using FileWriter or others.
File f = new File(fileName);
FileWriter w = new FileWriter(f);
w.write("aaa");
w.flush();
or using f.createNewFile() as suggested in other answer.
Then you can see your file and its content.
When I enter the full file path (C:\Users\djustinwebb\Documents\BlueJ Projects\LightHouse) for "search" and it attempts to open the file I get the error:
java.io.FileNotFoundException: C:\Users\djustinwebb\Documents\BlueJ Projects\LightHouse (Access is denied) (in java.io.FileInputStream)
I have input "invoicedata.txt" for search and it worked even though it doesn't read through the file properly but I would like to know why it won't work when I use the full file path. What do I need to do to use the full file path without running into this error?
public String searchCase()throws FileNotFoundException
{
String fileLine = null;
StringTokenizer stok = null;
Scanner inputFile = new Scanner(new File(search));
String whatever = null;
while(inputFile.hasNextLine())
{
fileLine = inputFile.nextLine();
stok = new StringTokenizer(fileLine,",");
caseLCount++;
while(stok.hasMoreTokens())
{
if(userWord.equals(stok.nextToken()))
{
caseWCount++;
whatever += caseLCount + ".\n";
}//end if
}// end nested while
}//end outer while
inputFile.close();
return whatever;
}// end searchCase()
This happens because you are trying to open and read a directory, which is LightHouse here. You are supposed to enter the file name in the file path as well, like this, ..\LightHouse\invoicedata.txt.
If you want to distinguish between files and folders, use the isFile() and isDirectory() methods. You can get the contents of folders using the list() and listFiles() methods.
I am trying to read 2 files after i read the files i want to get their contents and manipulate the contents of the two files then update a new file which is the output. The files are in the same folder as the program but the program always throws a FileNotFoundException.
Below is my code:-
import java.io.*;
import java.util.Scanner;
public class UpdateMaster {
public static void main(String[] args)
{
String master = "Customer.dat";
String trans = "Transactns.dat";
String newMaster = "Temp.txt";
Scanner inputStreamMaster = null;
Scanner inputStreamTrans = null;
PrintWriter inputStreamNewMaster = null;
try
{
inputStreamMaster = new Scanner(new File(master));
inputStreamTrans = new Scanner(new File(trans));
inputStreamNewMaster = new PrintWriter(newMaster);
}
catch(FileNotFoundException e)
{
System.out.println("Error: you opend a file that does not exist.");
System.exit(0);
}
catch(IOException e)
{
System.out.println("Error.");
System.exit(0);
}
do
{
String transLine = inputStreamTrans.nextLine();
String masterLine = inputStreamMaster.nextLine();
String[] transLineArr = transLine.split(",");
String[] masterLineArr = masterLine.split(",");
int trAccNo = Integer.parseInt(transLineArr[0]);
int sales = Integer.parseInt(transLineArr[1]);
int masterAccNo = Integer.parseInt(masterLineArr[0]);
int balance = Integer.parseInt(masterLineArr[1]);
while(masterAccNo== trAccNo){
inputStreamNewMaster.println(trAccNo+ " , "+masterAccNo);
masterLine = inputStreamMaster.nextLine();
masterLineArr = masterLine.split(",");
masterAccNo = Integer.parseInt(masterLineArr[0]);
balance = Integer.parseInt(masterLineArr[1]);
}
balance = balance + sales;
inputStreamNewMaster.println(masterAccNo+ " , "+balance);
}while(inputStreamTrans.hasNextLine());
inputStreamMaster.close();
inputStreamTrans.close();
inputStreamNewMaster.close();
//System.out.println(" the line were written to "+ newMaster);
}
}
Like #Ankit Rustagi said in the comments, you need the full path of the files if you want to keep the current implementation.
However, there is a solution where you only need the file names: use BufferedReader / BufferedWriter. See here an example on how to use these classes (in the example it uses the full path but it works without it too).
Use absolute path
String master = "C:/Data/Customer.dat";
String trans = "C:/Data/Transactns.dat";
String newMaster = "C:/Data/Temp.txt";
The code works for me, i guess you misspelled some filename(s) or your files are in the wrong folder. I created your files on the same level as the src or the project. Also this is the folder where the files are exspected.
There's nothing wrong with using relative paths like tihis. What's happening is that your program is looking for the files in the directory where you execute the program, which doesn't have to be the folder of the program. You can confirm this by logging the absolute path of the files before you try to read them. For example:
File masterFile = new File(master);
System.out.printf("Using master file '%s'%n", masterFile.getAbsolutePath());
inputStreamMaster = new Scanner(masterFile);
In general you should not hardcode file paths but allow the user to specify them in someway, for example using command line arguments, a configuration file with a well known path, or an interactive user interface.
There is a way to locate the program's class file but it's a little tricky because Java allows classes to be loaded from compressed archives that may be located in remote systems. It's better to solve this problem in some other manner.
Try this:
String current = new java.io.File( "." ).getCanonicalPath();
System.out.println("I look for files in:"+current);
To see what directory your program expects to find its input files. If it shows the correct directory, check spelling of filenames. Otherwise, you have a clue as to what's gone wrong.