У меня есть реализация программы, которая сортирует строки в большом файле, который не может быть полностью загружен в память из-за его размера. Мой алгоритм разбивает этот файл на несколько файлов, которые сортируются внутри, и после этого он берет два отсортированных файла, строка за строкой сливается в третий файл. Последний шаг повторяется до тех пор, пока не останется только один файл. Алгоритм работает, как и ожидалось, но я хочу отключиться от файлов и работать с пользовательским источником данных: например, сортировать строки из базы данных вместо строк из файла, или использовать простой сбор в качестве источника данных для пирога тестирования
Важно,что в моем алгоритме файл может быть открыт для чтения или записи. Моя идея заключалась в том, чтобы реализовать DataSource
интерфейс с методами String readLine()
и void writeLine(String line)
. Для базы данных и коллекции этот интерфейс может быть легко реализован, поскольку они поддерживают альтернативное чтение и запись. Но для файлов реализация становится намного сложнее, потому что файл может быть открыт либо в режиме чтения, либо в режиме записи.
Следовательно, , если какой-то другой код будет работать с моим интерфейсом, у них будет возможностьпопеременно вызывать чтение и запись, что нарушит реализацию FileDataSource, потому что readLine()
всегда будет возвращать первую строку после вызова writeLine.
Вот вопрос. Можно ли как-то реализовать такой интерфейс с файлами? Или, может быть, я должен рассмотреть другой интерфейс и другие методы? Я застрял и не знаю, что делать.
Позвольте мне объяснить с помощью кода, что я имею в виду:
Все тривиально с CollectionDataSource (я опустил индекс из-за связанной проверки)
public class CollectionDataSource implements DataSource {
private List<String> list = new ArrayList<>();
private int currentReadPosition = 0;
public String readLine() {
return list.get(currentReadPosition++);
}
public void writeLine(String line) {
list.add(line);
}
}
Но с FileDataSource выне может закончиться этим:
public class FileDataSource implements DataSource {
private File file = new File("path/to/file.txt");
private Scanner reader = new Scanner(file);
private PrintWriter writer = new PrintWriter(new FileWriter(file));
public String readLine() {
return reader.nextLine();
}
public void writeLine(String line) {
writer.println(line);
}
}
Вам нужно добавить что-то вроде этого:
public class FileDataSource {
private File file = new File("path/to/file.txt");
private Scanner reader;
private PrintWriter writer;
private Mode mode = Mode.NONE;
public String readLine() throws IOException {
changeMode(Mode.READ);
return reader.nextLine();
}
public void writeLine(String line) throws IOException {
changeMode(Mode.WRITE);
writer.println(line);
}
private void changeMode(Mode newMode) throws IOException {
if (newMode == mode) return;
switch (newMode) {
case NONE:
reader = null;
writer = null;
break;
case READ:
if (writer != null) {
writer.close();
}
reader = new Scanner(file);
break;
case WRITE:
if (reader != null) {
reader.close();
}
writer = new PrintWriter(new FileWriter(file, true));
break;
}
mode = newMode;
}
enum Mode {
NONE,
READ,
WRITE
}
}
Даже если учесть тот факт, что у меня есть куча комментариев к этому коду, это неработать как положено. Но это лучшее, что я могу сделать.
Вывод результата для кода:
DataSource source = new …..
source.writeLine("1");
source.writeLine("2");
source.writeLine("3");
System.out.println(source.readLine());
System.out.println(source.readLine());
source.writeLine("4");
System.out.println(source.readLine());
Использование CollectionDataSource:
1
2
3
Что ожидается и правильно,
Но для FileDataSource это
1
2
1
Я понимаю, почему, но не понимаю, как это исправить. Извините, если мой пост слишком подробный, но я боюсь, что меня неправильно поймут