Java: сохранить файл в два разных файла - пожалуйста, объясните мне решение

У меня проблема с одной из задач: Чтение 3 имен файлов из консоли: файл1, файл2, файл3. Разделить файл: сохранить половину фрагментов в файл2, а вторую половину — в файл3. Если количество байтов даже не равно, сохраните больше байтов в файле2. Закрыть потоки.

Мне было интересно, как это решить, и единственное решение, которое работает правильно, это:

public class main {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String a = reader.readLine();
        String b = reader.readLine();
        String c = reader.readLine();

        FileInputStream fileInputStream1 = new FileInputStream(a);
        FileOutputStream fileOutputStream2 = new FileOutputStream(b);
        FileOutputStream fileOutputStream3 = new FileOutputStream(c);

        byte[] buffer = new byte[fileInputStream1.available()];

        if (fileInputStream1.available() % 2 != 0) {
            while (fileInputStream1.available() > 0) {
                int count = fileInputStream1.read(buffer);
                fileOutputStream2.write(buffer, 0, count / 2+1);
                fileOutputStream3.write(buffer, count / 2+1, count/2);
            }
        } else {
            while (fileInputStream1.available() > 0) {
                int count = fileInputStream1.read(buffer);
                fileOutputStream2.write(buffer, 0, count / 2);
                fileOutputStream3.write(buffer, count / 2, count/2);
            }
        }

        fileInputStream1.close();
        fileOutputStream2.close();
        fileOutputStream3.close();
    }
}

Мой вопрос: почему я должен сохранять от count/2 до count/2? Для меня это не имеет никакого смысла. Если я буду использовать числа, предположим, что файл file1 имеет 100 байт. Я сохраняю от 0 до count/2 (100/2=50) и от count/2 до count/2 (от 100/2=50 до 100/2=50 или даже 50/2=25). На мой взгляд, это должно быть от 0 до count/2 и от count/2 до count или buffer.length

Пожалуйста, объясните мне, почему мои решения неверны по сравнению с правильным. Спасибо.


person Rafał Pawłowski    schedule 05.05.2020    source источник
comment
Посмотрите документацию OutputStream.write. Третий параметр — это длина части массива для записи, а не позиция. Кроме того, ваше решение неверно, поскольку available() не дает вам количество байтов в файле, а только те, которые доступны для чтения в следующей операции чтения. Это также только оценка. Очень важно читать документацию.   -  person RealSkeptic    schedule 05.05.2020
comment
Фантастика, это помогло мне. Я буду помнить всегда проверять документацию!   -  person Rafał Pawłowski    schedule 05.05.2020


Ответы (1)


Вот объяснение. Первая программа создает считыватель буфера, источником которого является ввод с клавиатуры. Затем программа читает строку за строкой и сохраняет результаты в соответствующих строках. Затем программа создает потоки для чтения и записи в файлы (так называемые файловые потоки). После этого все байты из входного файла считываются и помещаются в массив буферных байтов. Сначала нам нужно проверить, является ли номер байта в файле четным или нечетным, а затем выполнить соответствующие действия по копированию байтов в массивы. Имейте в виду, что при копировании буферного массива диапазон является эксклюзивным в конце и включительно в начале, например. Arrays.copyOfRange(buffer, 0, buffer.length/2) копирует байты в этот интервал [0,buffer.length/2>. Теперь нам нужно только записать байты в соответствующие файлы. Надеюсь это поможет.

       public static void main(String[] args) throws IOException  {

       BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        String inputFile = reader.readLine();
        String outFile2 = reader.readLine();
        String outFile3 = reader.readLine();

        FileInputStream  fileInputStream1  = new FileInputStream(inputFile);
        FileOutputStream fileOutputStream2 = new FileOutputStream(outFile2);
        FileOutputStream fileOutputStream3 = new FileOutputStream(outFile3);

        byte[] buffer = Files.readAllBytes(Paths.get(inputFile));
        byte[] bytesForOut2, bytesForOut3;

        if(buffer.length % 2 == 0) {
            bytesForOut2 = Arrays.copyOfRange(buffer, 0, buffer.length / 2);
            bytesForOut3 = Arrays.copyOfRange(buffer, buffer.length /2, buffer.length);
        }
        else {
            bytesForOut2 = Arrays.copyOfRange(buffer, 0, buffer.length / 2 + 1);
            bytesForOut3 = Arrays.copyOfRange(buffer, buffer.length /2 + 1, buffer.length);
        }

        fileOutputStream2.write(bytesForOut2);
        fileOutputStream3.write(bytesForOut3);

        fileInputStream1.close();
        fileOutputStream2.close();
        fileOutputStream3.close();

}
person Miki    schedule 05.05.2020
comment
Это не будет работать для файлов размером более 2 ГБ и, в зависимости от размера кучи, возможно, не для файлов меньшего размера. И выполнение copyOfRange означает, что вы фактически удваиваете потребность в памяти - первоначальное использование write(buf,from,len) было бы более эффективным с точки зрения использования памяти. - person RealSkeptic; 05.05.2020
comment
@RealSkeptic спасибо за отзыв. Я ценю это. Я новичок, поэтому совет опытного программиста всегда полезен. Есть еще комментарии к моему решению? - person Miki; 05.05.2020