Нужен совет по переходу на интерфейс с реализации - PullRequest
0 голосов
/ 24 октября 2019

У меня есть реализация программы, которая сортирует строки в большом файле, который не может быть полностью загружен в память из-за его размера. Мой алгоритм разбивает этот файл на несколько файлов, которые сортируются внутри, и после этого он берет два отсортированных файла, строка за строкой сливается в третий файл. Последний шаг повторяется до тех пор, пока не останется только один файл. Алгоритм работает, как и ожидалось, но я хочу отключиться от файлов и работать с пользовательским источником данных: например, сортировать строки из базы данных вместо строк из файла, или использовать простой сбор в качестве источника данных для пирога тестирования

Важно,что в моем алгоритме файл может быть открыт для чтения или записи. Моя идея заключалась в том, чтобы реализовать 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

Я понимаю, почему, но не понимаю, как это исправить. Извините, если мой пост слишком подробный, но я боюсь, что меня неправильно поймут

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...