【Java學習】調用ByteBuffer.getInt()方法得到808464432


調用ByteBuffer.getInt()方法遇到的奇怪錯誤

最近在參加阿里的中間件比賽,中間用到了RocketMQ的思想,並且主要集中在使用NIO來讀寫文件。其中遇到了一個很蛋疼的問題,想了半天想不出來為什么,現已解決並來記錄一下。

先上代碼:

@Test
public void test() throws IOException {
    FileChannel fc = new RandomAccessFile(STORE_PATH, "rw").getChannel();
    ByteBuffer byteBuffer = fc.map(FileChannel.MapMode.READ_WRITE, 0, 1024);
    int a = byteBuffer.getInt();
    System.out.println(a);
}

代碼主要使用了Java NIO中的FileChannel和ByteBuffer,目的是讀取文件中的四個字節,並將其轉為int類型的數字,對於這個文件我手動輸入了四個'0',按照我的想法,讀出來應該還是會為0。然而結果卻如下:

808464432

這是個什么鬼?試了幾次都是一樣的數字,覺得很奇怪,為什么不是0呢。看了下ByteBuffer.getInt()的源碼,發現ByteBuffer是一個抽象類,該方法有兩種實現方式,分別是DirectByteBuffer和HeapByteBuffer,其中NIO使用的DirectByteBuffer,所以看下源碼:

private int getInt(long a) {
    if (unaligned) {
        int x = unsafe.getInt(a);
        return (nativeByteOrder ? x : Bits.swap(x));
    }
    return Bits.getInt(a, bigEndian);
}

public int getInt() {
    return getInt(ix(nextGetIndex((1 << 2))));
}

其中調用的是Unsafe包下的getInt()的native方法,好像又遇到死胡同了。

最后沒招了,突發奇想搜了一下808464432這個數字,搜到
int變量的值為808464432 是為什么?內存越界?被賦錯值?這篇博客,其中的一段話很明確的解釋了原因:

808464432,是10進制數,轉換為16進制是0x30303030,0x30是字符'0'的ASCII碼的16進制表示,也就是說,808464432這個數字,對應字符串“0000”,一個int變量,占4個字節,如果每個字節都寫入一個字符'0',那么就會是這個數。

原來是因為我輸入的時候是以字符形式輸入到文件,稍微修改一下代碼,果然就好了,代碼和結果如下:

@Test
public void test() throws IOException {
    FileChannel fc = new RandomAccessFile(STORE_PATH, "rw").getChannel();
    ByteBuffer byteBuffer = fc.map(FileChannel.MapMode.READ_WRITE, 0, 1024);
    byteBuffer.putInt(0,1);
    int a = byteBuffer.getInt();
    System.out.println(a);
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM