I have one folder ("all_folders") which contains 5 sub folders ("folder_1","folder_2","folder_3","folder_4" and "folder_5" ).
Each of these sub-folders contains 2 text files having names like "file_1.txt" ,"file_2.txt" and so on.
Each of the text file contains address to the next file say "file_1.txt" content is GOTO "file_2.txt".
In the same manner a file can have multiple address and those file in turn can have address of other files.
Basically its like a binary tree.I want a user to input a file name for which he wants to know all the address the file he entered contains.
The output I want should be like a binary tree. I.e like file_10 contains address of file file_7 , file_8 and file_9.
Again file_9 contains address of file_6 and file_4.
file_8 contains address of file_5.
file_7 doesn't contain any address of file and so on....
I have attached the image of the output which I want and the files and folder i have.
Till now I have written the below code in which i am storing the address which file_10 contains (assuming user entered file_10) in a array list and able to print that.
But now I want this code to repeat till a file doesn't have any address (see image for the output required).
I am planning to use JTree to display output as a binary tree as shown in image.
But that is the second thing and first I need to get the output.
I need help on how we can repeatedly call function to show all file addresses.
Secondly I am using array list but my concern is , do I need to have as many array list as many level of parent child relationship I have in my tree.
Because at present I just only have 5 folders and 10 files but it may increase.so there will be lot many array list.
Can you please help me to achieve this output.
As this is a big code i have tried to write comments wherever possible but sorry as i might not be following good practices in the code as I am a beginner.
Output Image:
Attached all_folder files:
https://drive.google.com/open?id=0B9hvL6YZBpoTRkVYV0dUWEU5V2M
My Code is as below:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;
public class FindFile
{
String result;
static ArrayList<String> storeAllFileName = new ArrayList<String>(); // This array list will store all file names from all the sub-folders of all_folders
static int i = 0;
public void listFilesAndFilesSubDirectories(String directoryName)
{
File directory = new File(directoryName);
File[] fList = directory.listFiles();
for (File file : fList)
{
if (file.isFile())
{
if (file.getName().endsWith(".txt")) // Checking if the file is
// a text file
{
storeAllFileName.add(file.getName().toLowerCase());
i++;
}
} else if (file.isDirectory())
{
listFilesAndFilesSubDirectories(file.getAbsolutePath());
}
}
}
public static void main(String[] args) throws FileNotFoundException
{
recurrenceFileFind();
}
public static void recurrenceFileFind() throws FileNotFoundException
{
FindFile FindFile = new FindFile();
String fileName = "file_10.txt"; // Hardcoded this value assuming user
// have entered file_10.txt
final String directoryName = "C:\\all_folders"; // Hardcoded this value
// assuming all folder
// of user are placed in
// C:\all_folders
// directory
FindFile.listFilesAndFilesSubDirectories(directoryName);
FindFile.searchDirectory(new File(directoryName), fileName);
System.out.println("\nFile Found at: " + FindFile.getResult());
String filedirectoryName = FindFile.getResult(); // Passing the location
// of the file found
// at so that now we
// can read the text
// of the file and
// search for the
// address of child
// files
File file = new File(filedirectoryName);
Scanner in = new Scanner(file);
ArrayList<String> viewText = new ArrayList<String>(); // This array list
// will store the
// content of the
// file
while (in.hasNext())
{
viewText.add(in.next().toLowerCase()); // Store the content of file
// in a array list viewText
}
ArrayList<String> comparingList = new ArrayList<String>(viewText); // copy
// viewText
// array
// List
// to
// new
// array
// list
// comparingList
comparingList.retainAll(storeAllFileName); // store only those address
// in the comparingList for
// which we have file with
// that name in any of the
// sub-folder, as the file
// can have extra content
// like GOTO or any other
// words
System.out.println("\n\"" + file.getName() + "\"" + " contains below files:");
allListPrint(comparingList); // printing address of files which the
// parent file contains
}
public void searchDirectory(File directory, String fileNameToSearch)
{
if (directory.isDirectory())
{
search(directory, fileNameToSearch);
} else
{
System.out.println(directory.getAbsoluteFile() + " is not a directory!");
}
}
private void search(File directory, String fileNameToSearch)
{
if (directory.isDirectory())
{
System.out.println("Searching directory ... " + directory.getAbsoluteFile());
if (directory.canRead())
{
for (File temp : directory.listFiles())
{
if (temp.isDirectory())
{
search(temp, fileNameToSearch);
} else
{
if (fileNameToSearch.equalsIgnoreCase(temp.getName().toLowerCase()))
{
result = (temp.getAbsoluteFile().toString());
}
}
}
} else
{
System.out.println(directory.getAbsoluteFile() + "Permission Denied");
}
}
}
private static void allListPrint(ArrayList<String> List) // method to print
// array list
{
Iterator<String> itr = List.iterator();
while (itr.hasNext())
{
System.out.println(itr.next());
}
}
public String getResult()
{
return result;
}
}
Here is a recursive solution. I assume you can create HashMap<String,Node> from the directory of files yourself. I just manually created such HashMap to save time. But it's quite straightforward to do automatically. In one pass you read all files and create a Nodefor each file, and in the second pass you update their children field.
class Node {
String name;
List<Node> children = new ArrayList();
public Node(String name) {
this.name = name;
}
}
public class FileTree {
//recursive function for returning children
public void retChildHeirarchy(Node n) {
if (n == null) {
return;
}
for (Node child : n.children) {
retChildHeirarchy(child);
System.out.println(child.name);
}
}
public static void main(String[] args) {
HashMap<String, Node> treeStructure = new HashMap<>();
/*To save time, I manually create the nodes and update HashMap of Nodes
but you can do it automatically.
*/
Node f4 = new Node("file_4");
Node f6 = new Node("file_6");
Node f7 = new Node("file_7");
Node f8 = new Node("file_8");
Node f9 = new Node("file_9");
Node f10 = new Node("file_10");
//update f_10
f10.children.add(f9);
f10.children.add(f8);
f10.children.add(f7);
//update f9
f9.children.add(f6);
f9.children.add(f4);
treeStructure.put("file_4", f4);
treeStructure.put("file_6", f6);
treeStructure.put("file_7", f7);
treeStructure.put("file_8", f8);
treeStructure.put("file_9", f9);
treeStructure.put("file_10", f10);
FileTree ft = new FileTree();
//call the recursive function for the Node that you want:
ft.retChildHeirarchy(f9);
}
}
An the output is as follows. Note for f10 the recursive function works ok, but when manually updating f10 I didn't add 5, 2 3, and 1 to the list of its children.
ft.retChildHeirarchy(f9);
file_6
file_4
ft.retChildHeirarchy(f10);
file_6
file_4
file_9
file_8
file_7
Related
i have this code below, but it is not efficient at all, it is very very slow and more pictures i have to compare more long time it takes.
For example i have 500 pictures, each process lasts 2 minutes, 500 x 2 min =1000 min !
the specificity is as soon as there is picture same as compared, move it to another folder. then retrieve the rest files to compare i++
any idea ?
public static void main(String[] args) throws IOException {
String PicturesFolderPath=null;
String removedFolderPath=null;
String pictureExtension=null;
if(args.length>0) {
PicturesFolderPath=args[0];
removedFolderPath=args[1];
pictureExtension=args[2];
}
if(StringUtils.isBlank(pictureExtension)) {
pictureExtension="jpg";
}
if(StringUtils.isBlank(removedFolderPath)) {
removedFolderPath=Paths.get(".").toAbsolutePath().normalize().toString()+"/removed";
}
if(StringUtils.isBlank(PicturesFolderPath)) {
PicturesFolderPath=Paths.get(".").toAbsolutePath().normalize().toString();
}
System.out.println("path to find pictures folder "+PicturesFolderPath);
System.out.println("path to find removed pictures folder "+removedFolderPath);
Collection<File> fileList = FileUtils.listFiles(new File(PicturesFolderPath), new String[] { pictureExtension }, false);
System.out.println("there is "+fileList.size()+" files founded with extention "+pictureExtension);
Iterator<File> fileIterator=fileList.iterator();
//Iterator<File> loopFileIterator=fileList.iterator();
File dest=new File(removedFolderPath);
while(fileIterator.hasNext()) {
File file=fileIterator.next();
System.out.println("process image :"+file.getName());
//each new iteration we retrieve the files staying
Collection<File> list = FileUtils.listFiles(new File(PicturesFolderPath), new String[] { pictureExtension }, false);
for(File f:list) {
if(compareImage(file,f) && !file.getName().equals(f.getName()) ) {
String filename=file.getName();
System.out.println("file :"+file.getName() +" equal to "+f.getName()+" and will be moved on removed folder");
File existFile=new File(removedFolderPath+"/"+file.getName());
if(existFile.exists()) {
existFile.delete();
}
FileUtils.moveFileToDirectory(file, dest, false);
fileIterator.remove();
System.out.println("file :"+filename+" removed");
break;
}
}
}
}
// This API will compare two image file //
// return true if both image files are equal else return false//**
public static boolean compareImage(File fileA, File fileB) {
try {
// take buffer data from botm image files //
BufferedImage biA = ImageIO.read(fileA);
DataBuffer dbA = biA.getData().getDataBuffer();
int sizeA = dbA.getSize();
BufferedImage biB = ImageIO.read(fileB);
DataBuffer dbB = biB.getData().getDataBuffer();
int sizeB = dbB.getSize();
// compare data-buffer objects //
if(sizeA == sizeB) {
for(int i=0; i<sizeA; i++) {
if(dbA.getElem(i) != dbB.getElem(i)) {
return false;
}
}
return true;
}
else {
return false;
}
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}
The already mentioned answer should help you a bit, as considering the width and height of a picture should exclude more candidate pairs quickly.
However, you still have a big problem: For every new file, you read all old files. The number of comparisons grows quadratically and with doing ImageIO.read for every step, it simply must be slow.
You need some fingerprints, which can be compared very fast. You can't use fingerprinting over the whole file content as its infested by the metadata, but you can fingerprint the image data alone.
Just iterate over the image data of a file (like you do), and compute e.g., MD5 hash of it. Store it e.g., as a String in HashSet and you'll get a very fast lookup.
Some untested code
For every image file you want to compare, you compute (using Guava's hashing)
HashCode imageFingerprint(File file) {
Hasher hasher = Hashing.md5().newHasher();
BufferedImage image = ImageIO.read(file);
DataBuffer buffer = image.getData().getDataBuffer();
int size = buffer.getSize();
for(int i=0; i<size; i++) {
hasher.putInt(buffer.getElem(i));
}
return hasher.hash();
}
The computation works with the image data only, just like compareImage in the question, so the metadata get ignored.
Instead of searching for a duplicate in a directory, you compute the fingerprints of all its files and store them in a HashSet<HashCode>. For a new file, you compute its fingerprint and look it up in the set.
I have a folder named collect, there will be some files such as selectData01.json, selectData02.json, selectData03.json and so on.
I have to count the account of the files at first, and then I will send a different file every minute.
Now I want to konw how to achieve the purpose
public String getData() {
String strLocation = new SendSituationData().getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
log.info("strLocation = ");
// String strParent = new File(strLocation).getParent() + "/collectData/conf.properties";
// System.out.println("strParent = " + strParent);
File fileConf = new File("collect/");
System.out.println("fileConf = " + fileConf.getAbsolutePath());
List<List<String>> listFiles = new ArrayList<>();
//File root = new File(DashBoardListener.class.getClassLoader().getResource("collectData/").getPath());
//File root = new File("collectData/application.conf");
File root = new File(fileConf.getAbsolutePath());
System.out.println("root.listFiles( ) = " + root.listFiles( ));
Arrays
.stream(Objects.requireNonNull(root.listFiles( )))
.filter(file -> file.getName().endsWith("json"))
.map(File::toPath)
.forEach(path -> {
try {
//List<String> lines = Files.readAllLines(path);
//System.out.println("lines = " + lines);
List<String> lines = Files.readAllLines(path);
listFiles.add(lines);
} catch (IOException e) {
e.printStackTrace( );
}
});
String dataBody = listToString(listFiles.get(0));
//log.info(dataBody);
ResultMap result = buildRsult();
//String jsonString = JSON.toJSONString(result);
}
public static String listToString(List<String> stringList){
if (stringList == null) {
return null;
}
StringBuilder result=new StringBuilder();
boolean flag=false;
for (String string : stringList) {
if (flag) {
result.append("");
}else {
flag=true;
}
result.append(string);
}
return result.toString();
}
supplement
My friend, maybe i don't express my purpose explicitly. If I have three files, I will sent the first file in the 0:00, sent the second file in the 0:01, sent the third file in the 0:03, sent the first file in the 0:04, sent the second file in the 0:05 and so on.
If I have five files, I will sent the first file in the 0:00, sent the second file in the 0:01, sent the third file in the 0:03, sent the fourth file in the 0:04, sent the fifth file in the 0:05 and so on.
I want to know how to achieve the function
supplement
I have a struct Project that contains a folder named collect. Each file represents a string.
At first, I want to calculate the number of files in collect folder, and then I will send a file every minute.
Any suggestions?
I would use Apache camel with file2 component.
http://camel.apache.org/file2.html
Please read about 'noop' option before running any tests.
Processed files are deleted by default as far as I remember.
Update - simple example added:
I would recommend to start with https://start.spring.io/
Add at least two dependencies: Web and Camel (requires Spring Boot >=1.4.0.RELEASE and <2.0.0.M1)
Create new route, you can start from this example:
#Component
public class FileRouteBuilder extends RouteBuilder {
public static final String DESTINATION = "file://out/";
public static final String SOURCE = "file://in/?noop=true";
#Override
public void configure() throws Exception {
from(SOURCE)
.process(exchange -> {
//your processing here
})
.log("File: ${file:name} has been sent to: " + DESTINATION)
.to(DESTINATION);
}
}
My output:
2018-03-22 15:24:08.917 File: test1.txt has been sent to: file://out/
2018-03-22 15:24:08.931 File: test2.txt has been sent to: file://out/
2018-03-22 15:24:08.933 File: test3.txt has been sent to: file://out/
I have a code that saves a textfile, but the path of that textfile and the name are hardcoded.
How can i make that the user select his/her own path and the name of the file?
int[][] sudokuNumbers = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
try (
PrintStream output = new PrintStream(new File("C:\\Users\\David\\Desktop\\Proyecto4.3\\output.txt"));) {
for (int i = 0; i < sudokuNumbers.length; i++) {
String s= "";
for (int j = 0; j < sudokuNumbers[i].length; j++) {
s+= "|" + sudokuNumbers[i][j] + "|";
}
output.println(s);
}
output.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
The task is relatively easy to carry out however you will need a couple methods to assist you. If a User is to supply a custom path (specific for them-self) then you will need to ensure that the path will be created so that it exists before the file is created and written to. Another thing to consider is that there may also be a requirement of Permissions to be granted to the application so as to carry out the task within the local file system (if this is where the file is to be created) or wherever else.
Obviously you will need to provide a means for the User to supply a path and file name. The best way to do this in my opinion is with a Folder Chooser dialog. The reason I say this is because it's not nearly as prone to mistakes (spelling, system format, etc.) as it would be if the User completely typed in the desired path and file name. Basically, the less control you give the User to the local file system the better off your application will be. Creating a folder (directory) based on the User Name within a preset file system location and utilizing a User name and date/time for file names is relatively common and can be all auto-generated, this eliminates the possibility of any file system errors. If possible, your application should maintain full control of such a task but understandably this can not always be the case for specific applications where User interaction with the file system is a requirement due to the fact that it's sole functionality is based on such interaction. For example, a File System Explorer where creating, cutting, copying, pasting, deleting, and editing of files and folders is its allowable purpose.
To demonstrate what I'm talking about I have quickly created a small Java runnable you can play with to see how the provided custom methods work. The code is well commented so that you can understand what is going on. Unfortunately all the commenting makes the code file look large when in fact it isn't if you were to remove them.
For simplicity, when we run the provided little console application it first asks for a User's Name. This Users Name will serve two specific purposes.
1) It will be used to create a specific Folder for that particular User only.
2) When a file is saved the file name will start with the User's name and then be followed with date/time data and finally contain the
".txt" file name extension.
Again, just for example purposes, as soon as a User enters his/her name into the console a Folders Selection dialog window will be displayed so that a main folder location can be selected where Users sub-folders will be created in and ultimately the Users data files will be saved under his/her folder name.
The file data is automatically saved once the home folder is selected and the console indicates of success once completed. Our little console application then simply ends.
Here is the Java runnable:
package choosefolder;
import java.awt.Component;
import java.awt.Container;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;
import java.time.LocalDateTime;
import java.util.Scanner;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
public class ChooseFolder {
// Declare & initialize required String variables.
// These are global to the entire Class.
private static String userName = "";
private static String savePath = "";
public static void main(String[] args) {
//Setup a Scanner to get User input from console.
Scanner input = new Scanner(System.in);
// Ask for and get the Users Name and convert it to lowercase
// so as to maintain nameing consistency. No sense having "John Doe"
// one day and "john Doe" the next. This would consider 2 different
// Users since the second name has a lowercase "j" in "John" and
// therefore create two separate folder. Converting all supplied names
// to lowercase eliminates this problem.
while (userName.equals("")) {
System.out.println("\nPlease Enter User Name:");
userName = input.nextLine().toLowerCase();
}
// Open a Folders selection dialog window and allow for
// selection of a home folder where all Users saved files
// will be saved. Once we get the selected folder we then
// add the Users name to the path and create it.
savePath = openFoldersDialog("", "Select Home Folder To Save User Folders & File In...") + "\\" + userName;
// Create a special path just for the Users Name (ie: C:\My Files\John Doe\).
if (!createPath(savePath)) {
// If false was returnd from the createPath() method
// then there was an error while creating the path.
// Read console output to get the Error.
System.out.println("\n\u001B[31mError creating Users Save Path! Exiting...\u001B[39;49m");
System.exit(0);
}
// Get the local date & time so we can add it to
// our file namewhen its created.
LocalDateTime dateTime = LocalDateTime.now();
// Create the new file path & file name. This will be the path
// and file name where our Users data will be saved. We take the
// Users path e created and then add the file name to the end. The
// file name consists of the supplied User's name, the date/time and
// the .txt file name extension. Unwanted characters are also removed
// from the Date/Time. So, our path may look something like:
// C:\My Files\John Doe-20160419T155758107.txt
String filePathAndName = savePath + "\\" + userName + "-" +
dateTime.toString().replace("-", "").
replace(":", "").replace(".", "") + ".txt";
// Here is your code. This is the data saved to file....
int[][] sudokuNumbers = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
try (
// Notice the filePathAndName variable which we declared and initialized above.
PrintStream output = new PrintStream(new File(filePathAndName));) {
for (int i = 0; i < sudokuNumbers.length; i++) {
String s= "";
for (int j = 0; j < sudokuNumbers[i].length; j++) {
s+= "|" + sudokuNumbers[i][j] + "|";
}
output.println(s);
}
output.close();
}
catch (FileNotFoundException e) {
System.out.println(e.getMessage());
}
finally {
// Notify in console of success.
System.out.println("\n\u001B[34mFile Saved SUCCESSFULLY in:\n\u001B[39;49m" + filePathAndName);
}
}
/**
* Opens a Folder (directory) selection dialog window. All parameters for this method are optional but if you supply
* something to the last parameter then you must supply something to the parameters preceding it even if it's a null
* string ("") (see usage examples below)
*
* Example Usage:
*
* openFolderDialog(); //Allowed
* openFolderDialog("C:\\"); //Allowed
* openFolderDialog("", "Select The Folder You Need"); //Allowed
* openFolderDialog("", "", "Select Folder"); //Allowed
* openFolderDialog("", "", ""); //Allowed
* openFolderDialog( , "Your Folders, "Select Folder"); //Not Allowed
* openFolderDialog( , , "Select Folder"); //Not Allowed
* openFolderDialog("C:\\", "Your Folders, ); //Not Allowed
*
* I think you get the idea here.
*
* #param dialogOptions OPTIONAL - 3 String Type Parameters
* startPath - String - Default is the running applications' home folder. The path
* supplied here tells the dialog where to start displaying folders from.
* If you just want to use default but would like to supply something to
* the other optional parameters then just supply a null string ("") here.
*
* dialogTitle - String - Dialog Window Title - Default is "Select Folder...". You can
* supply whatever title you like for the dialog window.
*
* openButtonCaption - String - The Select Button Caption - Default is "Select". You can supply
* whatever you like for a button caption and it can be more than one word
* but do keep in mind that the button increases in length to accommodate the
* the supplied string.
*
* #return The selected Folder (directory) full path as string. Returns Null is nothing was selected.
*/
public static String openFoldersDialog(String... dialogOptions) {
String startPath = "";
try {
startPath = new File(".").getCanonicalPath();
} catch (IOException ex) {}
String dialogTitle = "Select Folder...";
String openButtonCaption = "Select";
if (dialogOptions.length != 0) {
if (dialogOptions.length >= 1) {
if (!dialogOptions[0].isEmpty()) { startPath = dialogOptions[0]; }
}
if (dialogOptions.length >= 2) {
if (!dialogOptions[1].isEmpty()) { dialogTitle = dialogOptions[1]; }
}
if (dialogOptions.length == 3) {
if (!dialogOptions[2].isEmpty()) { openButtonCaption = dialogOptions[2]; }
}
}
File sp = new File(startPath);
JFileChooser fc = new JFileChooser(sp);
//Remove the "Files Type:" combo box and label from dialog.
removeJFCFilesTypeComponent(fc);
fc.setDialogTitle(dialogTitle);
fc.setAcceptAllFileFilterUsed(false);
fc.setRequestFocusEnabled(true);
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int userSelection = fc.showDialog(null, openButtonCaption); //.showSaveDialog(null);
if (userSelection == JFileChooser.APPROVE_OPTION) {
String f = fc.getSelectedFile().getPath();
return f;
}
return null;
}
/**
* Removes the Filter ComboBox from the supplied JFileChooser object.
* This helps make the JFileChooser dialog window look more like a
* folder selection dialog.
* #param filechooser The object name of the JFileChooser object.
*/
public static void removeJFCFilesTypeComponent(Container filechooser) {
Component[] components = filechooser.getComponents();
for (Component component : components) {
if (component instanceof JComboBox) {
Object sel = ((JComboBox) component).getSelectedItem();
if (sel.toString().contains("AcceptAllFileFilter")) {
component.setVisible(false);
// OR
//con.remove(component);
}
}
if (component instanceof JLabel) {
String text = ((JLabel) component).getText();
if (text.equals("Files of Type:")) {
component.setVisible(false);
// OR
//con.remove(component);
}
}
if (component instanceof Container) {
removeJFCFilesTypeComponent((Container) component);
}
}
}
/**
* Creates the supplied path into the local file system if it doesn't already exist. You must
* make sure permissions are properly in place before using this method otherwise the path may
* not be created within the file system.
* #param pathString The path to create (must not include a file name). Will not create path if it already exists.
* #return Boolean True if successful and Boolean False if not.
*/
public static boolean createPath(String pathString) {
if (pathString.isEmpty()) { return false; }
if (doesFolderExist(pathString)) { return true; }
try {
File foldersToMake = new File(pathString);
foldersToMake.mkdirs();
return true;
}
catch (Exception ex) {
System.out.println("*** CreatePath() - Exception Encountered:\n*** " + ex.getMessage());
return false;
}
}
/**
* This method simply return boolean true or false if the supplied path exists.
* #param folderPathString (String) The full path to check. No File Name is allowed
* to be in this path.
* #return
*/
public static boolean doesFolderExist(String folderPathString) {
boolean tf = false;
try {
if (folderPathString.isEmpty() || "".equals(folderPathString)) { return tf; }
File f = new File(folderPathString);
if(f.exists() && f.isDirectory()) { tf = true; }
}
catch (Exception e) {
System.out.println("*** DoesFolderExist() - Exception Encountered:\n*** " + e.getMessage());
tf = false;
}
return tf;
}
}
I hope this helps you (and others).
I'm looking for a snippet of code that does the following:
Given two list of string representing two files
For example,
FILE1 = {"SSome" , "SSimple", "TText", "FFile"}
FILE2 = {"AAnother", "TText", "FFile", "WWith", "AAdditional", "LLines"}
If I call diff(file1,file2)
The output would be the diff between FILE1 and FILE2:
*SSome|Another
-SSimple
TText
FFile
+WWith
+AAdditional
+LLines
Many thanks!
I gather from your question the following:
*word1|word2 - Means the word from file 1 was changed in file 2
-word - Means the word from file 1 was removed file 2
word - Means the word from file 1 remained the same in file 2
+word - Means the word wasn't originally in file 1, but was added to file 2
I figured file 1 is the "source" file and file 2 is the "destination" file for which we are showing these differences from. Having said that, try this algorithm (It's not perfect to DiffNow but it's pretty close):
public static void main(String[] args) throws Exception {
List<String> file1 = new ArrayList(Arrays.asList("Some", "Simple", "Text", "File"));
List<String> file2 = new ArrayList(Arrays.asList("Another", "Text", "File", "With", "Additional", "Lines"));
boolean diff = false;
int file2Index = 0;
for (int file1Index = 0; file1Index < file1.size();) {
if (!file1.get(file1Index).equals(file2.get(file2Index)) && !diff) {
diff = true;
// The word from file 1 was changed
System.out.println("*" + file1.get(file1Index) + "|" + file2.get(file2Index));
file1Index++;
file2Index++;
} else if (!file1.get(file1Index).equals(file2.get(file2Index)) && diff) {
// This word was removed from file 1
System.out.println("-" + file1.get(file1Index));
file1Index++;
} else {
System.out.println(file1.get(file1Index));
diff = false;
file1Index++;
file2Index++;
}
}
// Print what's left from file 2
for (; file2Index < file2.size(); file2Index++) {
System.out.println("+" + file2.get(file2Index));
}
}
Results:
*Some|Another
-Simple
Text
File
+With
+Additional
+Lines
Here is what I tried.
import java.util.*;
public class SetDemo
{
public static void main(String[] args){
String[] file1 = new String[]{"Some", "Simple", "Text", "File"};
String[] file2 = new String[]{"Another", "Text", "File", "With", "Additional", "Lines"};
Set<String> set1 = new HashSet<String>();
Set<String> set2 = new HashSet<String>();
for(String s: file1)
{
set1.add(s);
}
for(String s2: file2)
{
set2.add(s2);
}
Set<String> s1intercopy = new HashSet<String>(set1);
Set<String> s2intercopy = new HashSet<String>(set2);
s1intercopy.retainAll(s2intercopy); //Finds the intesection
Set<String> s1symdiffcopy = new HashSet<String>(set1);
Set<String> s2symdiffcopy = new HashSet<String>(set2);
s1symdiffcopy.removeAll(set2);
s2symdiffcopy.removeAll(set1);
int count = 0;
for(String s7: s1intercopy){
count++;
System.out.println(Integer.toString(count)+'.'+s7);
}
if (set1.size() > set2.size())
{
for(String s3: s1symdiffcopy){
count++;
System.out.println(Integer.toString(count)+'.'+'+'+s3);
}
for(String s4: s2symdiffcopy){
count++;
System.out.println(Integer.toString(count)+'.'+'-'+s4);
}
}else if (set2.size() > set1.size())
{
for(String s5: s2symdiffcopy){
count++;
System.out.println(Integer.toString(count)+'.'+'+'+s5);
}
for(String s6: s1symdiffcopy){
count++;
System.out.println(Integer.toString(count)+'.'+'-'+s6);
}
}
}
}
Output:
1.Text
2.File
3.+Lines
4.+Additional
5.+Another
6.+With
7.-Some
8.-Simple
I wasn't sure what you meant by *Some|Another, but what the above code does is simply find the intersection and the symmetric differences between the sets, determine which set is bigger, and assign '+' to the values which are part of the bigger set and '-' to those of the smaller set. I didn't read in from a file to save time but that part is easy and you can look that up. It seems based on your output that you were searching through one file and for each string in that file searching through the other file. This is pretty inefficient for large files so I believe the above solution optimizes that by saving it into sets and performing set operations.
I'm trying to come up with a recursive function that I can use to create the tree view structure that angular tree view uses.
Here's a link that shows the structure: https://github.com/eu81273/angular.treeview
I'm trying to create a tree view based on a file directory on the server and wanted to pass it back from the Java code with JSON. I'm struggling mostly with creating the function that will loop through the directory and create the necessary structure with children.
I've created a POJO class to reflect the tree view structure server side. I was trying to use the following function as a basis for this one:
private static void listFiles(File rootDir, String[] files){
for (String fileName: files){
File fileOrDir = new File(rootDir, fileName);
if (fileOrDir.isDirectory()){
listFiles(fileOrDir, fileOrDir.list());
} else {
System.out.println(fileOrDir);
}
}
}
Here's a clip of what the object looks like:
public class AngularTreeview {
private String label;
private String id;
private Collection<AngularTreeview> children;
}
An suggestions on the function would be awesome. Also alternatives on how to browse the file system on the server or easier ways to create the tree view structure is good to. Thanks!
public static int level = 0;
private static void listFiles(File rootDir, String[] files){
String name = rootDir.toString();
System.out.println(name.substring(name.lastIndexOf('\\') + 1));
for (String fileName: files){
File fileOrDir = new File(rootDir, fileName);
if (fileOrDir.isDirectory()){
level += 1;
for(int i = 0; i < level; ++i)
System.out.print('*');
listFiles(fileOrDir, fileOrDir.list());
level -= 1;
} else {
for(int i = 0; i <= level; ++i)
System.out.print('*');
System.out.println(fileOrDir);
}
}
}
you can use other way to keep track of level and replace ('*') by your needed spaces or '\t'.
File root = new File("C:\\Root");
String[] files = root.list();
listFiles(root, files);
output for your example :
Root
*admin
**C:\Root\admin\subAdmin1.txt
**subAdmin2
***subAdmin2-1
****C:\Root\admin\subAdmin2\subAdmin2-1\subAdmin2-1-1.txt
****C:\Root\admin\subAdmin2\subAdmin2-1\subAdmin2-1-2.txt
*guest
**C:\Root\guest\subguest1.txt
**subguest2
*user
**C:\Root\user\superuser1.txt
**superUser2
This is what I ended up going with, I'm still working out using the results with angular treeview but I'll post that when it works.
public AngularTreeview getDirectoryTreeview(){
File node = new File("C:\\[yourlocation]");
String[] subNote = node.list();
AngularTreeview treeview = new AngularTreeview(node.getName());
treeview.setChildren(setChildrenFunction(node, subNote));
return treeview;
}
public Collection<AngularTreeview> setChildrenFunction(File rootDir, String[] subfiles) {
Collection<AngularTreeview> treecol = new ArrayList<AngularTreeview>();
for (String fileName : subfiles){
AngularTreeview child = new AngularTreeview(fileName);
File fileOrDir = new File(rootDir, fileName);
if (fileOrDir.isDirectory()){
child.setChildren(setChildrenFunction(fileOrDir, fileOrDir.list()));
}
treecol.add(child);
}
return treecol;
}