Не удается прочитать файл фрагментами с помощью MappedByteBuffer

Во время операций чтения я получаю java.io.IOException: канал не открыт для записи - невозможно расширить файл до требуемого размера

Я написал простую программу, которая читает файл с MappedByteBuffer. Идея в том, чтобы прочитать файл с регионами по API. Но во время выполнения я получаю исключение. У меня есть тестовый файл со следующим содержимым:

Простой тестовый файл!

static void readFileWithChunks(final String file){

    final Path pathToFile = Paths.get(file);
    LOG.info("Path to file: {}", pathToFile.toString());

    try (FileChannel fileChannel = (FileChannel) Files.newByteChannel(pathToFile, EnumSet.of(StandardOpenOption.READ))) {

        final long fileSize = fileChannel.size();
        LOG.info("Total size of the file: {} bytes", fileSize);

        final int maxChunkSize = 4;
        long startPosition = 0;
        long endPosition = 0;

        // main cycle to read chunks of data from file
        while (startPosition < fileSize){
            if (endPosition + maxChunkSize < fileSize){
                endPosition += maxChunkSize;
            } else {
                endPosition = fileSize;
            }
            readChunk(fileChannel, startPosition, endPosition);
            startPosition = endPosition;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}


static void readChunk(final FileChannel fileChannel, final long startPosition, final long endPosition) throws IOException {
    LOG.info("Start position: {}; End position: {}", startPosition, endPosition);

    final MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, startPosition, endPosition);

    final int bufferSize = (int) (endPosition - startPosition);
    LOG.info("Buffer size: {}", bufferSize);
    final byte[] buffer = new byte[bufferSize];

    mappedByteBuffer.get(buffer);

    LOG.info("Content of the buffer: {}", new String(buffer, StandardCharsets.UTF_8));
}

ВЫХОД:

OUTPUT
21:39:39.192 [main] com.test.FileReader INFO - Path to file: /user/test/testfile.txt
21:39:39.196 [main] com.test.FileReader INFO - Total size of the file: 15 bytes
21:39:39.196 [main] com.test.FileReader INFO - Start position: 0; End position: 4
21:39:39.198 [main] com.test.FileReader INFO - Buffer size: 4
21:39:39.198 [main] com.test.FileReader INFO - Content of the buffer: Simp
21:39:39.198 [main] com.test.FileReader INFO - Start position: 4; End position: 8
21:39:39.198 [main] com.test.FileReader INFO - Buffer size: 4
21:39:39.198 [main] com.test.FileReader INFO - Content of the buffer: leTe
21:39:39.198 [main] com.test.FileReader INFO - Start position: 8; End position: 12
java.io.IOException: Channel not open for writing - cannot extend file to required size
    at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:901)
    at com.test.FileReader.readChunk(FileReader.java:59)
    at com.test.FileReader.readFile(FileReader.java:42)
    at com.test.TestClass.main(TestClass.java:14)

person jspens    schedule 11.09.2019    source источник
comment
Проблема до сих пор не имеет решения. Если я перехожу в режим WRITE, в файл добавляются конечные нули.   -  person jspens    schedule 12.09.2019


Ответы (1)


Вот ваша проблема:

final MappedByteBuffer mappedByteBuffer = 
    fileChannel.map(
        FileChannel.MapMode.READ_ONLY,
        startPosition,
        endPosition // <-- (endPosition - startPosition)
    );

FileChannel.map принимает смещение + длину, а не начало + конец:

public abstract MappedByteBuffer map(MapMode mode,
                                     long position, long size)
    throws IOException;

Когда вы продвигаете сопоставленное представление за пределы длины файла, базовый файл расширяется для размещения (с неопределенным содержимым между предыдущим концом файла и новым). Для расширения файла требуется доступ для записи, отсюда и исключение.

person JvR    schedule 30.04.2020