I'm reading from a file a list of paths. I want to save them in a built-in java structure that can erase the duplicates automatically. By duplicates I mean if I have /usr/bin and then I add /usr the bin folder has to be erased because is "contained" inside the usr folder. I read the file sequentially so I'd prefer to not have to check all data twice, if possible.
Example code:
UnknownType<Path> database;
BufferedReader reader = new BufferedReader(new FileReader(new File("db.txt")));
String line;
while ((line = reader.readLine()) != null) {
Path path = Paths.get(line).toRealPath();
database.add(path);
}
Example file:
/usr/bin
/usr
/dev
/dev/sda1
/dev/sda2
/home/user/Desktop/file.txt
/home/user/Documents/file2.txt
/home/user/Documents/file3.txt
Expected output:
data structure containing paths:
/usr
/dev
/home/user/Desktop/file.txt
/home/user/Documents/file2.txt
/home/user/Documents/file3.txt
A tree-based solution (probably more efficient):
class Database {
public void add(String p) {
root.add(Arrays.asList(p.split("\\\\|/")), 0);
}
public void addAll(Collection<? extends String> list) {
for (String p : list)
add(p);
}
public List<String> getPathsList() {
ArrayList<String> list = new ArrayList<>();
root.listPaths(list, "");
return list;
}
PathNode root = new PathNode("");
static class PathNode {
public final String name;
public Map<String, PathNode> children = new HashMap<>();
public PathNode(String name) {
this.name = name;
}
public boolean isLeaf() {
return children.size()==0;
}
public boolean isRoot() {
return name.isEmpty();
}
public void add(List<String> path, int i) {
String childName = path.get(i);
PathNode child = children.get(childName);
if (child != null) {
if (path.size()-i <= 1) child.children.clear();
else child.add(path, i+1);
} else if (!isLeaf() || isRoot()) {
PathNode node = this;
for (; i < path.size(); i++) {
String key = path.get(i);
node.children.put(key, node = new PathNode(key));
}
}
}
public void listPaths(ArrayList<String> list, String prefix) {
for (PathNode child : children.values()) {
if (child.isLeaf()) list.add(prefix+child.name);
else child.listPaths(list, prefix+child.name+File.separator);
}
}
}
}
Test to verify correctness: http://ideone.com/cvqEVT
This implementation will accept both Windows and Unix paths when running on any platform. The paths returned by Database.getPathsList() will still use the OS's file separator; you could change that by changing File.separator in Database.PathNode.listPaths (the last line of real code).
A simple solution:
class Database {
public void add(Path p) {
for (int i = 0; i < paths.size(); i++) {
Path p2 = paths.get(i);
if (p2.startsWith(p)) {
// replace with new path
paths.set(i, p);
return;
}
if (p.startsWith(p2)) {
// don't add this new one
return;
}
}
// else, add the new one
paths.add(p);
}
ArrayList<Path> paths = new ArrayList<>();
}
LinkedList implementation:
class Database {
public void add(Path p) {
for (ListIterator<Path> it = paths.listIterator(0); it.hasNext();) {
Path p2 = it.next();
if (p2.startsWith(p)) {
// replace with new path
it.set(p);
return;
}
if (p.startsWith(p2)) {
// don't add this new one
return;
}
}
// else, add the new one
paths.add(p);
}
LinkedList<Path> paths = new LinkedList<>();
}
static ArrayList<Path> paths = new ArrayList<Path>();
public static void main (String[]args) {
add(Paths.get("/usr/bin"));
add(Paths.get("/usr"));
add(Paths.get("/dev"));
add(Paths.get("/dev/sda"));
add(Paths.get("/home/user/Desktop/file.txt"));
System.out.println(paths.toString());
}
public static void add(Path path){
// get root
String firstDir = path.subpath(0, 1).toString();
// check all known paths
for (int q = 0; q < paths.size(); q++){
Path p = paths.get(q);
// get root of saved path
String pFirstDir = p.subpath(0, 1).toString();
// do they have the same root path
if (pFirstDir.equals(firstDir)){
// the new path needs to have less folders otherwise return
if (path.getNameCount()>p.getNameCount()){
return;
}
// set the new path and return
paths.set(q, path);
return;
}
}
// no paths found taht match so add
paths.add(path);
}
will print:
[\usr, \dev, \home\user\Desktop\file.txt]
Related
I want to read the annotations from .class file placed into random folder. I tried this:
public static void main(String[] args) 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)
In this part I want to create a package into random dir. It is really hard to create a valid package from path because there is no any rule package names should follow.
Can you give me some advice how this can be fixed?
Am new to java automation and i have a scenario where i need to navigate to a particular folder, the folder has a list of files i need to filter by date and fetch a filename that got generated recently i.e. if the current time is 5:30pm i need to find the file name that got created between 5:28pm to current time (5:30pm)
This has to be achieved using Java code, File names in the folder
DOF_US_DELL_1.0_20160930_0516.CSV
DOF_US_DELL_1.0_20160930_0756.CSV
DOF_US_DELL_1.0_20161003_0346.CSV
DOF_US_DELL_1.0_20161003_0536.CSV
DOF_US_DELL_1.0_20161004_0747.CSV
DOF_US_DELL_1.0_20161005_0527.CSV
Here is a piece of code that helps me to fetch the list of files in a directory
File dir = new File("C:\\FolderName");
FilenameFilter filter = new FilenameFilter() {
public boolean accept
(File dir, String name) {
return name.startsWith("DOF");
}
};
String[] children = dir.list(filter);
if (children == null) {
System.out.println("Either dir does not exist or is not a directory");
}
else
{
System.out.println("# of the files in the folder is: "+children.length);
if(children.length>0)
{
for (int i=0; i<children.length; i++)
{
String filename = children[i];
System.out.println(filename);
}
}
else
{
System.err.println("# of the files in the folder is: "+children.length);
fail("# of the files in the folder is: "+children.length);
}
}
Thanks in Advance.
Try this. Here I am sorting files on the basis of their last updated time.
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.startsWith("cred");
}
};
List<FileOrder> list = new ArrayList<FileOrder>();
File dir = new File("/tmp/");
for (File file : dir.listFiles(filter)) {
list.add(new FileOrder(file.getName(), file.lastModified()));
}
Collections.sort(list);
System.out.println(list);
System.out.println("Last updated file : " + (list != null ? list.get(0) : null));
Above code is part of main function.
Below code is separate class.
public class FileOrder implements Comparable<FileOrder> {
private String fileName;
private Long updationTIme = 0l;
#Override
public String toString() {
return "FileOrder [fileName=" + fileName + ", updationTIme=" + updationTIme + "]";
}
public FileOrder(String fileName, Long updationDate) {
super();
this.fileName = fileName;
this.updationTIme = updationDate;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public Long getUpdationDate() {
return updationTIme;
}
public void setUpdationDate(Long updationDate) {
this.updationTIme = updationDate;
}
#Override
public int compareTo(FileOrder o) {
return o.getUpdationDate().compareTo(this.getUpdationDate());
}
}
I'm working on implementing the ls method in my program. I need to create a recursive method that will walk through my FileSystem.
Here is my FileSystem implementation right now:
import java.util.ArrayList;
public class FileSystem {
private Directory root;
private Directory wDir;
private ArrayList<File> files = new ArrayList<File>();
// Constructor
public FileSystem() {
}
// Constructor with parameters
public FileSystem(Directory root) {
this.root = root;
wDir = root;
files.add(root);
}
// Returns the FileSystem's files
public ArrayList<File> getFiles() {
return files;
}
// Returns the working directory
public Directory getWDir() {
return wDir;
}
// Sets the working directory
public void setWDir(Directory d) {
wDir = d;
}
// Returns the root file. This will always be / in our program
public File getRoot() {
return root;
}
public File getFile(File f, String name) {
if (f.isDirectory()) {
for (File c : ((Directory) f).getChildren()) {
if (c.getName().equals(name))
return c;
}
}
return null;
}
// Currently only used in cat method, getFile is better
File findFile(File f, String name) {
if (f.getName().equals(name))
return f;
File file = null;
if (f.isDirectory()) {
for (File c : ((Directory) f).getChildren()) {
file = findFile(c, name);
if (file != null)
break;
}
}
return file;
}
// Returns true if file is found
boolean isFile(String name) {
File file = null;
file = getFile(wDir, name);
if (file != null) {
return true;
}
return false;
}
// Creates Directory
public void mkdir(String path) {
files.add(new Directory(path));
int size = files.size();
// Sets the parent
files.get(size - 1).setParent(wDir);
// Sets the child
wDir.addChild(files.get(size - 1));
}
// Changes working directory
public void cd(String s) {
if (s.equals("..")) {
if (wDir != root) {
wDir = wDir.getParent();
}
} else if (s.equals("/")) {
wDir = root;
} else {
wDir = (Directory) getFile(wDir, s);
}
}
// Provides absolute filename
public void pwd() {
if (wDir == root) {
System.out.println("/");
} else {
System.out.println(wDir.getPath());
}
}
// Lists children of current working directory
public void ls() {
ArrayList<File> children = wDir.getChildren();
if (children != null) {
for (int i = 0; i < children.size(); i++) {
String childName = children.get(i).getName();
System.out.print(childName + " ");
}
}
}
// Lists children of file(s) inputted by user
public void ls(File f) {
String name = f.getName();
if (f instanceof TextFile) {
System.out.println(f.getPath());
} else {
ArrayList<File> children = ((Directory) f).getChildren();
if (children != null) {
for (int i = 0; i < children.size(); i++) {
String childName = children.get(i).getName();
System.out.print(childName + " ");
}
}
}
}
// Creates a TextFile or edit's TextFile's content if already exists in the
// tree
public void edit(String name, String content) {
files.add(new TextFile(name, content));
// Setting TextFile parent
files.get(files.size() - 1).setParent(wDir);
// Setting Parent's child
wDir.addChild(files.get(files.size() - 1));
}
// Prints the content of TextFile
public void cat(String name) {
File f = findFile(root, name);
System.out.println(((TextFile) f).getContent());
}
}
As an example of what it needs to do, let's say I have a tree like this:
/
/ \
a b
/ \
x c
/ \
y d
If the user were to enter: ls -r a, my main class would convert that String value using the getFile method, and I would enter that into my recursive function. It would then make use of either ls() or ls(File f), and my main program would output something like this:
a:
x
a/x:
y
a/x/y:
How should I go about creating this method?
Also I should note that I have a Main class, a File class, and a TextFile and Directory class that inherit File.
Any other information that is needed just let me know and I will update this post with it.
You could use something like this:
public void ls(File f) {
System.out.println(f); //or whatever is needed to print the filename
if(f instanceof Directory) {
List<File> fileList = ((Directory)f).getFiles();
//with Java 8
fileList.forEach(subFile -> System.out.println(subFile));
fileList.forEach(subFile -> ls(subFile));
//without Java 8
for(File subFile : fileList) {
System.out.println(subFile);
}
for(File subFile : fileList) {
ls(subFile);
}
System.out.println();
}
}
Basically the first loop is printing all the files in the current directory and the second loop is doing that for all the subdirectories. If the File is not a Directory only it's name is printed. Here I'm assuming that your Directory class has a getFiles() method that returns a List of all Files in the Directory
I'm working on a FileSystem implementation, and I'm having trouble with my Binary Search Tree locate method. Right now the way I have it structured. It will add additional files or something else that I'm unable to figure out.
As an example, I have the tree:
/
/ \
a b
/ / \
c h q
/
x
If the user inputs locate h, my program will output /acxh.
When the user inputs locate h, the output SHOULD be /bh
Here is my FileSystem class:
import java.io.IOException;
import java.util.ArrayList;
public class FileSystem {
private Directory root;
private Directory wDir;
private ArrayList<File> files = new ArrayList<File>();
// Constructor
public FileSystem() {
}
// Constructor with parameters
public FileSystem(Directory root) {
this.root = root;
wDir = root;
files.add(root);
}
// Returns the FileSystem's files
public ArrayList<File> getFiles() {
return files;
}
// Returns the working directory
public Directory getWDir() {
return wDir;
}
// Sets the working directory
public void setWDir(Directory d) {
wDir = d;
}
// Returns the root file. This will always be / in our program
public File getRoot() {
return root;
}
public File getFile(File f, String name) {
if (f.isDirectory()) {
for (File c : ((Directory) f).getChildren()) {
if (c.getName().equals(name))
return c;
}
}
return null;
}
// Currently only used in cat method, getFile is better
File findFile(File f, String name) {
if (f.getName().equals(name))
return f;
File file = null;
if (f.isDirectory()) {
for (File c : ((Directory) f).getChildren()) {
file = findFile(c, name);
if (file != null)
break;
}
}
return file;
}
// Returns true if file is found
boolean isFile(String name) {
File file = null;
file = getFile(wDir, name);
if (file != null) {
return true;
}
return false;
}
// Creates Directory
public void mkdir(String path) {
files.add(new Directory(path));
int size = files.size();
// Sets the parent
files.get(size - 1).setParent(wDir);
// Sets the child
wDir.addChild(files.get(size - 1));
}
// Changes working directory
public void cd(String s) {
if (s.equals("..")) {
if (wDir != root) {
wDir = wDir.getParent();
}
} else if (s.equals("/")) {
wDir = root;
} else {
wDir = (Directory) getFile(wDir, s);
}
}
// Provides absolute filename
public void pwd() {
if (wDir == root) {
System.out.println("/");
} else {
System.out.println(wDir.getPath());
}
}
// Lists children of current working directory
public void ls() {
ArrayList<File> children = wDir.getChildren();
if (children != null) {
for (int i = 0; i < children.size(); i++) {
String childName = children.get(i).getName();
System.out.print(childName + " ");
}
}
}
// Lists children of file(s) inputted by user
public void ls(File f) {
if (f instanceof TextFile) {
System.out.println(f.getPath());
} else {
ArrayList<File> children = ((Directory) f).getChildren();
if (children != null) {
for (int i = 0; i < children.size(); i++) {
String childName = children.get(i).getName();
System.out.print(childName + " ");
}
}
}
}
public void recLS(File f, String location) {
System.out.println(location + ":");
ls(f);
System.out.println("");
if (f.isDirectory()) {
ArrayList<File> children = ((Directory) f).getChildren();
for (File c : children) {
location += "/" + c.getName();
}
for (File c : children) {
recLS(c, location);
}
}
}
// Creates a TextFile or edit's TextFile's content if already exists in the
// tree
public void edit(String name, String content) {
files.add(new TextFile(name, content));
// Setting TextFile parent
files.get(files.size() - 1).setParent(wDir);
// Setting Parent's child
wDir.addChild(files.get(files.size() - 1));
}
// Prints the content of TextFile
public void cat(String name) {
File f = findFile(root, name);
System.out.println(((TextFile) f).getContent());
}
public void updatedb(Indexer i) throws IOException {
i.index(files);
}
public String locate(String s, Indexer i) {
return i.locate(s);
}
}
Here is my Indexer class:
import java.io.*;
import java.util.*;
class Entry implements Comparable<Entry> {
String word;
ArrayList<Integer> page = new ArrayList<Integer>();
Entry(String word) {
this.word = word;
}
public int compareTo(Entry e) {
return word.compareTo(e.word);
}
}
class Indexer {
private BinarySearchTree<Entry> bst;
public void index(ArrayList<File> files) throws IOException {
bst = new BinarySearchTree<Entry>();
int fileCount = 1;
for (int i = 0; i < files.size(); i++) {
String name = files.get(i).getName();
indexName(name, fileCount++);
}
}
private void indexName(String name, int fileCount) {
Entry e = new Entry(name);
Entry r = bst.find(e);
if (r != null) {
r.page.add(fileCount);
} else {
e.page.add(fileCount);
bst.add(e);
}
}
public String locate(String s) {
Entry e = new Entry(s);
ArrayList<String> path = new ArrayList<String>();
bst.locateHelper(e, bst.root, path);
String word = "";
for (int i = 0; i < path.size(); i++) {
word += path.get(i);
}
return word;
}
}
Here is my BinarySearchTree class:
import java.util.ArrayList;
public class BinarySearchTree<E extends Comparable> extends BinaryTree<E> {
private boolean addReturn;
private E deletedItem;
boolean add(E item) {
root = add(root, item);
return addReturn;
}
private Node<E> add(Node<E> n, E item) {
if (n == null) {
addReturn = true;
return new Node<E>(item);
} else if (item.compareTo(n.data) == 0) {
addReturn = false;
return n;
} else if (item.compareTo(n.data) < 0) {
n.leftChild = add(n.leftChild, item);
return n;
} else {
n.rightChild = add(n.rightChild, item);
return n;
}
}
public E find(E target) {
return find(target, root);
}
private E find(E target, Node<E> node) {
if (node == null) {
return null;
}
int result = target.compareTo(node.data);
if (result == 0) {
return node.data;
}
if (result < 0) {
return find(target, node.leftChild);
}
return find(target, node.rightChild);
}
public String locateHelper(Entry e, Node<Entry> node, ArrayList<String> path) {
if (node == null) {
return null;
}
int result = e.compareTo(node.data);
if (result == 0) {
path.add(node.data.word);
return node.data.word;
}
if (result < 0) {
path.add(node.data.word);
return locateHelper(e, node.leftChild, path);
}
path.add(node.data.word);
return locateHelper(e, node.rightChild, path);
}
}
I apologize for having a lot of code in the post, I know I'm supposed to keep it minimal, but I'm sure you will need to look at these 3 classes at least to provide some help. If anything else is needed just let me know and I'll edit this post to provide it.
I'm new to using Swing - I have a recursive method which iterates over directories on the hard drive and currently prints out the music tracks - I want to add the tracks to an array list so that I can send the complete list to a JPanel and display it there... How can I stop the array list being cleared when the method is called recursively for each folder? Thanks
I'm not sure that I understand your code, so I'll restart from scratch, by giving you some pseudo-code:
private List<File> getAllAudioFiles(File folder) {
List<File> result = new ArrayList<>();
// you want a single list. There should be no other list creation in the algorithm.
addAllAudioFiles(folder, result);
return result;
}
private void addAllAudioFiles(File folder, List<File> result) {
for (File file : folder.listFiles()) {
if (file.isDirectory()) {
// call this method recursively, to add all the audio files in the subfolder
// to the SAME list
addAllAudioFiles(file, result);
}
else if (isAudioFile(file)) {
result.add(file);
}
}
}
Try the following code
public class MusicGetter {
ArrayList<String> tlist = new ArrayList<>();
MusicGetter(String c) {
addToList(c);
}
private void addToList(String s) {
File root = new File(s);
File[] files = root.listFiles();
for (File f : files) {
String str = f.getPath();
if (str.endsWith(".mp3") || str.endsWith(".wav") || str.endsWith(".flac") || str.endsWith(".m4a") || str.endsWith(".ogg") || str.endsWith(".wma")) {
tlist.add(str);
}
if (f.isDirectory()) {
addToList(f.getPath().toString());
}
}
}
public static void main(String[] args) {
MusicGetter mg = new MusicGetter("E:\\audios");
for (int i = 0; i < mg.tlist.size(); i++) {
System.out.println(mg.tlist.get(i));
}
}
}