2017-02-22 128 views
1

我是新來的Java流,我想讀一個特定的文件內容,然後需要從頭閱讀它。我已經創建了一個的BufferedInputStream,我感到困惑BufferedInputStream.mark(INT markLimit)的文檔什麼是在緩衝輸入流中使用標記讀取限制

文檔說:

public void mark(int readlimit) 

此方法標誌着在輸入到該流可以一位置通過調用reset()方法來「重置」。參數readlimit是在標記變爲無效之前設置標記之後可以從流中讀取的字節數。例如,如果調用mark()時讀取限制爲10,則在調用reset()方法之前從流中讀取11個字節的數據時,標記無效,並且不需要流對象實例記住標記。

請注意,此方法可以記住的字節數可能大於內部讀取緩衝區的大小。它也不依賴於支持標記/重置功能的從屬流。

覆蓋: 標誌類FilterInputStream

參數: readlimit - 可以在標記之前被讀取的字節數變爲無效**

我的代碼是:

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

     File resource = new File("beforeFix.txt");   
     FileInputStream fileInputStream = new FileInputStream(resource); 
     BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); 
     int i = bufferedInputStream.read(); 
     bufferedInputStream.mark(1); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     bufferedInputStream.reset(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     i = bufferedInputStream.read(); 
     bufferedInputStream.reset(); 
    } 
} 

在上面的代碼中,我將marklimit設置爲1,但標記不會根據文檔進入無效狀態。

任何人都可以清楚地解釋我什麼是用小例子設置此實際目的?

在此先感謝

+0

,它不會拋出的任何異常給我。根據文檔,標記在讀取第二個字節後應該是無效的,因爲我已將標記限制設置爲1,但事實並非如此。那麼這個標記()的目的是什麼? –

+0

對引用的文本使用引號格式。請把粗體裁掉。它傷害了我們的眼睛。 – EJP

回答

1

爲了復位工作,回到你標記的位置,你需要標記在內存中緩衝後讀取數據。標記時指定的值是應爲此保留的內存量。

因此,如果您打算在調用重置之前讀取100個字節,那麼您的緩衝區至少需要100個字節,因此您必須調用mark。

bufferedInputStream.mark(200); 

... read no more than 200 bytes ... 

bufferedInputStream.reset(); // reset back to marked position 

更新

它看起來像文檔mark不匹配的實際行爲。該文件指出:

the maximum limit of bytes that can be read before the mark position becomes invalid 

但是,它看起來像它應該是the minimum limit,或至少是潛在的實現並不要求儘快放棄了標記爲超過讀取限制,如果他們仍然可以支持復位到標記的位置。

+0

在上面的例子中(我已經提供了),我已經將標記限制設置爲1並且讀取多於一個的字節。根據文檔,標記在讀取第二個字節後應該是無效的,因爲我已將標記限制設置爲1,但事實並非如此。那麼這個標記()的目的是什麼? –

+0

我認爲你在這裏的文檔中發現了一個錯誤,即使這些文檔似乎暗示重置一旦超出限制就會失敗,這在實踐中並不會發生。我認爲他們打算說'最低限額'而不是'最高​​限額'。 – john16384

+0

「最低限度」沒有意義。當然,在調用reset()之前,您不需要讀取儘可能多的字節。 – Holger

0

通過調用mark指定的限制,您正在請求在讀取達到指定限制後支持重置的功能,但您並不否認超出該限制的功能。The specification明確表示:

然而,不需要流在所有如果超過readlimit字節從流中讀取reset調用之前,必須記住任何數據。

「不需要」不意味着「不允許」。規範只是說明你不能總是工作的東西,它沒有說明你可能總會失敗的東西。

BufferedInputStream的情況下,很容易解釋底下發生了什麼。每個BufferedInputStream都有一個容量,default是8192,它總是可以重置與當前緩衝區容量相同的字節數。通過指定一個更高的限制,你將會在需要的時候使它分配一個更大的緩衝區,以履行保證。

由於您無法查詢流的當前緩衝區容量,只能依賴重置的保證,只要您不讀取超過指定限制的字節。

可以很容易地改變你的榜樣,以使其失敗重複性:

當我打電話復位()
File resource = new File("beforeFix.txt");   
FileInputStream fileInputStream = new FileInputStream(resource); 
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, 1); 
int i = bufferedInputStream.read(); 
bufferedInputStream.mark(1); 
i = bufferedInputStream.read(); 
i = bufferedInputStream.read(); 
bufferedInputStream.reset(); // will fail 
+0

文檔還說這是:「在標記位置變爲無效之前可以讀取的字節的最大限制」,但它不成爲這是OP的問題,總是無效。它不會讀取「**可能**變得無效」。 – john16384

+0

@ john16384:概念上,標記*無效,因爲您不能依賴它。另一個問題是,會產生哪些後果。 [reset()'](https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html#reset--)的文檔清楚地表明:「如果...數量從最後一次調用mark'開始,從流中讀取的字節大於最後一次調用時標記爲'mark'的參數,那麼可能拋出一個'IOException' **。「您會看到」*可能是*「,不是「*保證是*」... – Holger

+0

好吧,這是一個很好的發現。 – john16384