Iterate through a few jars - java

I just made a program, which iterates through a jar file, and prints out all of the qualified path names for each .class file
My code looks like the following:
public static ArrayList<String> getClassNames(String jarName) {
ArrayList<String> CorbaClasses = new ArrayList<String>();
System.out.println("Jar " + jarName );
try {
JarInputStream jarFile = new JarInputStream(new FileInputStream(
jarName));
JarEntry jarEntry;
while (true) {
jarEntry = jarFile.getNextJarEntry();
if (jarEntry == null) {
break;
}
if (jarEntry.getName().endsWith(".class")) {
System.out.println("Found "
+ jarEntry.getName().replaceAll("/", "\\.").replace(".class", ""));
CorbaClasses.add(jarEntry.getName().replaceAll("/", "\\."));
jarFile.close();
}
}
jarFile.close();
} catch (Exception e) {
e.printStackTrace();
}
return CorbaClasses;
}
What I need now is not to iterate only through one jar file, but to iterate through a bunch of folders, where in each folder there is a jar file, that I need to print out the path names of the class files.
How can i do that?

to iterate over multiple directories/subdirectories use the following code.
File path = new File("your root Directory path");
File [] files = path.listFiles();//return list of all folder plus file in root directory
for (int i = 0; i < files.length; i++){
if (files[i].isFile()){ //if it is file do something
System.out.println(files[i]);
}else {
//it is directory go inside to find jar files
//if inside also directory found make it function and call it recursively
}
}

Related

LibGdx not getting files from within a directory

In my assets folder, I have a directory called "maps" which contains a list of images I want to load.
When running:
Gdx.files.internal("maps").exists();
This returns true
and:
Gdx.files.internal("maps/Africa.png").exists();
also returns true
However, trying to list these files seems to be unfeasible:
Gdx.files.internal("maps").list().length;
returns a value of 0 for the number of files in that directory
Moreover:
Gdx.files.internal("maps").isDirectory();
returns false.
This is very puzzling for what could have seemed to been a very straightforward way of getting files from a directory.
Does anyone have any ideas to circumvent this?
Since desktop builds cannot use the list() method on internal directories, I created this script to write the file names to a text file. It uses Apache commons.io (you can put compile "commons-io:commons-io:2.4+" into your build.gradle to include it in your desktop module):
//directories within assets that you want a catalog of
static final String[] directories = {
"completeMaps",
"typeAMaps",
"typeBMaps",
"sfx",
"music"
};
public static void main (String[] args){
String workingDir = System.getProperty("user.dir");
for (String dir : directories){
File directory = new File(workingDir + "/" + dir);
File outputFile = new File(directory, "catalog.txt");
FileUtils.deleteQuietly(outputFile); //delete previous catalog
File[] files = directory.listFiles();
try {
for (int i = 0; i < files.length; i++) {
FileUtils.write(outputFile, files[i].getName() + (i == files.length - 1 ? "" : "\n"), true);
}
} catch (IOException e){
Util.logError(e);
}
}
}
Then to get a file list in a directory:
private FileHandle[] readDirectoryCatalogue (String directory){
String[] fileNames = Gdx.files.internal(directory + "/catalog.txt").readString().split("\n");
FileHandle[] files = new FileHandle[fileNames.length];
for (int i = 0; i < fileNames.length; i++) {
files[i] = Gdx.files.internal(directory + "/" + fileNames[i].replaceAll("\\s+",""));
}
return files;
}

How do i get the absolute path of .java file from inside the file?

