I beg you for help. This is my task.
File Tree Description
Build a String representation of directory hierarchy under a given path
Details
Implement tree method in FileTreeImpl class.
Input parameter is a path.
If a given path does not exist, return an empty Optional.
If a given path refers to a file, return a String with its name and size like this:
some-file.txt 128 bytes
IF a given path refers to a directory, return a String with its name, total size and its full hierarchy:
some-dir 100 bytes
├─ some-inner-dir 50 bytes
│ ├─ some-file.txt 20 bytes
│ └─ some-other-file.txt 30 bytes
└─ some-one-more-file.txt 50 bytes
Use pseudo graphic symbols to format output. Compute directory size as a sum of all its contents.
Sort content in following way: directories go first, directories and files are sorted in lexicographic order (case-insensitive).
This is my implementation.
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class FileTreeImpl implements FileTree {
@Override
public Optional<String> tree(Path path) {
File file = new File(String.valueOf(path));
if ( !file.exists()) return Optional.empty();
if ( file.isFile()) {
return Optional.of(file.getName() + " " + file.length() + " bytes");
}
if (file.isDirectory()) {
return Optional.of(directoryTree(file, 0, false));
}
return Optional.empty();
}
private String directoryTree(File folder, int depth, boolean lastFolder) {
String directory = folder.getName() + " " + folderSize(folder);
if (depth != 0) directory = ((!lastFolder) ? "├─ " : "└─ ") + directory;
File[] files = folder.listFiles();
int count = files.length;
files = sortFiles(files);
for (int i = 0; i < count; i++) {
directory += "\n";
if (depth != 0) directory += "│ ";
if (files[i].isFile()) {
directory += (lastFolder ? " " : "│ ") + (i + 1 == count ? "└" : "├") + "─ " +
files[i].getName() + " " + files[i].length() + " bytes";
} else {
directory += directoryTree(files[i], depth + 1, i + 1 == numberOfFolders(files));
}
}
System.out.println(directory);
return directory;
}
private long getFolderSize(File folder) {
long size = 0;
File[] files = folder.listFiles();
int count = files.length;
for (int i = 0; i < count; i++) {
if (files[i].isFile()) {
size += files[i].length();
} else {
size += getFolderSize(files[i]);
}
}
return size;
}
private String folderSize(File folder) {
return getFolderSize(folder) + " bytes";
}
private File[] sortFiles(File[] folder) {
Arrays.sort(folder);
List<File> sorted = new ArrayList<>();
for (int i = 0; i < folder.length; i++) {
if (folder[i].isDirectory()) sorted.add(folder[i]);
}
for (int i = 0; i < folder.length; i++) {
if (folder[i].isFile()) sorted.add(folder[i]);
}
return sorted.toArray(new File[sorted.size()]);
}
private int numberOfFolders(File[] files) {
int folders = 0;
for (File file : files)
if (file.isDirectory()) folders++;
return folders;
}
}
code of tests you can see here: https://github.com/npogoncuk/file-tree
expected and actual:
Please, help me change the code or, please, give me a piece of advice about new algorithm.
Here is the solution.
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class FileTreeImpl implements FileTree {
@Override
public Optional<String> tree(Path path) {
File file = new File(String.valueOf(path));
if ( !file.exists()) return Optional.empty();
if ( file.isFile()) {
return Optional.of(file.getName() + " " + file.length() + " bytes");
}
if (file.isDirectory()) {
return Optional.of(directoryTree(file, new ArrayList<>()));
}
return Optional.empty();
}
private String directoryTree(File folder, List<Boolean> lastFolders) {
String directory = "";
if (lastFolders.size() != 0)
directory += (!(lastFolders.get(lastFolders.size() -1 )) ? "├─ " : "└─ ");
directory += folder.getName() + " " + folderSize(folder);
File[] files = folder.listFiles();
int count = files.length;
files = sortFiles(files);
for (int i = 0; i < count; i++) {
directory += "\n";
for (Boolean lastFolder : lastFolders) {
if (lastFolder) {
directory += " ";
} else {
directory += "│ ";
}
}
if (files[i].isFile()) {
directory += (i + 1 == count ? "└" : "├") + "─ " +
files[i].getName() + " " + files[i].length() + " bytes";
} else {
ArrayList<Boolean> list = new ArrayList<>(lastFolders);
list.add(i+1 == count);
directory += directoryTree(files[i], list);
}
}
return directory;
}
private long getFolderSize(File folder) {
long size = 0;
File[] files = folder.listFiles();
int count = files.length;
for (int i = 0; i < count; i++) {
if (files[i].isFile()) {
size += files[i].length();
} else {
size += getFolderSize(files[i]);
}
}
return size;
}
private String folderSize(File folder) {
return getFolderSize(folder) + " bytes";
}
private File[] sortFiles(File[] folder) {
Arrays.sort(folder);
List<File> sorted = new ArrayList<>();
for (int i = 0; i < folder.length; i++) {
if (folder[i].isDirectory()) sorted.add(folder[i]);
}
for (int i = 0; i < folder.length; i++) {
if (folder[i].isFile()) sorted.add(folder[i]);
}
return sorted.toArray(new File[sorted.size()]);
}
}
Example of output
test3 0 bytes
├─ a 0 bytes
│ ├─ aa 0 bytes
│ │ ├─ a.txt 0 bytes
│ │ ├─ b.txt 0 bytes
│ │ ├─ c.txt 0 bytes
│ │ └─ d.txt 0 bytes
│ └─ BA 0 bytes
│ ├─ A.txt 0 bytes
│ ├─ b.txt 0 bytes
│ ├─ C.txt 0 bytes
│ └─ d.txt 0 bytes
├─ b 0 bytes
│ ├─ AB 0 bytes
│ │ ├─ a.txt 0 bytes
│ │ ├─ b.txt 0 bytes
│ │ ├─ c.txt 0 bytes
│ │ └─ d.txt 0 bytes
│ └─ bb 0 bytes
│ ├─ A.txt 0 bytes
│ ├─ b.txt 0 bytes
│ ├─ C.txt 0 bytes
│ └─ d.txt 0 bytes
├─ c 0 bytes
│ ├─ aa 0 bytes
│ │ ├─ a.txt 0 bytes
│ │ ├─ b.txt 0 bytes
│ │ ├─ c.txt 0 bytes
│ │ └─ d.txt 0 bytes
│ ├─ BA 0 bytes
│ │ ├─ A.txt 0 bytes
│ │ ├─ b.txt 0 bytes
│ │ ├─ C.txt 0 bytes
│ │ └─ d.txt 0 bytes
│ ├─ a.txt 0 bytes
│ ├─ b.txt 0 bytes
│ ├─ c.txt 0 bytes
│ └─ d.txt 0 bytes
└─ d 0 bytes
├─ aa 0 bytes
│ ├─ a.txt 0 bytes
│ ├─ b.txt 0 bytes
│ ├─ c.txt 0 bytes
│ └─ d.txt 0 bytes
└─ bb 0 bytes
├─ A.txt 0 bytes
├─ b.txt 0 bytes
├─ C.txt 0 bytes
└─ d.txt 0 bytes