簡體   English   中英

為什么 BufferedInputStream(InputStream in, int bufSize) 在使用 mark() 時沒有從 inputStream 中讀取 bufSize 塊中的數據?

[英]Why BufferedInputStream(InputStream in, int bufSize) is not reading data in chunks of bufSize from the inputStream while using mark()?

這是我的代碼:

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;

public class MarkAndResetDemo {

    public static void main(String[] args) {
        String s = "Today is Sunday!";
        byte buf[] = s.getBytes();
        
        System.out.println("s: "+s);
        ByteArrayInputStream in = new ByteArrayInputStream(buf);
        int c, count = 0;
        
        try(BufferedInputStream f = new BufferedInputStream(in, 4)) {//Line 1
            while((c=f.read()) != -1) {
                System.out.print((char)c);
                count++;
                
                if(count==3) f.mark(2); //Line 2
                
                if(count==8) f.reset(); //Line 3
                
            }
        }
        catch(IOException e) {
            e.printStackTrace();
        }

    }

}

當第 3 行計數設置為 8 時,輸出為:

s: 今天是星期天!

今天是java.io.IOException:重置為無效標記

當第 3 行中計數設置為 7 時,輸出為:

s: 今天是星期天!

今天是星期天!

所以我的問題是為什么當第 3 行中的 count 為 7 時沒有出現“無效標記”異常,因為自從上次調用 mark(int i) 以來已經讀取了超過 2 個字節? 似乎 BufferedInputStream 的內部緩沖區一次被填充一個字節,除非 mark(int i) 無效。

我知道 BufferedInputStream 將從輸入流中讀取大小等於其內部緩沖區的數據塊(這里緩沖區大小為 4)。 因此,經過 4 次 while 循環迭代后,BufferedInputStream 的內部緩沖區應包含字節數組中接下來的 4 個字節(buf[] 表示字節編碼形式的字符 'y'、''、'i'、's')。 同樣,第 2 行中的 mark(2) 將在調用 mark(int i) 時在當前位置(要在輸入流中讀取的下一個字節)放置一個鈎子。

設置標記時,緩沖區包含“Toda”,標記的字符為“a”。 當我們需要重新填充緩沖區以打印 'y' 時,前 3 個字符被丟棄(因為標記不需要它們),讀取三個新字符,緩沖區現在包含 'ay i'。 打印 7 個字符 'ay' 后,我們不需要重新填充緩沖區,因此 reset 仍然可以重置為 'a'。

如果您想了解這樣的事情,請在 JDK 類中放置一些斷點。

感謝 tgdavies 的解釋和使用斷點的建議。 我可以看到 BufferedInputStream 的受保護字段,例如 markpos、marlimit、pos 和 count。 通過為marklimit和內部緩沖區大小設置不同的值來玩上面的代碼后,我得出了以下結論:

對於長度為 n >= marklimit 的內部緩沖區:

如果 markpos = k 其中 k 是內部緩沖區 (buf) 的索引,並且即使在從 buf 讀取 (nk) 個字節后,也不會調用 reset,因為上次調用 mark(),然后從輸入流中讀取下一個輸入:

buf 的索引位置 k 到 n-1 的字節被寫入索引位置 0 到 nk-1,並且在從 nk 到 n-1 的索引處寫入新數據,並且 pos 的值(下一個字節的索引位置be read in buf) 變為 n-k+1,因為此時新添加的數據中的一個字節已被讀取。

對於長度為 n < 標記限制的內部緩沖區:

在讀取了 n+k 個字節並且即將讀取第 (n+k+1) 個字節后,將創建一個長度為 marklimit 的新緩沖區。

我知道這是一個很長的解釋,但認為如果他們遇到這個標記()和重置(),這可能對其他人有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM