My aim is to generate a tree structure in an XML file from a nested ArrayList containing File objects. I constructed the ArrayList by scanning a directory structure on my harddisk.
I want the XML file to look similar to the following:
<root>
<layer1 name="">
<layer2 name="">
<layer3 name=""></layer3>
</layer2>
<layer1>
</root>
the XML should simply represent the hierarchical order of my folders and the name-attributes should be filled with the folder names.
Is there a simple way to realize this in Java?
Thanks in advance!
I have a solution using a library that supports creation of XML via XPath like expression. (I am affiliated with that project)
public class CreateXML {
public static void main(String[] args) {
List<String> fileEntries = Arrays.asList("/path1/path2/file.txt","/path1/path3/path4/file2.txt","/path5/file3.txt");
DOMAccess domAccess = new XBProjector().projectEmptyDocument(DOMAccess.class);
for (String entry:fileEntries) {
String xpath="root";
int i=0;
for (String s:(entry.replaceFirst("\\/", "")).split("\\/")) {
xpath+="/layer"+(++i)+"[#name='"+s+"']";
}
System.out.println(xpath);
domAccess.create(xpath, "");
}
System.out.println(domAccess.asString());
}
}
First thepaths are transformed to a xpath, then elments are created by these paths. The program prints out:
root/layer1[#name='path1']/layer2[#name='path2']/layer3[#name='file.txt']
root/layer1[#name='path1']/layer2[#name='path3']/layer3[#name='path4']/layer4[#name='file2.txt']
root/layer1[#name='path5']/layer2[#name='file3.txt']
<root>
<layer1 name="path1">
<layer2 name="path2">
<layer3 name="file.txt"/>
</layer2>
<layer2 name="path3">
<layer3 name="path4">
<layer4 name="file2.txt"/>
</layer3>
</layer2>
</layer1>
<layer1 name="path5">
<layer2 name="file3.txt"/>
</layer1>
</root>
You'll need only the top-most file in your hierarchy for this. If you don't know which is you can first sort your list, this will put the top-most file at the first position.
String parseFile(File file, int layer) {
StringBuilder result = new StringBuilder();
if(file.isDirectory()) {
if(layer == 0) {
result.append("<root>");
for(File childFile : file.listFiles()) {
result.append(parseFile(childFile, layer + 1));
}
result.append("</root>");
}
result.append("<layer"+layer+" name=\""+file.getName()+"\">");
for(File childFile : file.listFiles()) {
result.append(parseFile(childFile, layer + 1));
}
result.append("</layer"+layer+">");
}
return result.toString();
}
This will go on until the leaf directories, if you intend to parse strictly the files on your list you'll need to test:
String parseFile(List<File> originalFileList, File file, int layer) {
StringBuilder result = new StringBuilder();
if(file.isDirectory()) {
if(layer == 0) {
result.append("<root>");
for(File childFile : file.listFiles()) {
if(originalFileList.contains(childFile)) {
result.append(parseFile(originalFileList, childFile, layer + 1));
}
}
result.append("</root>");
} else {
result.append("<layer"+layer+" name=\""+file.getName()+"\">");
for(File childFile : file.listFiles()) {
if(originalFileList.contains(childFile)) {
result.append(parseFile(originalFileList, childFile, layer + 1));
}
}
result.append("</layer"+layer+">");
}
}
return result.toString();
}
Related
I have the following xml
<Company>
<Company1>
<Dept>
<Name>M1</Name>
<Employers>10</Employers>
<Product>soap</Product>
<Building>001</Building>
<Compulsory>Yes</Compulsory>
</Dept>
<Dept>
<Name>M2</Name>
<Sub-Name>M2-01</Sub-Name>
<Id>m1001</Id>
<Employers>12</Employers>
<Product>soap-cover</Product>
</Dept>
</Company1>
<OtherDetails>
<DeptOther>
<Name>M3</Name>
<Employers>10</Employers>
<Product>soap-colour</Product>
<Building>001</Building>
<Sub>001-01</Sub>
<Compulsory>Yes</Compulsory>
</DeptOther>
</OtherDetails>
</Company>
I need to read this xml and map each of these element to following POJOs.
Object1 - 'Company' which has attributes 'Company1' and 'OtherDetails'
Object2 - 'Company1' which has attributes 'Dept'
Object3 - 'Dept' which has attributes 'Name', 'Employers' etc.
I'm using org.apache.axiom.om.impl.builder.StAXOMBuilder in order to build the DocumentElement.
I'm using following code,
public static void main(String[] args) throws IOException {
mapXMLtoPOJO(FILE_LOCATION);
}
private static boolean mapXMLtoPOJO(String fileLocation) {
File file = new File(fileLocation);
if (file.exists()) {
OMElement fileElement;
try {
InputStream xmlInputStream = new FileInputStream(file);
fileElement = new StAXOMBuilder(xmlInputStream).getDocumentElement();
} catch (Exception e) {
log.error("Error while parsing XML file : " + file.getAbsolutePath());
return false;
}
elementWriter(fileElement);
} else {
return false;
}
return true;
}
public static void elementWriter(OMElement fileElement){
if(fileElement != null){
Iterator iterator1 = fileElement.getChildElements();
int i = 0;
while (iterator1.hasNext()){
OMElement pp = (OMElement) iterator1.next();
log.info(" -------------- " + i);
log.info(" -0-0-0-0-0-0- " + pp.getLocalName() + " ----- " + pp.getText());
i++;
elementWriter(pp);
}
}
}
which print each of the above elements with their values.
But I couldn't find a way to map each of these elements correctly into the java objects created for each major tag as mentioned above.
Should I be store these values in a hash map and then later put them into the created objects? Or what is the most optimum algorithm to do this?
Any idea on how I could do this would be appreciated.
I need help to ‘recursively’ grab files in s3:
For example, I have s3 structure like this:
My-bucket/2018/06/05/10/file1.json
My-bucket/2018/06/05/11/file2.json
My-bucket/2018/06/05/12/file3.json
My-bucket/2018/06/05/13/file5.json
My-bucket/2018/06/05/14/file4.json
My-bucket/2018/06/05/15/file6.json
I need to get all files pathes with file name for given bucket:
I tried following method, but it didn’t worked for me (its returning not whole path):
public List<String> getObjectsListFromFolder4(String bucketName, String keyPrefix) {
List<String> paths = new ArrayList<String>();
String delimiter = "/";
if (keyPrefix != null && !keyPrefix.isEmpty() && !keyPrefix.endsWith(delimiter)) {
keyPrefix += delimiter;
}
ListObjectsRequest listObjectRequest = new ListObjectsRequest().withBucketName(bucketName)
.withPrefix(keyPrefix).withDelimiter(delimiter);
ObjectListing objectListing;
do {
objectListing = s3Client.listObjects(listObjectRequest);
paths.addAll(objectListing.getCommonPrefixes());
listObjectRequest.setMarker(objectListing.getNextMarker());
} while (objectListing.isTruncated());
return paths;
}
There is a new utility class — S3Objects — that provides an easy way to iterate Amazon S3 objects in a "foreach" statement. Use its withPrefix method and then just iterate them. You can use filters and streams as well.
Here is an example (Kotlin):
val s3 = AmazonS3ClientBuilder
.standard()
.withCredentials(EnvironmentVariableCredentialsProvider())
.build()
S3Objects
.withPrefix(s3, bucket, folder)
.filter { s3ObjectSummary ->
s3ObjectSummary.key.endsWith(".gz")
}
.parallelStream()
.forEach { s3ObjectSummary ->
CSVParser.parse(
GZIPInputStream(s3.getObject(s3ObjectSummary.bucketName, s3ObjectSummary.key).objectContent),
StandardCharsets.UTF_8,
CSVFormat.DEFAULT
).use { csvParser ->
…
}
}
getCommonPrefixes() only lists the prefixes, not the actual keys. From the documentation:
For example, consider a bucket that contains the following keys:
"foo/bar/baz"
"foo/bar/bash"
"foo/bar/bang"
"foo/boo"
If calling
listObjects with the prefix="foo/" and the delimiter="/" on this
bucket, the returned S3ObjectListing will contain one entry in the
common prefixes list ("foo/bar/") and none of the keys beginning with
that common prefix will be included in the object summaries list.
Instead, use getObjectSummaries() to get the keys. You also need to remove withDelimiters(). This causes S3 to only list items in the current 'directory.' This method works for me:
public static List<String> getObjectsListFromS3(AmazonS3 s3, String bucket, String prefix) {
final String delimiter = "/";
if (!prefix.endsWith(delimiter)) {
prefix = prefix + delimiter;
}
List<String> paths = new LinkedList<>();
ListObjectsRequest request = new ListObjectsRequest().withBucketName(bucket).withPrefix(prefix);
ObjectListing result;
do {
result = s3.listObjects(request);
for (S3ObjectSummary summary : result.getObjectSummaries()) {
// Make sure we are not adding a 'folder'
if (!summary.getKey().endsWith(delimiter)) {
paths.add(summary.getKey());
}
}
request.setMarker(result.getMarker());
}
while (result.isTruncated());
return paths;
}
Consider an S3 bucket that contains the following keys:
particle.fs
test/
test/blur.fs
test/blur.vs
test/subtest/particle.fs
With this driver code:
public static void main(String[] args) {
String bucket = "playground-us-east-1-1234567890";
AmazonS3 s3 = AmazonS3ClientBuilder.standard().withRegion("us-east-1").build();
String prefix = "test";
for (String key : getObjectsListFromS3(s3, bucket, prefix)) {
System.out.println(key);
}
}
produces:
test/blur.fs
test/blur.vs
test/subtest/particle.fs
Here is an example about how to get all files in the directory, hope can help you :
public static List<String> getAllFile(String directoryPath,boolean isAddDirectory) {
List<String> list = new ArrayList<String>();
File baseFile = new File(directoryPath);
if (baseFile.isFile() || !baseFile.exists()) {
return list;
}
File[] files = baseFile.listFiles();
for (File file : files) {
if (file.isDirectory()) {
if(isAddDirectory){
list.add(file.getAbsolutePath());
}
list.addAll(getAllFile(file.getAbsolutePath(),isAddDirectory));
} else {
list.add(file.getAbsolutePath());
}
}
return list;
}
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
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;
}
I am searching for a .txt file that is located at change set.
Then I need to create locally over my pc the full path directory of this file.
For example if there a file called"test.txt" that it's located at:
Project1-->Folder1-->Folder2-->test.txt
Till now I have managed to search for this file.
Now I need to fetch the full directory and create similar one over my pc:
Result at my pc:
Folder1-->Folder2-->test.txt
That's what I did to search for the file within a changeset and retrieve it:
public IFileItem getTextFileFile(IChangeSet changeSet, ITeamRepository repository) throws TeamRepositoryException{
IVersionableManager vm = SCMPlatform.getWorkspaceManager(repository).versionableManager();
List changes = changeSet.changes();
IFileItem toReturn = null;
for(int i=0;i<changes.size();i++) {="" <br=""> Change change = (Change) changes.get(i);
IVersionableHandle after = change.afterState();
if( after != null && after instanceof IFileItemHandle) {
IFileItem fileItem = (IFileItem) vm.fetchCompleteState(after, null);
if(fileItem.getName().contains(".txt")) {
toReturn = fileItem;
break;
} else {
continue;
}
}
}
if(toReturn == null){
throw new TeamRepositoryException("Could not find the file");
}
return toReturn;
}
I use RTC:4
Win:XP
Thanks in advance.
I have the following IConfiguration that I fetched by the following:
IWorkspaceManager workspaceManager = SCMPlatform.getWorkspaceManager(repository);
IWorkspaceSearchCriteria wsSearchCriteria = WorkspaceSearchCriteria.FACTORY.newInstance();
wsSearchCriteria.setKind(IWorkspaceSearchCriteria.STREAMS);
wsSearchCriteria.setPartialOwnerNameIgnoreCase(projectAreaName);
List <iworkspacehandle> workspaceHandles = workspaceManager.findWorkspaces(wsSearchCriteria, Integer.MAX_VALUE, Application.getMonitor());
IWorkspaceConnection workspaceConnection = workspaceManager.getWorkspaceConnection(workspaceHandles.get(0),Application.getMonitor());
IComponentHandle component = changeSet.getComponent();
IConfiguration configuration = workspaceConnection.configuration(component);
List lst = new ArrayList<string>();
lst=configuration.locateAncestors(lst,Application.getMonitor());
=========================================
Now to get the full path of the file item ,I made the following method I got from :
https://jazz.net/forum/questions/94927/how-do-i-find-moved-from-location-for-a-movedreparented-item-using-rtc-4-java-api
=========================================
private String getFullPath(List ancestor, ITeamRepository repository)
throws TeamRepositoryException {
String directoryPath = "";
for (Object ancestorObj : ancestor) {
IAncestorReport ancestorImpl = (IAncestorReport) ancestorObj;
for (Object nameItemPairObj : ancestorImpl.getNameItemPairs()) {
NameItemPairImpl nameItemPair = (NameItemPairImpl) nameItemPairObj;
Object item = SCMPlatform.getWorkspaceManager(repository)
.versionableManager()
.fetchCompleteState(nameItemPair.getItem(), null);
String pathName = "";
if (item instanceof IFolder) {
pathName = ((IFolder) item).getName();
}
else if (item instanceof IFileItem) {
pathName = ((IFileItem) item).getName();
}
if (!pathName.equals(""))
directoryPath = directoryPath + "\\" + pathName;
}
}
return directoryPath;
}
=========================================