Код разделения файлов в Java не работает должным образом - PullRequest
0 голосов
/ 05 декабря 2018

Я пробовал следующий код для разделения файлов, он работает, но не так, как требуется.то есть имена mp3-файлов «song.mp3» имеют размер 2540 КБ, ожидаемое количество фрагментов (по 100 КБ каждый) равно 25, но коды дают только 12 фрагментов, я не понимаю причину.

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

              File file = new File("song.mp3");

    FileInputStream fIn = new FileInputStream("song.mp3");
    FileOutputStream fOut = new FileOutputStream("song_0.mp3");
    int chunk_size = 1024 * 100;
    byte[] buff = new byte[chunk_size]; // 100KB file
    int i = 0;
    String file_name = file.getName();
    String file_name_base = file_name.substring(0, 
    file_name.lastIndexOf("."));
    while (fIn.read() != -1) {

        fIn.read(buff);
        int total_read = 0;
        total_read += chunk_size;
        long read_next_chunk = total_read;
        String file_name_new = file_name_base + "_" + i + ".mp3";
        File file_new = new File(file_name_base);
        i++;
        fOut = new FileOutputStream(file_name_new);
        fOut.write(buff);

        fIn.skip(total_read);// skip the total read part

    } // end of while loop

    fIn.close();
    fOut.close();

}

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Я хотел бы немедленно предложить более новые Path/Files классы.

Следующий код не проверен, но имеет четкое буферизованное чтение:

  • читать исходный файл последовательно
  • зацикливать детали
  • записывать детали, используя буфер (block) - что быстрее, чем просто FileInputStream

Так:

public static void splitFile(String file) throws IOException {
    final long partSize = 100 * 1024;

    Path originalPath = Paths.get(file);
    if (Files.isReadable(originalPath)) {
        throw new FileNotFoundException("Is not a readable file: " + originalPath);
    }
    // Read the file:
    long totalSizeToRead = Files.size(originalPath);
    try (InputStream in = Files.newInputStream(originalPath)) {
        int partNo = 0;
        byte[] block = new byte[16 * 1024];
        // Write parts
        while (totalSizeToRead > 0) {
            // Write part
            ++partNo;
            Path partPath = Paths.get(String.format("%s-%03d.part", file, partNo));
            int sizeToReadInPart = partSize;
            if (totalSizeToRead < sizeToReadInPart) {
                sizeToReadInPart = (int) totalSizeToRead;
            }
            try (OutputStream out = Files.newOutputStream(partPath,
                                    StandardOpenOptions.REPLACE_EXISTING)) {
                // Write blocks of part
                while (sizeToReadInPart > 0) {
                    int toRead = Math.min(block.length, sizeToReadInPart);
                    int actuallyRead = in.read(block, 0, toRead);
                    sizeToReadInPart -= actuallyRead;
                    if (actuallyRead <= 0) {
                        break;
                    }
                    out.write(block, 0, actuallyRead);
                }
            }
            totalSizeToRead -= sizeToReadInPart;
        }
    }
}

Точки здесь:

  • try-with-resource автоматически закрывается даже при исключении возврата / прерывания / выброса.
  • Я использовал файлsize (Long) и int для размеров Buffer, требует некоторого ухода.Также это избыточность, учитывая, что actuallyRead.
  • Java по соглашению использует camelCase вместо подчеркивания для обычных переменных.
0 голосов
/ 05 декабря 2018

Ваш код уверен, что не работает, хотя бы потому, что:на каждой итерации вы читаете 1 байт и выбрасываете его на while (fIn.read() != -1).Измените ваш цикл на что-то вроде этого:

int bytesReadCounter;
while((bytesReadCounter = fIn.read(buff, 0, chunk_size)) > 0){
    .................................. 
    fOut.write(buff, 0, bytesReadCounter);
    ..................................
}

В buff вы сохраняете прочитанные байты, а в bytesReadCounter число прочитанных байтов.Затем вы пишете в fOut из buff точно bytesReadCounter байт.

Редактировать , используйте этот код:

public static void main(String[] args) {
    File file = new File("song.mp3");

    FileInputStream fIn = null;
    try {
        fIn = new FileInputStream(file);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

    int chunk_size = 1024 * 100;
    byte[] buff = new byte[chunk_size]; // 100KB file
    int i = 0;
    String file_name = file.getName();
    String file_name_base = file_name.substring(0, file_name.lastIndexOf("."));
    int bytesReadCounter;
    boolean hasMore = true;
    while (hasMore) {
        try {
            bytesReadCounter = fIn.read(buff, 0, chunk_size);
        } catch (IOException e) {
            e.printStackTrace();
            break;
        }

        hasMore = bytesReadCounter > 0;

        if (!hasMore)
            break;

        String file_name_new = file_name_base + "_" + i + ".mp3";
        File file_new = new File(file_name_new);

        FileOutputStream fOut = null;
        try {
            fOut = new FileOutputStream(file_new);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            break;
        }

        try {
            fOut.write(buff, 0, bytesReadCounter);
            fOut.close();
        } catch (IOException e) {
            e.printStackTrace();
            break;
        }

        i++;
    }

    try {
        fIn.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...