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.
Related
I want to check if a directory is exist by using the notExists(Path path, LinkOption... options) and Im confused with the LinkOption.NOFOLLOW_LINKS although after I googled I still not quite get when to use it. Here are my codes:
import java.io.*;
import java.nio.file.Files;
import java.nio.file.*;
import java.util.ArrayList;
public class Test
{
public static void main(String[] args) throws IOException
{
Path source = Paths.get("Path/Source");
Path destination = Paths.get("Path/Destination");
ArrayList<String> files = new ArrayList<String>();
int retry = 3;
// get files inside source directory
files = getFiles(source);
// move all files inside source directory
for (int j=0; j < files.size(); j++){
moveFile(source,destination,files.get(j),retry);
}
}
// move file to destination directory
public static void moveFile(Path source, Path destination, String file, int retry){
while (retry>0){
try {
// if destination path not exist, create directory
if (Files.notExists(destination, LinkOption.NOFOLLOW_LINKS)) {
// make directory
Files.createDirectories(destination);
}
// move file to destination path
Path temp = Files.move(source.resolve(file),destination.resolve(file));
// if successfully, break
if(temp != null){
break;
}
// else, retry
else {
--retry;
}
} catch (Exception e){
// retry if error occurs
--retry;
}
}
}
// get all file names in source directory
public static ArrayList<String> getFiles(Path source){
ArrayList<String> filenames = new ArrayList<String>();
File folder = new File(source.toString());
File[] listOfFiles = folder.listFiles(); // get all files inside the source directory
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
filenames.add(listOfFiles[i].getName()); // add file's name into arraylist
}
}
return filenames;
}
}
The result of using LinkOption.NOFOLLOW_LINKS and not using it are the same (The files are transferred to the destination). So, Im guessing for my case, i can ignore the Link option? also, in what situation will i be needing that? Thanks!
So, Im guessing for my case, i can ignore the Link option?
You can only follow a link if the link exists.
So if you are testing to make sure a directory doesn't exist, there are two outcomes.
it exists, so there is no need to follow the link.
it doesn't exist, so there is nothing to follow.
in what situation will i be needing that?
Did you look at my answer in the link I provided you? I tried to give a simple example.
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 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.
I am a beginner in Java trying to work with Files and Directories. I wanted to create a program where I could change file names automatically while searching through all the child directories for file names that are not valid. I am actually trying to load a huge amount of files on to a server but the server settings do not allow file names containing special characters. To start with I was able to write the code where if I pass the path to a directory it renames all the files with invalid names in that directory:
public class reNaming {
public static String baseLoc = "C:/Users/Developer/Desktop/.../Data Cleanup";
public static void main(String[] args) {
//LinkedList<File> fileList = new LinkedList<File>();
File obj = new File(baseLoc);
int count = 0;
for (File file: obj.listFiles())
{
String origName = file.getName();
if (origName.contains("&") || origName.contains("#") || origName.contains("#"))
{
System.out.println("Original name: "+origName);
origName = origName.replaceAll("&", "_and_");
origName = origName.replaceAll("#", "_at_");
String newName = origName.replaceAll("#", "_");
System.out.println("New Name: "+newName);
String newLoc = baseLoc+"/"+newName;
File newFile = new File(newLoc);
System.out.println(file.renameTo(newFile));
count++;
}
}
}
}
Now I want to do the same but only this time I want all the files to be reNamed even in the child directories. Can somebody please guide me how I can achieve that?
Recursion is your friend
/**Removes 'invalid' characters (&,#,#) from pathnames in the given folder, and subfolders, and returns the number of files renamed*/
public int renameDirectory(File base){
//LinkedList<File> fileList = new LinkedList<File>();
int count=0;//count the renamed files in this directory + its sub. You wanted to do this?
//Process each file in this folder.
for (File file: base.listFiles()){
String origName = file.getName();
File resultFile=file;
if (origName.contains("&") || origName.contains("#") || origName.contains("#")){
//I would replace the if statement with origName.matches(".*[&##].*") or similar, shorter but more error prone.
System.out.println("Original name: "+origName);
origName = origName.replaceAll("&", "_and_");
origName = origName.replaceAll("#", "_at_");
String newName = origName.replaceAll("#", "_");
System.out.println("New Name: "+newName);
String newLoc = baseLoc+File.separator+newName;//having "/" hardcoded is not cross-platform.
File newFile = new File(newLoc);
System.out.println(file.renameTo(newFile));
count++;
resultFile=newFile;//not sure if you could do file=newFile, tired
}
//if this 'file' in the base folder is a directory, process the directory
if(resultFile.isDirectory()){//or similar function
count+=renameDirectory(resultFile);
}
}
return count;
}
Move the code you have to a utility method (e.g. public void renameAll(File f){}). Have a condition that checks if the file is a directory and recursively call your method with it's contents. After that do what you are currently doing.
public void renameAll(File[] files){
for(File f: files){
if(f.isDirectory){
renameAll(f.listFiles());
}
rename(f);
}
}
public void rename(File f){ }
It is a program (Java) that uses system calls to extract basic information related to the system.
Scan all the files and Display the name and path of the file with the maximum size
Can someone please help i am confused with the system calls.
THanks
Start by taking a look at java.io.File
Take a look at:
File#listFiles
File#length
The for statement
If you're very brave and have the time, you could also take a look at the File I/O API available in Java 7
This is what tou need. But you should read documentation about FILE API . http://docs.oracle.com/javase/7/docs/api/java/io/File.html
public class ListFiles
{
public static void main(String[] args)
{
// Directory path here
String path = ".";
String files="";
double maxBytes = 0;
File folder = new File(path);
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++)
{
if (listOfFiles[i].isFile() && listOfFiles[i].length()>maxBytes)
{
maxBytes = listOfFiles[i].length()
files = listOfFiles[i].getName();
}
}
System.out.println(files);
}
}