I want to create a new file at the same package of the current class.
FileOutputStream fileOut = new FileOutputStream(YYY);
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(this);
what are the correct YYY for that purpose?
I tried this:
FileOutputStream fileOut = new FileOutputStream("myObject");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(this);
but the "myObject" file was created at: c:\program files\eclipse
help please!
thanks
EDIT: maybe it is worth mentionnig that this is a SVN project. maybe it has something to do with that
What you want is not possible because there might not be a .java file around (only a .class file), the .class file might reside inside a (nested) .jar file and the JVM does not know which classpath entry was used to locate the .class file.
That said, I have tried to solve the same problem for a project of mine. The code goes like this:
private static List<Class> getClassesForPackage(String packagename)
throws ClassNotFoundException
{
// This will hold a list of directories matching the pckgname.
// There may be more than one if a package is split over multiple
// jars/paths
List<Class> classes = new ArrayList<Class>();
List<File> directories = new ArrayList<File>();
try {
ClassLoader classLoader =
Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
throw new ClassNotFoundException("Can't get class loader.");
}
// Ask for all resources for the path
Enumeration<URL> resources =
classLoader.getResources(packagename.replace('.', '/'));
while (resources.hasMoreElements()) {
URL res = resources.nextElement();
if (res.getProtocol().equalsIgnoreCase("jar")) {
JarURLConnection conn =
(JarURLConnection) res.openConnection();
JarFile jar = conn.getJarFile();
for (JarEntry e : Collections.list(jar.entries())) {
if (e.getName().startsWith(
packagename.replace('.', '/'))
&& e.getName().endsWith(".class")
&& !e.getName().contains("$"))
{
String className =
e.getName().replace("/", ".").substring(
0,
e.getName().length() - 6);
classes.add(Class.forName(className));
}
}
}
else
directories.add(new File(URLDecoder.decode(
res.getPath(),
"UTF-8")));
}
}
catch (NullPointerException x) {
throw new ClassNotFoundException(packagename
+ " does not appear to be "
+ "a valid package (Null pointer exception)");
}
catch (UnsupportedEncodingException encex) {
throw new ClassNotFoundException(packagename
+ " does not appear to be "
+ "a valid package (Unsupported encoding)");
}
catch (IOException ioex) {
throw new ClassNotFoundException(
"IOException was thrown when trying "
+ "to get all resources for " + packagename);
}
List<String> subPackages = new ArrayList<String>();
// For every directory identified capture all the .class files
for (File directory : directories) {
if (directory.exists()) {
// Get the list of the files contained in the package
File[] files = directory.listFiles();
for (File file : files) {
// add .class files to results
String fileName = file.getName();
if (file.isFile() && fileName.endsWith(".class")) {
// removes the .class extension
classes.add(Class.forName(packagename + '.'
+ fileName.substring(0, fileName.length() - 6)));
}
// add directories to subpackages
if (file.isDirectory()) {
subPackages.add(packagename + "." + fileName);
}
}
}
else {
throw new ClassNotFoundException(packagename + " ("
+ directory.getPath()
+ ") does not appear to be a valid package");
}
}
// check all potential subpackages
for (String subPackage : subPackages) {
classes.addAll(getClassesForPackage(subPackage));
}
return classes;
}
To find the directory of the corresponding .java file you need to configure the source directory you are using.
Tested for simple case:
URL resource = this.getClass().getClassLoader().getResource(this.getClass().getName().concat(".class"));
This should get you the .class file. Bear in mind the .java file may not even be on the system.

How can I add files to a Jar file?

