Java Mapped Byte Buffer - мусорные значения в буфере

Я экспериментирую с Mapped Byte Buffer (Java), мне нужно использовать DirectBuffer для файла, чтобы выполнить некоторые арифметические операции:

MappedByteBuffer mbf = new RandomAccessFile("blah.bin", "rw").getChannel().map(FileChannel.MapMode.READ_WRITE,0,100*8L);

Вопросы: - заполнен ли нулевой прямой буфер? У меня есть метод отладки, который сбрасывает значения как

    private void dump(){
    for (int i = 0; i < 100; i++) {
        System.out.println(mbf.getDouble(i));
    }
}

Интересно, что когда я беру дамп перед записью каких-либо значений, он сбрасывает все нули (удваивается):

Когда я пишу в любое место, говорите:

mbf.putDouble(13,100.0);

Когда я снова запускаю дамп, он сбрасывает некоторые случайные значения:

0.0
0.0
0.0
0.0
0.0
3.16E-322
8.1387E-320
2.0835183E-317
5.333806864E-315
1.36545455721E-312
3.4955636664571E-310
1.8187371284868433E-307
100.0
5.164499756173817E120
0.0
0.0
0.0
0.0
0.0

Моя логика зависит от нулевого значения

if (mbf.getDouble(6)==0.0)
//then do some thing
else
//do some thing else

Как я могу убедиться, что значения правильно инициализированы в ноль, прежде чем писать какие-либо условия, как указано выше? Кто-нибудь получил подобную проблему? Каков наилучший способ справиться с этой ситуацией?

Любые идеи высоко ценятся.

Немного подробнее: ОС: Windows 10 JDK: версия Java "1.8.0_111"

Заранее спасибо!

2 ответа

Решение

double значение занимает 8 байт. (В Java всегда, в некоторых других языках обычно, но не всегда.) Из javadoc https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html

Считывает восемь байтов по заданному индексу, объединяя их в двойное значение в соответствии с текущим порядком байтов.

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

Прямой буфер заполнен нулями?

Я склонен полагать, что это заполнено нулями. Потому что, поскольку я использую приведенный ниже код для открытия файла blah.bin, размер на диске составляет 800 байт как для Windows, так и для Linux.

Когда я снова запускаю дамп, он сбрасывает некоторые случайные значения:

Вы видите случайные значения, потому что вы не перемещаете position из mapped byte buffer правильно. т. е. Integer занимает 4 байта, поэтому, как только вы закончите чтение с индексом 0, вы должны начать следующее целое число с позиции 3. Аналогично, для double это 8 байтов.

package com.test;

import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class MappedFileGarbage {

    public static void main(String[] args) throws Exception {
        RandomAccessFile raf = new RandomAccessFile("blah.bin", "rw");
        MappedByteBuffer mbf = raf.getChannel().map(FileChannel.MapMode.READ_WRITE,0,100*8L);
        mbf.putInt(1000).putInt(2000).putDouble(4000.0);
        raf.close();

        raf = new RandomAccessFile("blah.bin", "rw");
        mbf = raf.getChannel().map(FileChannel.MapMode.READ_WRITE,0,100*8L);
        dump(mbf);
    }


    private static void dump(MappedByteBuffer mbf){
        // Reading the data without manually setting the position, as getXXX(n) methods internally increment the position.
        System.out.println(mbf.getInt(0));
        System.out.println(mbf.getInt(4));
        System.out.println(mbf.getDouble(8));

    // Reading the data via getXXX() method as manually setting the position, as getXXX(n) methods don't increment the position.
    System.out.println(mbf.position());
    System.out.println(mbf.getInt());
    System.out.println(mbf.position(4));
    System.out.println(mbf.getInt());
    System.out.println(mbf.position(8));
    System.out.println(mbf.getDouble());
    System.out.println(mbf.position());

    }   
}

Надеюсь это поможет.

Другие вопросы по тегам