How to get file sequence between two file paths - java

I got two files:
The first:
/opt/tmp/some_dir_1/some_dir_2/file_1.txt
and the second:
/opt/
Is there a pretty way in java to get files between them?
In result i need such a List<File>:
/opt/tmp/
/opt/tmp/some_dir_1/
/opt/tmp/some_dir_1/some_dir_2/
or a List<String>:
/tmp/
/some_dir_1/
/some_dir_2/
if files not inside each other, there can be some exception or Collection.emptyList() in result
Thanks!

This is classic looping style
public static void main(String[] args) {
List<File> files = new ArrayList<>();
Path path1 = Path.of("/home/test/folder");
Path path2 = Path.of("/home");
if(!path1.startsWith(path2)){
System.err.println("Path2 has to be a parent of path1");
System.exit(-1);
}
while(!path1.equals(path2)){
files.add(path1.toFile());
path1 = path1.getParent();
}
System.out.println(files);
}

Try below solution:
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
public class Solution {
public static void main(String[] args)
{
String strPath1 = "/opt/tmp/some_dir_1/some_dir_2/file_1.txt";
String strPath2 = "/opt";
Path path1 = Paths.get(strPath1);
Path path2 = Paths.get(strPath2);
List<String> inbetweenPaths = new ArrayList<>();
List<File> inbetweenFiles = new ArrayList<>();
if(path1.toFile().exists() && path1.startsWith(path2)) {
Path tempPath = path1;
while(!tempPath.getParent().equals(path2)) {
tempPath = tempPath.getParent();
inbetweenPaths.add(tempPath.toString());
inbetweenFiles.add(tempPath.toFile());
}
}
System.out.println(inbetweenPaths);
System.out.println(inbetweenFiles);
}
}
Output:
[/opt/tmp/some_dir_1/some_dir_2, /opt/tmp/some_dir_1, /opt/tmp]
[/opt/tmp/some_dir_1/some_dir_2, /opt/tmp/some_dir_1, /opt/tmp]

Use absolute path to avoid null value from getParent in case the path provided is not absolute and has no parents e.g. /some_dir_1.
public static void main(String args[]) {
Path childPath = Paths.get("/opt/tmp/some_dir_1/some_dir_2/file_1.txt").toAbsolutePath();
Path parentPath = Paths.get("/opt").toAbsolutePath();
List<String> parents = new ArrayList<String>();
// Checks if parentPath is indeed a parent of childPath
if(childPath.startsWith(parentPath)){
// Loop until parent of childPath and parentPath are equal
while(!childPath.getParent().equals(parentPath)) {
parents.add(childPath.getParent().toString());
childPath = childPath.getParent();
}
}
else {
// throw Exception or set parent to empty array here
System.out.println("ERR: parentPath must be a parent of childPath");
return;
}
// Prints the output
for(String p : parents) {
System.out.println(p);
}
}
Output:
/opt/tmp/some_dir_1/some_dir_2
/opt/tmp/some_dir_1
/opt/tmp

Related

Cannot get custom annotations from Java class

I want to get class level annotation from Java class:
class FixAnnotation {
public String[] author;
}
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface Fix {
public String[] author() default "";
}
I tried this example of compiled java class:
#Component("test")
#Fix(
author = {"Example author 1", "Example author 2"}
)
public class Order implements Action {
..
}
But when I try:
public List listLocalFilesAndDirsAllLevels(File baseDir) {
List<File> collectedFilesAndDirs = new ArrayList<>();
Deque<File> remainingDirs = new ArrayDeque<>();
if(baseDir.exists()) {
remainingDirs.add(baseDir);
while(!remainingDirs.isEmpty()) {
File dir = remainingDirs.removeLast();
List<File> filesInDir = Arrays.asList(dir.listFiles());
for(File fileOrDir : filesInDir) {
// We need to process only .class files
if(fileOrDir.getName().endsWith(".class")){
collectedFilesAndDirs.add(fileOrDir);
if(fileOrDir.isDirectory()) {
remainingDirs.add(fileOrDir);
}
}
}
}
}
return collectedFilesAndDirs;
}
List<File> list;
for(int i=0; i<list.size(); i++) {
File item = list.get(i);
System.out.println(item.getName());
Fix name = item.getClass().getAnnotation(Fix.class);
out.println("author: " + name.author());
}
I get NPE. Do you know how I can get the annotation content?
EDIT:
I tried this:
public static void main() throws Exception
{
final File folder = new File("/opt/test");
processAnnotatedFiles(listLocalFilesAndDirsAllLevels(folder));
}
public void processAnnotatedFiles(List<File> list) throws IOException, ClassNotFoundException {
out.println("Directory files size " + list.size());
for(int i=0; i<list.size(); i++) {
out.println("File " + list.get(i).getName());
File file = list.get(i);
String path = file.getPath();
String[] authors = getFixFromClassFile(Paths.get(path));
System.out.println(Arrays.toString(authors));
}
}
public List<File> listLocalFilesAndDirsAllLevels(File baseDir) {
List<File> collectedFilesAndDirs = new ArrayList<>();
Deque<File> remainingDirs = new ArrayDeque<>();
if(baseDir.exists()) {
remainingDirs.add(baseDir);
while(!remainingDirs.isEmpty()) {
File dir = remainingDirs.removeLast();
List<File> filesInDir = Arrays.asList(dir.listFiles());
for(File fileOrDir : filesInDir) {
// We need to process only .class files
if(fileOrDir.getName().endsWith(".class")){
collectedFilesAndDirs.add(fileOrDir);
if(fileOrDir.isDirectory()) {
remainingDirs.add(fileOrDir);
}
}
}
}
}
return collectedFilesAndDirs;
}
private String[] getFixFromClassFile(Path pathToClass) throws MalformedURLException, ClassNotFoundException {
// Create class loader based on path
URLClassLoader loader = new URLClassLoader(new URL[]{pathToClass.toUri().toURL()});
// convert path to class with package
String classWithPackage = getClassWithPackageFromPath(pathToClass);
// Load class dynamically
Class<?> clazz = loader.loadClass(classWithPackage);
Fix fix = clazz.getAnnotation(Fix.class);
if (fix == null) {
return new String[0];
}
return fix.author();
}
private String getClassWithPackageFromPath(Path pathToClass) {
final String packageStartsFrom = "com.";
final String classFileExtension = ".class";
final String pathWithDots = pathToClass.toString().replace(File.separator, ".");
return pathWithDots.substring(pathWithDots.indexOf(packageStartsFrom)).replace(classFileExtension, "");
}
I get java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(String.java:1927)
When you invoke getClass method on File object it will return java.io.File Class instance. This method does not load class from given file.
If you want to load a class from given *.class file you need to use java.lang.ClassLoader implementation. For example, java.net.URLClassLoader. Below you can find example how to load class and check annotation:
import java.io.File;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
#Fix(author = "Test author")
public class ReflectionApp {
public static void main(String[] args) throws Exception {
String path = "path/to/com/so/ReflectionApp.class";
String[] authors = getFixFromClassFile(Paths.get(path));
System.out.println(Arrays.toString(authors));
}
private static String[] getFixFromClassFile(Path pathToClass) throws MalformedURLException, ClassNotFoundException {
// Create class loader based on path
URLClassLoader loader = new URLClassLoader(new URL[]{pathToClass.toUri().toURL()});
// convert path to class with package
String classWithPackage = getClassWithPackageFromPath(pathToClass);
// Load class dynamically
Class<?> clazz = loader.loadClass(classWithPackage);
Fix fix = clazz.getAnnotation(Fix.class);
if (fix == null) {
return new String[0];
}
return fix.author();
}
private static String getClassWithPackageFromPath(Path pathToClass) {
final String packageStartsFrom = "com.";
final String classFileExtension = ".class";
final String pathWithDots = pathToClass.toString().replace(File.separator, ".");
return pathWithDots.substring(pathWithDots.indexOf(packageStartsFrom)).replace(classFileExtension, "");
}
}
Above code prints:
[Test author]
See also:
Method to dynamically load java class files

How find files in a directory knowing a part of the name