I want to add a series of files previously extracted from other files(already done) to a jar. These files will be overwriting files inside the JAR. What is the most efficient way to do it?
I need it to be fast.
Thank you!
jar -uf my.jar file1 file2...
jar -uf my.jar dir/
or mixed
jar -uf my.jar file dir/
jar -u file.jar file1 file2 file3 ...
A JAR file is a ZIP file, remember.
Just use some ZIP library.
Just to add to the existing answers, there is at least one special case: so-called executable JAR files. If you add another JAR file as a dependency -- whether you use jar or zip -- it will complain that the embedded file is compressed:
Caused by: java.lang.IllegalStateException: Unable to open nested entry 'BOOT-INF/lib/file.jar'. It has been compressed and nested jar files must be stored without compression. Please check the mechanism used to create your executable jar file
The solution to this is to use the 0 option to jar:
jar uvf0 myfile.jar BOOT-INF/lib/file.jar
You don't need this for normal class files.
zip file.jar file1 file2 file3
works for me in Mac Os 10.7.5
//Add a file in jar in a particular folder
jar uvf <jar file name> <file to be added> <folder name inside jar>
Extending the existing answers, I find the -C jar option very useful when adding files that are on their own folder and you flatten their path out.
$ jar uf jar-file -C /path/to/my_jars/ this_useful.jar
You will end up having this_useful.jar right in the JAR's root:
$ jar tf jar-file | grep this_useful.jar
this_useful.jar
If someone needs a programmatically answer, here it is.
private static void createJar(File source, JarOutputStream target) {
createJar(source, source, target);
}
private static void createJar(File source, File baseDir, JarOutputStream target) {
BufferedInputStream in = null;
try {
if (!source.exists()) {
throw new IOException("Source directory is empty");
}
if (source.isDirectory()) {
// For Jar entries, all path separates should be '/'(OS independent)
String name = source.getPath().replace("\\", "/");
if (!name.isEmpty()) {
if (!name.endsWith("/")) {
name += "/";
}
JarEntry entry = new JarEntry(name);
entry.setTime(source.lastModified());
target.putNextEntry(entry);
target.closeEntry();
}
for (File nestedFile: source.listFiles()) {
createJar(nestedFile, baseDir, target);
}
return;
}
String entryName = baseDir.toPath().relativize(source.toPath()).toFile().getPath().replace("\\", "/");
JarEntry entry = new JarEntry(entryName);
entry.setTime(source.lastModified());
target.putNextEntry(entry); in = new BufferedInputStream(new FileInputStream(source));
byte[] buffer = new byte[1024];
while (true) {
int count = in .read(buffer);
if (count == -1)
break;
target.write(buffer, 0, count);
}
target.closeEntry();
} catch (Exception ignored) {
} finally {
if ( in != null) {
try { in .close();
} catch (Exception ignored) {
throw new RuntimeException(ignored);
}
}
}
}
Here is another example of copying directory content to JAR file.
/**
* Copy source directory to a folder inside JAR file.
* #param directory
* #param jarFile
* #param jarFolder
* #throws Exception
*/
protected void copyDirectoryToJar(String directory, String jarFile, String jarFolder)
throws Exception {
// Initialize local variables.
FileSystem destinationJarFileSystem = null;
Exception exception = null;
try {
// Get source path.
final Path sourcePath = Paths.get(directory);
// Get destination JAR file system and destination path inside the JAR file.
final URI uri = URI.create("jar:file:/" + jarFile.replace(File.separatorChar, '/'));
final Map<String, String> environment = Map.of("create", "true");
destinationJarFileSystem = FileSystems.newFileSystem(uri, environment);
final Path destinationPath = destinationJarFileSystem.getPath(jarFolder);
// Copy source directory into target JAR file.
copyFromDirToJar(sourcePath, destinationPath, destinationJarFileSystem);
}
catch (Exception e) {
exception = e;
}
finally {
// Close JAR file systems.
try {
if (destinationJarFileSystem != null) {
destinationJarFileSystem.close();
}
}
catch (Exception e) {
if (exception == null) {
exception = e;
}
}
}
// Throw exception.
if (exception != null) {
throw exception;
}
}
/* Recursively copy the source sub directories and files to target JAR file system.
* #param sourcePath
* #param destinationPath
* #param destinationFileSystem
*/
private static void copyFromDirToJar(Path sourcePath, Path destinationPath, FileSystem destinationFileSystem)
throws Exception {
// Create destination directory if it doesn't exist.
if (!Files.exists(destinationPath)) {
Files.createDirectories(destinationPath);
}
// If the source and destination paths designate files, copy the source
// file directly to the destination file.
if (Files.isRegularFile(sourcePath) && Files.isRegularFile(destinationPath)) {
Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);
}
// List sub directories in the source path.
Exception [] exception = new Exception [] {null};
Files.list(sourcePath).forEachOrdered(sourceSubPath -> {
try {
Path fileOrFolder = sourceSubPath.getFileName();
Path destinationSubPath = destinationFileSystem.getPath(destinationPath.toString(), fileOrFolder.toString());
// Copy sub directories recursively or copy a single file.
if (Files.isDirectory(sourceSubPath)) {
copyFromDirToJar(sourceSubPath, destinationSubPath, destinationFileSystem);
}
else {
Files.copy(sourceSubPath, destinationSubPath, StandardCopyOption.REPLACE_EXISTING);
}
}
catch (Exception e) {
exception[0] = e;
}
});
// Throw exception.
if (exception[0] != null) {
throw exception[0];
}
}
String cmd = "jar uvf " + "jarName" + " " + "Filename";
System.out.println(cmd);
try {
Process p = Runtime.getRuntime().exec(cmd);
}
catch (Exception ex) {
}

how to get name of all file in a directory and sub-directory in java

I have a directory which consist of some different sub directory which every one have several files. how can i get name of all file?
If you want to use a library, try the listFiles method from apache commons io FileUtils, which will recurse into directories for you.
Here's an example of how you could call it to find all files named *.dat and *.txt in any directory anywhere under the specified starting directory:
Collection<File> files = FileUtils.listFiles(new File("my/dir/path"), {"dat", "txt"}, true);
public static void walkin(File dir) {
String pattern = "file pattern"; //for example ".java"
File listFile[] = dir.listFiles();
if(listFile != null) {
for(int i=0; i<listFile.length; i++) {
if(listFile[i].isDirectory()) {
walkin(listFile[i]);
} else {
if(listFile[i].getName().endsWith(pattern))
{
System.out.println(listFile[i].getPath());
}
}
}
}
}
Recurse through the directory structure, gathering the names of all the files that are not sub-directories.
You are looking for File.list() take a closer look into the javadoc for more details.
To list a directory using Java do something similar to this
File dir = new File(fname);
String[] list = dir.list();
if(list == null){
System.out.println("Specified directory does not exist or is not a directory.");
System.exit(0);
}else{
//list the directory content
for(int i = 0; i < chld.length; i++){
String fileName = list[i];
System.out.println(fileName);
}
Most of this code comes from here, http://www.roseindia.net/java/beginners/DirectoryListing.shtml
This programme will display the whole structure with nested files and nested sub directories with file system.
import java.io.File;
public class DirectoryStructure
{
static void RecursivePrint(File[] arr, int index, int level)
{
// terminate condition
if (index == arr.length) {
return;
}
// tabs for internal levels
for (int i = 0; i < level; i++) {
System.out.print("\t");
}
// for files
if (arr[index].isFile()) {
System.out.println(arr[index].getName());
}
// for sub-directories
else if (arr[index].isDirectory())
{
System.out.println("[" + arr[index].getName() + "]");
// recursion for sub-directories
RecursivePrint(arr[index].listFiles(), 0, level + 1);
}
// recursion for main directory
RecursivePrint(arr, ++index, level);
}
// Driver Method
public static void main(String[] args)
{
// Provide full path for directory(change accordingly)
String maindirpath = "E:\\dms\\Notes";
// File object
File maindir = new File(maindirpath);
if (maindir.exists() && maindir.isDirectory())
{
// array for files and sub-directories
// of directory pointed by maindir
File arr[] = maindir.listFiles();
System.out.println("**********************************************");
System.out.println("Files from main directory : " + maindir);
System.out.println("**********************************************");
// Calling recursive method
RecursivePrint(arr, 0, 0);
}
}
}
Using Apache Commons
String filePath = "/apps/fraud";
String[] acceptedExtension = {"ctl","otl","dat","csv","xls"};
String[] acceptedFolders = {"suresh","dir","kernel"};
Collection fileList = FileUtils.listFiles(
new File(filePath),
new SuffixFileFilter(acceptedExtension) ,
new NameFileFilter(acceptedFolders)
);

Moving file to new location then deleting the Previous file

I want to move file from one path to another path but instead of moving it copy the file to new location.
Kindly provide any hints
Thanks in advance
MovePngToPreviewDir pngToPreviewDir = new MovePngToPreviewDir(null, "png");
File[] listOfPNGFiles = RootDir.listFiles(pngToPreviewDir);
for(File file:listOfPNGFiles){
Log.e("PNG = ",file.getAbsolutePath());
Log.e("PNG = ",file.getName());
if(previewDiagramDir == null){
Log.e("Preview Diagram Dir is NULL","Preview Diagram DIR is NULL");
}
if(file!= null && previewDiagramDir != null){
Log.e("Preview Diagram Dir",previewDiagramDir.getAbsolutePath()+"/");
if(file.renameTo(new File(previewDiagramDir, file.getName()))){
Log.e("PNG File is successfully Moved",file.getName());
}else{
Log.e("Error in Moving PNG File","Error in Moving PNG file");
}
}else{
}
If you want to copy the file to another location, you can use file.renameTo() method of File class, related to your istance object file, trying this:
file.renameTo(new File("new_directory_to_copy_file"+file.getName()));
After copying the file, you can delete it with file.delete();.
Note: The method delete() returns a boolean object, then you can check the correct file deletion with:
boolean del = file.delete();
if(del) System.out.println("File "+file.getName()+" deleted!");
else System.out.println("File "+file.getName()+"not deleted!");
About the File class API: http://download.oracle.com/javase/6/docs/api/java/io/File.html
Use file.delete() after the file is copied to another location so that it is completely moved to the new location.
I have moved files to the destination directory and after moving deleted those moved files from source folder, in three ways, and at last am using the 3rd approach in my project.
1st approach:
File folder = new File("SourceDirectory_Path");
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
Files.move(Paths.get("SourceDirectory_Path"+listOfFiles[i].getName()), Paths.get("DestinationDerectory_Path"+listOfFiles[i].getName()));
}
System.out.println("SUCCESS");
2nd approach:
Path sourceDir = Paths.get("SourceDirectory_Path");
Path destinationDir = Paths.get("DestinationDerectory_Path");
try(DirectoryStream<Path> directoryStream = Files.newDirectoryStream(sourceDir)){
for (Path path : directoryStream) {
File d1 = sourceDir.resolve(path.getFileName()).toFile();
File d2 = destinationDir.resolve(path.getFileName()).toFile();
File oldFile = path.toFile();
if(oldFile.renameTo(d2)){
System.out.println("Moved");
}else{
System.out.println("Not Moved");
}
}
}catch (Exception e) {
e.printStackTrace();
}
3rd approach:
Path sourceDirectory= Paths.get(SOURCE_FILE_PATH);
Path destinationDirectory = Paths.get(SOURCE_FILE_MOVE_PATH);
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(sourceDirectory)) {
for (Path path : directoryStream) {
Path dpath = destinationDirectory .resolve(path.getFileName());
Files.move(path, dpath, StandardCopyOption.REPLACE_EXISTING);
}
} catch (IOException ex) {
ex.printStackTrace();
}

Categories