I have a program that is supposed to rename all files within an entire folder (with sub-folders) to a temporary file name, copy those to a different directory, then change the temp filename back to the original filename. During this process I would like to keep all folder names the same. When I run the code below, all it does is change the name of the top-level folders in the path that i specify:
package shortenFilenames;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class shortenFilenameClass
{
public static void main(String[] args) throws IOException
{
String absolutePathLocal = "C:\\Users\\talain\\Desktop\\marketingOriginal"; //original files
String absolutePathOnedrive= "C:\\Users\\talain\\Desktop\\fakeOnedrive"; //path to onedrive
File local = new File(absolutePathLocal);
File onedrive = new File(absolutePathOnedrive);
File[] filesInDir = local.listFiles();
for(int i = 0; i < filesInDir.length; i++)
{
String name = filesInDir[i].getName();
System.out.println(name);
String newName = String.valueOf(i);
File oldPath = new File(absolutePathLocal + "\\" + newName);
System.out.println("oldPath: " + oldPath);
filesInDir[i].renameTo(new File(oldPath.toString()));
File newPath = new File(absolutePathOnedrive + "\\" + newName);
copyFileUsingJava7Files(oldPath, newPath);
newPath.renameTo(new File(newPath.toString()));
System.out.println("renamed: " + name + "to: " + newName + ", copied to one drive, and changed back to original name");
}
}
private static void copyFileUsingJava7Files(File source, File dest) throws IOException {
Files.copy(source.toPath(), dest.toPath());
}
}
I just did the following and it copied whatever files were in the first path into the second path. If it fails for you, show me the error output.
for(int i = 0; i < filesInDir.length; i++)
{
String name = filesInDir[i].getName();
System.out.println(name);
Files.copy(new File(absolutePathLocal + "\\" + name).toPath(),new File(absolutePathOnedrive + "\\" + name).toPath());
}
Your code also assumes that those directories already exist on your system otherwise you will run into a FileNotFound exception.
Related
How should I effectively check for the availability of particular folder(myfolder) recursively and if available, then create a tmp directory parallel to it
Example:
#ls -l
--parent folder
--projects
-- sub folders (further depth is possible)
-- myfolder
-- tmp
I'm from python background and yet to get used to java. Below is what I could come up with.
import java.io.File;
class Main
{
public static void main(String[] args)
{
String currentDir = System.getProperty("user.dir");
String projectDir = currentDir + "/projects"; // under this I have to search the for the `myfolder` recursively.
File file = new File(projectDir);
if (file.isDirectory()) {
new File("tmp").mkdirs();
}
else {
System.out.println("Directory doesn't exist!!");
}
}
note: I use java 8
Below is a method that recursively searches through all the sub-directories that might be contained within the provided local directory path for a specific directory (folder) name. When the first instance of that directory name is found the search halts and the full path to that directory is returned.
From that point, the returned path string should be parsed to get the parent path. Something like that could be done something like this:
String foundFolderParentPath = foundDirectory.substring(0,
foundDirectory.lastIndexOf(File.separator));
Now you would want to check and see if the tmp directory already exists there. Maybe you don't need to create it or, you may want to carry out some other action based on that fact:
if (new File(foundFolderParentPath + File.separator + "tmp").exists()) {
// tmp already exists...Do whatever...
}
else {
// Otherwise Create the tmp directory...
new File(foundFolderParentPath + File.separator + "tmp").mkdir();
}
Here is the recursive findDirectory() method:
/**
* This method recursively searches through all sub-directories beginning
* from the supplied searchStartPath until the supplied folder to find is
* found.<br>
*
* #param searchStartPath (String) The full path to start the search from.<br>
*
* #param folderToSearchFor (String) The directory (folder) or sub-directory
* (sub-folder) name to search for. Just a single name should be supplied, not multiple directory names..<br>
*
* #return (String) If the search is successful then the full path to that
* found folder is returned. If the search was unsuccessful then Null String
* (""), an empty string is returned.
*/
public static String findDirectory(String searchStartPath, String folderToSearchFor) {
String foundPath = "";
File[] folders = new File(searchStartPath).listFiles(File::isDirectory);
if (folders.length == 0) {
return "";
}
String tmp;
for (int i = 0; i < folders.length; i++) {
String currentPath = folders[i].getAbsolutePath();
if (currentPath.equals(folderToSearchFor) ||
currentPath.substring(currentPath.lastIndexOf(File.separator) + 1)
.equals(folderToSearchFor)) {
foundPath = currentPath;
break;
}
tmp = "";
// The recursive call...
tmp = findDirectory(folders[i].getAbsolutePath(), folderToSearchFor);
if (!tmp.isEmpty()) {
// Directory is found...
foundPath = tmp;
break; // Get out of loop. It's No longer needed.
}
}
return foundPath;
}
How you might use this method:
String currentDir = System.getProperty("user.dir");
String projectDir = currentDir + "/Projects"; // under this I have to search the for the `myfolder` recursively.
String searchForDirectory = "mySpecialFolder";
String foundDirectory = findDirectory(currentDir, searchForDirectory);
if (foundDirectory.isEmpty()) {
System.out.println("The folder to find (" + searchForDirectory
+ ") could not be found!");
}
else {
System.out.println("The ' " + searchForDirectory +
"' Folder is found at: --> " + foundDirectory);
/* Create the 'tmp' folder within the same parent folder where
mySpecialFolder resides in. */
String foundFolderParentPath = foundDirectory.substring(0,
foundDirectory.lastIndexOf(File.separator));
// Is there a 'tmp' folder already there?
if (new File(foundFolderParentPath + File.separator + "tmp").exists()) {
// Yes there is..
System.out.println("\nThere is no need to create the 'tmp' folder! It already"
+ "exists within the\nparent path of: --> " + foundFolderParentPath);
}
else {
// No here isn't so create it...
new File(foundFolderParentPath + File.separator + "tmp").mkdir();
System.out.println("The 'tmp' folder was created within the parent path indicated below:");
System.out.println(foundFolderParentPath);
System.out.println();
}
// Display a File-Chooser to prove it just for the heck of it.
javax.swing.JFileChooser fc = new javax.swing.JFileChooser(foundFolderParentPath);
fc.showDialog(null, "Just A Test");
}
I have the following code below, which is used to list all the files within specific folders/directories.
For mac this works perfectly, but when it comes to windows I get a java.lang.NullPointerException. I am not completely sure how I would fix it, I am aware that it means one of the directory File variables are passed as Null when being put into the function. But I am not sure how to check whether the directory is null and why exactly it creates an error on only that particular directory as it works on all the other directories and the directory it doesn't work on is just the regular documents directory on Windows. I have made a small comment on the three lines where the java.lang.NullPointerException error is showing.
I have also tried to fix it by surrounding the file list function to check whether the folder is null or not. But that doesn't work as it is already to late, the null error is already happening at the File variable declaration.
public static void main() throws IOException {
if (isMac()) {
listFilesForFolderMac(folderMac1);
listFilesForFolderMac(folderMac2);
listFilesForFolderMac(folderMac3);
listFilesForFolderMac(folderMac4);
listFilesForFolderMac(folderMac5);
listFilesForFolderMac(folderMac6);
listFilesForFolderMac(folderMac7);
} else if (isWindows()) {
listFilesForFolderWin(folderWin1);
listFilesForFolderWin(folderWin2);
listFilesForFolderWin(folderWin3);
listFilesForFolderWin(folderWin4);
listFilesForFolderWin(folderWin5);
listFilesForFolderWin(folderWin6);
}
}
public static boolean isWindows() {
return (OS.indexOf("win") >= 0);
}
public static boolean isMac() {
return (OS.indexOf("mac") >= 0);
}
public static void listFilesForFolderMac(final File folder) throws IOException {
PrintWriter writToDoc = new PrintWriter(new FileWriter("/Users/" + username + "/Documents/files.txt",true));
for (final File fileEntry : folder.listFiles()) {
if (fileEntry.isDirectory()) {
listFilesForFolderMac(fileEntry);
} else {
writToDoc.println(fileEntry.getName());
}
}
writToDoc.close();
}
public static void listFilesForFolderWin(final File folder) throws IOException {
PrintWriter writToDoc = new PrintWriter(new FileWriter("c:\\users\\" + username + "\\Documents\\files.txt",true));
for (final File fileEntry : folder.listFiles()) { //Error here
if (fileEntry.isDirectory()) {
listFilesForFolderWin(fileEntry); //Error here
} else {
writToDoc.println(fileEntry.getName());
}
}
writToDoc.close();
}
final static File folderMac1 = new File("/Users/" + username + "/Pictures");
final static File folderMac2 = new File("/Users/" + username + "/Documents");
final static File folderMac3 = new File("/Users/" + username + "/Movies");
final static File folderMac4 = new File("/Users/" + username + "/Music");
final static File folderMac5 = new File("/Users/" + username + "/Downloads");
final static File folderMac6 = new File("/Users/" + username + "/Applications");
final static File folderMac7 = new File("/Users/" + username + "/Desktop");
final static File folderWin1 = new File("C:\\Users\\" + username + "\\Desktop");
final static File folderWin2 = new File("C:\\Users\\" + username + "\\Downloads");
final static File folderWin3 = new File("C:\\Users\\" + username + "\\Documents"); //Error here
final static File folderWin4 = new File("C:\\Users\\" + username + "\\Pictures");
final static File folderWin5 = new File("C:\\Users\\" + username + "\\Music");
final static File folderWin6 = new File("C:\\Users\\" + username + "\\Videos");
I get the following error stated below.
Exception in thread "main" java.lang.NullPointerException
at script.MyClass.listFilesForFolderWin(MyClass.java:200)
at script.MyClass.listFilesForFolderWin(MyClass.java:202)
at script.MyClass.main(MyClass.java:155)
There are some folders in Windows that Java can see but not see into, and some files that it sees as directories. To solve your problem, simply check before you try to list the files:
if (fileEntry.isDirectory()&&fileEntry.listFiles()!=null) {
listFilesForFolderWin(fileEntry);
}
I have messed around with the file commands that Java has, and usually when you get a NullPointerExcpetion, it means that the directory you have given it is wrong. I have not run your code on windows, but for that platform, all you need to do is follow the same file structure that you did with your Mac paths. Here is what your first variable should be:
final static File folderWin1 = new File("C:/Users/" + username + "/Pictures");
All of the rest of your variables should follow the same structure. I hope this fixes your problem.
java.util.File can not process Window's "junction"s (a type of symbolic link), such as "My Documents" and "Pictures"
You will need to switch over to the NIO2 API and make use of the Paths API.
See Walking the File Tree which actually has an example for processing symbolic links
Extract from above link
#Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attr) {
if (attr.isSymbolicLink()) {
System.out.format("Symbolic link: %s ", file);
} else if (attr.isRegularFile()) {
System.out.format("Regular file: %s ", file);
} else {
System.out.format("Other: %s ", file);
}
System.out.println("(" + attr.size() + "bytes)");
return CONTINUE;
}
You may also want to have a look at Links, Symbolic or Otherwise for more details
I'm writing a short application that opens a .jar file, runs a few transforms on its contents, then wraps it up as a .jar file again. I'm using the approach from How to use JarOutputStream to create a JAR file? to create the new jar file and it's working with the exception that it's creating a file hierarchy in new jar file that stretches all the way back to my computer's root.
It's perfectly logical that this is happening since I'm passing the process the target directory as a path from the computer root. What I can't find is any other way of communicating the context that process needs to be able to find my target folder. How do I set the context from which I want the .jar file to be created?
To clarify:
I've rewritten the Run method of the solution linked above to accept two parameters: a string defining the name and location of the output jar file and a string defining the location of the folder I want compressed, like so:
public void run(String output, String inputDirectory) throws IOException
{
JarOutputStream target = new JarOutputStream(new FileOutputStream(output));
add(new File(inputDirectory), target, inputDirectory.length());
target.close();
}
Two sample values that I hand off to the method would be: C:/temp/964ca469-5f7b-4c56-8b5a-72b4c1c851e0/help.jar and C:/temp/964ca469-5f7b-4c56-8b5a-72b4c1c851e0/out/
I want the structure of my .jar file to have its root at the forward slash following "out", but instead the .jar file's hierarchy is:
C:
|-Temp
|-964ca469-5f7b-4c56-8b5a-72b4c1c851e0
|-out
|-{content}
I've tried passing the length of the string preceding the actual content to the Add method and paring it off before adding the JarEntry, but that just gets me an out of index error, which makes perfect sense because I'm just frikkin' groping.
There must be a way of setting the JarEntry class to a specific point in a folder hierarchy before adding a file, or some other means of doing the same thing, but I canna find it so far.
Thanks.
There is no 'root context' in a JAR file. What the files and paths are is completely dependent on what name(s) you put into the JarEntries.
Never figured out how to do it with Jar file creation, but as fge suggested the zip filesystem provider was indeed easier to work with. I used this in my main method:
CreateJarPackage zipper = new CreateJarPackage();
System.out.println(baseline + unique_directory + "/" + out_jar_file);
System.out.println(baseline + unique_directory + "/out/");
System.out.println(baseline.length() + unique_directory.length() + 5);
try {
zipper.addZipFiles(baseline + unique_directory + "/" + out_jar_file, baseline + unique_directory + "/out/", baseline.length() + unique_directory.length() + 5);
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
File folder = new File(baseline + unique_directory + "/out/");
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isDirectory()) {
try {
zipper.addZipFiles(baseline + unique_directory + "/" + out_jar_file, listOfFiles[i].toString(), baseline.length() + unique_directory.length() + 5);
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
To call this:
import java.io.File;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.Map;
public class FinalZipCreator {
public static void processList(URI uri, Map<String, String> env, String path)
throws Throwable {
try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
File folder = new File(path);
File[] listOfFiles = folder.listFiles();
int index = path.length();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
Path externalTxtFile =Paths.get(listOfFiles[i].toString());
Path pathInZipfile = zipfs.getPath(listOfFiles[i]
.toString().substring(index));
// copy a file into the zip file
Files.copy(externalTxtFile, pathInZipfile,
StandardCopyOption.REPLACE_EXISTING);
} else if (listOfFiles[i].isDirectory()) {
Path externalTxtFile = Paths.get(listOfFiles[i].toString());
Path pathInZipfile = zipfs.getPath(listOfFiles[i]
.toString().substring(index));
// copy a file into the zip file
Files.copy(externalTxtFile, pathInZipfile,
StandardCopyOption.REPLACE_EXISTING);
File folder2 = new File(listOfFiles[i].toString());
File[] listOfFiles2 = folder2.listFiles();
int index2 = listOfFiles[i].toString().length();
for (int e = 0; e < listOfFiles2.length; e++) {
if (listOfFiles2[i].isFile()) {
Path externalTxtFile2 = Paths.get(listOfFiles2[e].toString());
Path pathInZipfile2 = zipfs.getPath(listOfFiles2[e]
.toString().substring(index2));
// copy a file into the zip file
Files.copy(externalTxtFile2, pathInZipfile2,
StandardCopyOption.REPLACE_EXISTING);
}
}
}
}}
}
}
There's likely a zillion better ways of doing it, but it worked. Thanks for the help.
As a side note, it's the equivalent of the "pathInZipFile" function that I could never locate in the Jar creator.
My goal is to change every folder's icon of my movie library to an icon I have for every folder in Windows using Java.
Every folder has a 256x256 icon in it named after the folder but with the appropriate extension.
For example the folder called 5cm Per Second has the file 5cm Per Second.ico in it.
I figured I could do this by modifying the desktop.ini file in the folder. All the folders have that file in them because the icons inside each folder used to be the actual icon of the folder, but after I changed the path of my movie library the path of the icon in desktop.ini didn't get updated.
Every desktop.ini looks like this:
[.ShellClassInfo]
IconResource=F:\Anime\Movies\5cm Per Second\5cm Per Second.ico,0
Now the path of where the icon is at is this: E:\Movies\5cm Per Second\5cm Per Second.ico so I figured all I have to do is change the desktop.ini to this:
[.ShellClassInfo]
IconResource=E:\Movies\5cm Per Second\5cm Per Second.ico,0
That did not work at all then I figured I also should make Windows know that desktop.ini is a system file, I added this to my code but that did not work at all.
My code for that sample folder:
import java.io.File;
import java.io.IOException;
import org.ini4j.Wini;
public class ListFiles {
public static void main(String[] args) throws IOException {
// Directory path here
String path = "E:\\Movies\\5cm Per Second";
String fileName;
File folder = new File(path);
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
if ("ini".equals(getExtension(listOfFiles[i])))
{
File theFile = listOfFiles[i];
Wini ini = new Wini(theFile);
String iconPath = theFile.getParent() + ".ico";
String field = iconPath + ",0";
ini.put(".ShellClassInfo", "IconResource", field);
Runtime.getRuntime().exec("attrib +H " + theFile.getAbsolutePath());
}
}
}
}
public static String getExtension(File theFile) {
String extension = null;
String fileName = theFile.getName();
int i = fileName.lastIndexOf('.');
if (i > 0 && i < fileName.length() - 1) {
extension = fileName.substring(i + 1).toLowerCase();
}
if (extension == null) {
return "";
}
return extension;
}
}
As you can see I edit the IconResource field to the one I need it to be using ini4j library and then I change the attributes of desktop.ini to Hidden and System.
It looks like this is not enough and I really don't know what else to do.
You are not calling ini.store(), which probably writes the change to disk.
I'm trying to get a backup program to take a folder selected by the user using JFileChooser and copy it to a destination also selected using the same method.
The only problem is that it doesn't put all the contents of the selected folder into a folder in the destination named the same thing, and I really dont know why. I did some Googling, and I didnt find anything useful.
Here's the code:
package main;
import java.io.File;
import java.util.ArrayList;
public class test {
BackgroundWorker bw;
static ArrayList bgWorker = new ArrayList();
ArrayList al = new ArrayList(); // this is the list of files selected to
// back up
String dir = ""; // this is the path to back everything up to selected by
static // the user
boolean bwInitiallized = false;
public void startBackup() throws Exception {
Panel.txtArea.append("Starting Backup...\n");
for (int i = 0; i < al.size(); i++) {
/**
* THIS IS WHERE I NEED TO CREATE THE FOLDER THAT EACH BACKUP FILE
* WILL GO INTO EX: SC2 GOES INTO A FOLDER CALLED SC2 AND RIOT GOES
* TO RIOT, ALL WITHIN THE DIRECTORY CHOSEN
*/
File file = new File((String) al.get(i));
File directory = new File(dir);
// File dirFile = new File(dir + "\\" + file.getName());
// if (!dirFile.exists())
// dirFile.mkdir();
bw = new BackgroundWorker(Panel.txtArea, file, directory);
bgWorker.add(bw);
bwInitiallized = true;
bw.execute();
/**
* follows to the bottom of the txtarea
*/
int x;
Panel.txtArea.selectAll();
x = Panel.txtArea.getSelectionEnd();
Panel.txtArea.select(1, x);
}
clearList(); // method not included in this example that deletes all the
// contents of the al array list.
}
public static void cancel() {
BackgroundWorker bg;
if (bwInitiallized) {
bwInitiallized = false;
Panel.txtArea.append("Cancelling...\n");
for (int i = 0; i < bgWorker.size(); i++) {
// BackgroundWorker bg = (BackgroundWorker) bgWorker.get(i);
bg = (BackgroundWorker) bgWorker.get(i);
bg.cancel(true);
}
Panel.txtArea.append("Canceled backUp!\n");
} else {
Panel.txtArea.append("Cannot Cancel! Not Initiallized!\n");
}
}
}
What I think the problem is: I believe that for whatever reason the destination file path needs to have to the name of the folder included, but I tried that and it didnt help.
Does anyone know what I'm doing wrong?
This is the code that makes the JFileChooser:
public void fileChooserToDestination() {
LookAndFeel previousLF = UIManager.getLookAndFeel();
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
}
JFileChooser jfc = new JFileChooser();
try {
UIManager.setLookAndFeel(previousLF);
} catch (UnsupportedLookAndFeelException e) {
}
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
if (jfc.showDialog(null, "Select Directory") == JFileChooser.APPROVE_OPTION) {
File file = jfc.getSelectedFile();
dir = file.getPath();
Panel.txtArea.append("User selected " + file.getPath()
+ " for the destination...\n");
try {
startBackup();
} catch (Exception e) {
}
} else {
Dialogs.msg("You canceled selecting a destination folder! Returning to main screen...");
al.clear();
Panel.txtArea.append("User cancelled the destination selection..."
+ "\n");
}
return;
}
Parts of the code I need are missing. I can't see where you're making your decisions about how to append the source file to the destination path, so I wrote this quick example it illustrate the point...
File sourcePath = new File("/path/to/be/backed/up");
File destPath = new File("X:/BackupHere");
// Get all the files from sourcePath
List<File> listFiles = getFilesFrom(sourcePath);
for (File toBackup : listFiles) {
// Now we need to strip off the sourcePath
// Get the name of the file
String fileName = toBackup.getName();
// Get parent folder's path
String path = toBackup.getParent();
// Remove the source path from file path
path = path.substring(sourcePath.getPath().length());
// Append the file name to the path
path = path + File.separator + fileName;
// Now we have the name of the back up file
String backupFile = destPath + path;
System.out.println("Backup to " + backupFile);
}
Basically, you need to strip of the "source path" (the directory you want to copy). You then use the resulting value to append to the "backup path" value and you should then have a suitable path.