JAVA中mark()和reset()用法


根據JAVA官方文檔的描述,mark(int readlimit)方法表示,標記當前位置,並保證在mark以后最多可以讀取readlimit字節數據,mark標記仍有效。如果在mark后讀取超過readlimit字節數據,mark標記就會失效,調用reset()方法會有異常。 
但實際的運行情況卻和JAVA文檔中的描述並不完全相符。 有時候在BufferedInputStream類中調用mark(int readlimit)方法后,即使讀取超過readlimit字節的數據,mark標記仍有效,仍然能正確調用reset方法重置。 

事實上,mark在JAVA中的實現是和緩沖區相關的。只要緩沖區夠大,mark后讀取的數據沒有超出緩沖區的大小,mark標記就不會失效。如果不夠大,mark后又讀取了大量的數據,導致緩沖區更新,原來標記的位置自然找不到了。

因此,mark后讀取多少字節才失效,並不完全由readlimit參數確定,也和BufferedInputStream類的緩沖區大小有關。 如果BufferedInputStream類的緩沖區大小大於readlimit,在mark以后只有讀取超過緩沖區大小的數據,mark標記才會失效。看下面的例子。 

?
<span style= "color: #ff0000;" >ava代碼
package packet1;  
   
import java.io.BufferedInputStream;  
import java.io.ByteArrayInputStream;  
import java.io.IOException;  
   
/** 
* @author WuDian 
*  
*/ 
public class MarkExample {  
     public static void main(String[] args) {  
   
         try {  
             // 初始化一個字節數組,內有5個字節的數據  
             byte [] bytes={ 1 , 2 , 3 , 4 , 5 };  
             // 用一個ByteArrayInputStream來讀取這個字節數組  
             ByteArrayInputStream in= new ByteArrayInputStream(bytes);  
             // 將ByteArrayInputStream包含在一個BufferedInputStream,並初始化緩沖區大小為2。  
             BufferedInputStream bis= new BufferedInputStream(in, 2 );   
             // 讀取字節1  
             System.out.print(bis.read()+ "," );  
             // 在字節2處做標記,同時設置readlimit參數為1  
             // 根據JAVA文檔mark以后最多只能讀取1個字節,否則mark標記失效,但實際運行結果不是這樣  
             System.out.println( "mark" );  
             bis.mark( 1 );  
                
             /* 
              * 連續讀取兩個字節,超過了readlimit的大小,mark標記仍有效 
              */ 
             // 連續讀取兩個字節  
             System.out.print(bis.read()+ "," );   
             System.out.print(bis.read()+ "," );   
             // 調用reset方法,未發生異常,說明mark標記仍有效。  
             // 因為,雖然readlimit參數為1,但是這個BufferedInputStream類的緩沖區大小為2,  
             // 所以允許讀取2字節  
             System.out.println( "reset" );  
             bis.reset();  
                
             /* 
              * 連續讀取3個字節,超過了緩沖區大小,mark標記失效。 
              * 在這個例子中BufferedInputStream類的緩沖區大小大於readlimit, 
              * mark標記由緩沖區大小決定 
              */ 
             // reset重置后連續讀取3個字節,超過了BufferedInputStream類的緩沖區大小  
             System.out.print(bis.read()+ "," );  
             System.out.print(bis.read()+ "," );  
             System.out.print(bis.read()+ "," );  
             // 再次調用reset重置,拋出異常,說明mark后讀取3個字節,mark標記失效  
             System.out.println( "reset again" );  
             bis.reset();  
         } catch (IOException e) {  
             // TODO Auto-generated catch block  
             e.printStackTrace();  
         }  
     }  
 
package packet1;
 
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
 
/**
* @author WuDian
*
*/
public class MarkExample {
         public static void main(String[] args) {
 
                 try {
                         // 初始化一個字節數組,內有5個字節的數據
                         byte [] bytes={ 1 , 2 , 3 , 4 , 5 };
                         // 用一個ByteArrayInputStream來讀取這個字節數組
                         ByteArrayInputStream in= new ByteArrayInputStream(bytes);
                         // 將ByteArrayInputStream包含在一個BufferedInputStream,並初始化緩沖區大小為2。
                         BufferedInputStream bis= new BufferedInputStream(in, 2 );
                         // 讀取字節1
                         System.out.print(bis.read()+ "," );
                         // 在字節2處做標記,同時設置readlimit參數為1
                         // 根據JAVA文檔mark以后最多只能讀取1個字節,否則mark標記失效,但實際運行結果不是這樣
                         System.out.println( "mark" );
                         bis.mark( 1 );
                         
                         /*
                          * 連續讀取兩個字節,超過了readlimit的大小,mark標記仍有效
                          */
                         // 連續讀取兩個字節
                         System.out.print(bis.read()+ "," );
                         System.out.print(bis.read()+ "," );
                         // 調用reset方法,未發生異常,說明mark標記仍有效。
                         // 因為,雖然readlimit參數為1,但是這個BufferedInputStream類的緩沖區大小為2,
                         // 所以允許讀取2字節
                         System.out.println( "reset" );
                         bis.reset();
                         
                         /*
                          * 連續讀取3個字節,超過了緩沖區大小,mark標記失效。
                          * 在這個例子中BufferedInputStream類的緩沖區大小大於readlimit,
                          * mark標記由緩沖區大小決定
                          */
                         // reset重置后連續讀取3個字節,超過了BufferedInputStream類的緩沖區大小
                         System.out.print(bis.read()+ "," );
                         System.out.print(bis.read()+ "," );
                         System.out.print(bis.read()+ "," );
                         // 再次調用reset重置,拋出異常,說明mark后讀取3個字節,mark標記失效
                         System.out.println( "reset again" );
                         bis.reset();
                 } catch (IOException e) {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
                 }
         }
}
</span>

