Кратко суть решения:
1. Создал класс MyFile с полями File file и String fileName реализующий интерфейс Comparable
2. Рекурсивно прохожу по директориям и добавляю в TreeSet<MyFile> файлы удовлетворяющие условию
3. Обрабатываю полученный список и копирую содержимое в целевой файл.
Валидатор по всем пунктам ставит на моем решение крест :)
Посмотрел правильное решение - там все сделано совсем по другому. Вроде выбранное мной решение не плохое и мне хочется понять где я допускаю ошибки.
1. Начинается все с переименования файла. Сначала я попытался использовать такую конструкцию
File file = new File(args[1]);
File newFile = new File(file.getParent() + "/allFilesContent.txt");
Но обнаружил, что если в параметрах указать относительный путь, например просто имя файла, то возникает ошибка:
java.io.FileNotFoundException: null\allFilesContent.txt (Системе не удается найти указанный путь)
После этого я реализовал такой вариант:
String newFileName = file.getPath().substring(0, (file.getPath().length()-file.getName().length())) + "allFilesContent.txt";
File newFile = new File(newFileName);
Он работает и на абсолютном и на относительном пути (по крайней мере на тех вариантах, что я попробовал), но валидатор выдает ошибки:
- Файл, который приходит вторым параметром в main, должен быть переименован в allFilesContent.txt.
- Нужно создать поток для записи в переименованный файл.
Посмотрел "правильное" решение, там так:
File newFile = new File(file.getParentFile() + "/allFilesContent.txt");
Метод getParentFile() возвращает объект типа File и я так понимаю он приводится к типу String, т.е. по сути это решение аналогично тому, что я сделал изначально. Вывод в консоль у file.getParent() + "/allFilesContent.txt" и file.getParentFile() + "/allFilesContent.txt" одинаковый - null/allFilesContent.txt, зато валидатор доволен и убирает первые две ошибки.
Итак вопросы по первой части:
- Есть ли какой-то смысл в том, что в правильном решении используется getParentFile() вместо getParent()?
- В выбранном мной решении с обрезанием пути есть какая-то ошибка или валидатор просто занимается фигней?
2. В условиях задачи указано, что файлы нужно отсортировать "по имени файла в возрастающем порядке". Реализуя интерфейс Comparable я делегировал логику сравнения классу String:
public int compareTo(MyFile o) {
return this.fileName.compareTo(o.fileName);
}
Если в первой части реализовать "правильное решение", то от валидатора остается две ошибки:
- Содержимое всех файлов, размер которых не превышает 50 байт, должно быть записано в файл allFilesContent.txt в отсортированном по имени файла порядке.
- Поток для записи в файл нужно закрыть.
Допускаю, что ошибка связана с тем, что стандартная сортировка для строк отличается от того, что хочет увидеть валидатор, но из условий задачи не понятны какие детали сортировки ему не нравятся/нужны, а глядя в правильное решение я вообще не могу понять как они реализуют сортировку.
Вопросы по второй части:
- как правильно сортировать строки, чтобы удовлетворить валидатор
- каким образом реализована сортировка в правильном решении?
package com.javarush.task.task31.task3101;
import java.io.*;
import java.util.*;
/*
Проход по дереву файлов
*/
public class Solution {
public static void main(String[] args) throws IOException{
if (args.length != 2) return;
File path = new File(args[0]);
File file = new File(args[1]);
//String newFileName = file.getPath().substring(0, (file.getPath().length()-file.getName().length())) + "allFilesContent.txt";
//File newFile = new File(newFileName);
File newFile = new File(file.getParent() + "/allFilesContent.txt");
/*
System.out.println(newFileName);
System.out.println(file.getParent() + "/allFilesContent.txt");
System.out.println(file.getParentFile() + "/allFilesContent.txt");
*/
//File newFile = new File(file.getParentFile() + "/allFilesContent.txt");
/* if (FileUtils.isExist(newFile)) {
FileUtils.deleteFile(newFile);
}*/
if (FileUtils.isExist(file)) {
FileUtils.renameFile(file, newFile);
}
SortedSet<MyFile> files = new TreeSet<>();
checkFile(path, files);
aggregateFile(newFile, files);
}
public static void checkFile(File file, Set<MyFile> files) {
if (file.isDirectory() && file.listFiles()!=null) {
for (File innerFile : file.listFiles()) {
checkFile(innerFile, files);
}
}
else if (file.length() <= 50) {
files.add(new MyFile(file.getName(), file));
}
}
public static void aggregateFile(File file, Set<MyFile> files) {
try {
FileOutputStream fos = new FileOutputStream(file);
boolean flag = false;
for (MyFile myFile : files) {
if (flag) {
fos.write("\n".getBytes());
}
FileInputStream fis = new FileInputStream(myFile.file);
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
fos.write(buffer);
flag = true;
}
fos.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
public static class MyFile implements Comparable<MyFile>{
public String fileName;
public File file;
public MyFile(String fileName, File file) {
this.fileName = fileName;
this.file = file;
}
@Override
public int compareTo(MyFile o) {
return this.fileName.compareTo(o.fileName);
}
}
}