I have a problem, i have this directory with 1k+ files and some folders. I need find the path of the files(which are in subdirectories) that starts with "BCM", but not only the first i find but every single file which start with that.
I tried looking at other answers about this topic but i couldn't find help,
tried using this code:
File dir = new File("K:\\Jgencs");
FilenameFilter filter = new FilenameFilter()
{
public boolean accept (File dir, String name)
{
return name.startsWith("BCM");
}
};
String[] children = dir.list(filter);
if (children == null)
{
System.out.println("No directory found");
}
else
{
for (int i = 0; i< children.length; i++)
{
String filename = children[i];
System.out.println(filename);
File h = new File(dir,filename);
System.out.println(h.getAbsolutePath()
[UPDATED] This is how you can achieve using plain Java and filter text from a variable passing as parameter:
Here is my directory: /tmp
And here is the code running:
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class GetAllFilesInDirectory {
public static void main(String[] args) throws IOException {
String filter = "BCM";
List<File> files = listFiles("/tmp", new CustomerFileFilter(filter));
for (File file : files) {
System.out.println("file: " + file.getCanonicalPath());
}
}
private static List<File> listFiles(String directoryName, CustomerFileFilter fileFilter) {
File directory = new File(directoryName);
List<File> files = new ArrayList<>();
// Get all files from a directory.
File[] fList = directory.listFiles(fileFilter);
if(fList != null) {
for (File file : fList) {
if (file.isFile()) {
files.add(file);
} else if (file.isDirectory()) {
files.addAll(listFiles(file.getAbsolutePath(), fileFilter));
}
}
}
return files;
}
}
class CustomerFileFilter implements FileFilter {
private final String filterStartingWith;
public CustomerFileFilter(String filterStartingWith) {
this.filterStartingWith = filterStartingWith;
}
#Override
public boolean accept(File file) {
return file.isDirectory() || file.isFile() && file.getName().startsWith(filterStartingWith);
}
}
This is the output:
file: /private/tmp/BCM01.txt
file: /private/tmp/BCM01
file: /private/tmp/subfolder1/BCM02.txt
Doing recursive calls to the method when finding a directory to also list the files form inside, and filtering by name the files before adding.
You want Files.walk:
try (Stream<Path> files = Files.walk(Paths.get("K:\\Jgencs"))) {
files.filter(f -> f.getFileName().toString().startsWith("BCM")).forEach(
file -> System.out.println(file));
}

Comparing file names

I want to compare file lying in two different folders.
I wish to compare only files which have same name in those two different folders.
What I wish to do is to compare two different versions of a software and find how many files have been changed.
This will help you get files for two paths:
import java.io.File;
import java.util.*;
public class ListFiles
{
public static void main(String[] args)
{
// First directory path here.
String path1 = ".";
// Second directory path here.
String path2 = ".";
// File class is very important.
// If you did a simple Google search
// Then you would have seen this class mentioned.
File folder1 = new File(path1);
File folder2 = new File(path2);
// It gets the list of files for you.
File[] listOfFiles1 = folder1.listFiles();
File[] listOfFiles2 = folder2.listFiles();
// We'll need these to store the file names as Strings.
ArrayList<String> fileNames1 = new ArrayList<String>();
ArrayList<String> fileNames2 = new ArrayList<String>();
// Get file names from first directory.
for (int i = 0; i < listOfFiles1.length; i++)
{
if (listOfFiles1[i].isFile())
{
fileNames1.add(listOfFiles1[i].getName());
}
}
// Get file names from second directory.
for (int i = 0; i < listOfFiles2.length; i++)
{
if (listOfFiles2[i].isFile())
{
fileNames2.add(listOfFiles2[i].getName());
}
}
// Now compare
// Loop through the two array lists and add your own logic.
}
}
You will need to add your own logic to compare. Source
I have this code which compares all the files in the directory with a particular file to check if that files aleady exists in the directory,may tweak that a little as per your needs.It uses commons-io.jar
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.io.FileUtils;
public class CompareFile {
String directory;
File file;
public CompareFile(String directory, File file) {
this.directory = directory;
this.file = file;
}
public boolean doesFileExist() {
boolean indicatorFileExist = true;
List<File> files = null;
try {
files = getFiles();
files = files.stream().filter(fileMatch -> {
try {
if(fileMatch.isFile()){
return FileUtils.contentEquals(fileMatch, file);
}else{
return false;
}
} catch (Exception excep) {
excep.printStackTrace();
return false;
}
}).collect(Collectors.toList());
if(files.isEmpty()){
indicatorFileExist = false;
}
} catch (Exception excep) {
excep.printStackTrace();
} finally {
if (files != null) {
files = null;
}
}
return indicatorFileExist;
}
private List<File> getFiles() {
List<File> fileList = null;
try {
if(directory!=null && directory.trim().length()>0 && file!=null){
File dir = new File(directory);
if(dir.isDirectory() && dir.exists() && dir.canRead()){
fileList = Arrays.asList(dir.listFiles());
}
}
} catch (Exception excep) {
excep.printStackTrace();
}
return fileList;
}
}

Iterate through all files in Java

I want to make my program print huge list of all files that I have on my computer. My problem is that it only prints files from first folder of the first hard-drive, when I want it to print all files located on my computer. Any ideas what am I doing wrong here? Thanks.
Here is code I use:
Main:
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
ArrayList<File> roots = new ArrayList();
roots.addAll(Arrays.asList(File.listRoots()));
for (File file : roots) {
new Searcher(file.toString().replace('\\', '/')).search();
}
}
}
and Searcher class:
import java.io.File;
public class Searcher {
private String root;
public Searcher(String root) {
this.root = root;
}
public void search() {
System.out.println(root);
File folder = new File(root);
File[] listOfFiles = folder.listFiles();
for (File file : listOfFiles) {
String path = file.getPath().replace('\\', '/');
System.out.println(path);
if (!path.contains(".")) {
new Searcher(path + "/").search();
}
}
}
}
I just tried this and it worked for me. I did have to add one null check and changed the directory evaluation method though:
package test;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
public class Searcher {
public static void main(String[] args) {
ArrayList<File> roots = new ArrayList<File>();
roots.addAll(Arrays.asList(File.listRoots()));
for (File file : roots) {
new Searcher(file.toString().replace('\\', '/')).search();
}
}
private String root;
public Searcher(String root) {
this.root = root;
}
public void search() {
System.out.println(root);
File folder = new File(root);
File[] listOfFiles = folder.listFiles();
if(listOfFiles == null) return; // Added condition check
for (File file : listOfFiles) {
String path = file.getPath().replace('\\', '/');
System.out.println(path);
if (file.isDirectory()) {
new Searcher(path + "/").search();
}
}
}
}
You should update your search method like this:
public void search() {
System.out.println(root);
File folder = new File(root);
File[] listOfFiles = folder.listFiles();
for (File file : listOfFiles) {
String path = file.getPath().replace('\\', '/');
System.out.println(path);
if (file.isDirectory()) {
new Searcher(path + "/").search();
}
}
}
If Java 7 is an option, look into the walkFileTree() method. It will allow you to visit all files and directories in a tree, which you can start from the root of your drive. Just implement a basic FileVisitor to process the file attributes for each Path. You can get started here.
If you're using Java SE 7, use the new file API:
http://docs.oracle.com/javase/7/docs/api/java/nio/file/FileVisitor.html
http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#walkFileTree%28java.nio.file.Path,%20java.util.Set,%20int,%20java.nio.file.FileVisitor%29
http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#walkFileTree%28java.nio.file.Path,%20java.nio.file.FileVisitor%29
I don't know what error you are getting but I got a NPE because you are not checking for the null after the following line.
File[] listOfFiles = folder.listFiles();
After changing the code as follows it seemed to run fine , I stopped it because I have a lot of files. I am assuming it will go on to the next root after the first root(c:/ in my case)
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
public class Search {
public static void main(String[] args) {
ArrayList<File> roots = new ArrayList();
roots.addAll(Arrays.asList(File.listRoots()));
for (File file : roots) {
System.out.println(file.toString());
new Searcher(file.toString().replace('\\', '/')).search();
}
}
}
class Searcher {
private String root;
public Searcher(String root) {
this.root = root;
}
public void search() {
System.out.println(root);
File folder = new File(root);
File[] listOfFiles = folder.listFiles();
if(listOfFiles!=null)
{
for (File file : listOfFiles) {
String path = file.getPath().replace('\\', '/');
System.out.println(path);
if (!path.contains(".")) {
new Searcher(path + "/").search();
}
}
}
}
}

Retrieveing path of text files in Directory using Java

I have the directory path being passed as an argument in Java program and the directory has various types of files. I want to retrieve path of text files and then further each text file.
I am new to Java, any recommendation how to go about it?
Even though this is not an optimum solution you can use this as a starting point.
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DirectoryWalker {
/**
* #param args
*/
private String extPtr = "^.+\\.txt$";
private Pattern ptr;
public DirectoryWalker(){
ptr = Pattern.compile(extPtr);
}
public static void main(String[] args) {
String entryPoint = "c:\\temp";
DirectoryWalker dw = new DirectoryWalker();
List<String> textFiles = dw.extractFiles(entryPoint);
for(String txtFile : textFiles){
System.out.println("File: "+txtFile);
}
}
public List<String> extractFiles(String startDir) {
List<String> textFiles = new ArrayList<String>();
if (startDir == null || startDir.length() == 0) {
throw new RuntimeException("Directory entry can't be null or empty");
}
File f = new File(startDir);
if (!f.isDirectory()) {
throw new RuntimeException("Path " + startDir + " is invalid");
}
File[] files = f.listFiles();
for (File tmpFile : files) {
if (tmpFile.isDirectory()) {
textFiles.addAll(extractFiles(tmpFile.getAbsolutePath()));
} else {
String path = tmpFile.getAbsolutePath();
Matcher matcher = ptr.matcher(path);
if(matcher.find()){
textFiles.add(path);
}
}
}
return textFiles;
}
}
Create a File object representing the directory, then use one of the list() or listFiles() methods to obtain the children. You can pass a filter to these to control what is returned.
For example, the listFiles() method below will return an array of files in the directory accepted by a filter.
public File[] listFiles(FileFilter filter)
Start by reading the File API. You can create a File from a String and even determine if it exists() or isDirectory(). As well as listing the children in that directory.

Categories