  運行結果如下:

Java代碼 
1,mark   
2,3,reset   
2,3,4,reset again   
java.io.IOException: Resetting to invalid mark   
    at java.io.BufferedInputStream.reset(BufferedInputStream.java:416)   
    at packet1.MarkExample.main(MarkExample.java:51)  

1,mark
2,3,reset
2,3,4,reset again
java.io.IOException: Resetting to invalid mark
        at java.io.BufferedInputStream.reset(BufferedInputStream.java:416)
        at packet1.MarkExample.main(MarkExample.java:51)       同樣的,在調用mark(int readlimit)方法時,如果readlimit大於BufferedInputStream類緩沖區的大小,緩沖區會被擴大,那mark后最多就可以讀readlimit字節。
    
        簡言之,BufferedInputStream類調用mark(int readlimit)方法后讀取多少字節標記才失效,是取readlimit和BufferedInputStream類的緩沖區大小兩者中的最大值,而並非完全由readlimit確定。這個在JAVA文檔中是沒有提到的。

JAVA中mark()和reset()用法的通俗理解

mark就像書簽一樣,在這個BufferedReader對應的buffer里作個標記,以后再調用reset時就可以再回到這個mark過的地方。mark方法有個參數,通過這個整型參數,你告訴系統,希望在讀出這么多個字符之前,這個mark保持有效。讀過這么多字符之后,系統可以使mark不再有效,而你不能覺得奇怪或怪罪它。這跟buffer有關,如果你需要很長的距離,那么系統就必須分配很大的buffer來保持你的mark。    
    //eg.    
    //reader      is      a      BufferedReader    
      
    reader.mark(50);//要求在50個字符之內,這個mark應該保持有效,系統會保證buffer至少可以存儲50個字符    
    int      a      =      reader.read();//讀了一個字符    
    int      b      =      reader.read();//又讀了一個字符    
      
    //做了某些處理,發現需要再讀一次    
    reader.reset();    
    reader.read();//讀到的字符和a相同    
    reader.read();//讀到的字符和b相同


免責聲明!

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



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