欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于BufferedReader的mark(int),mark()解惑

程序员文章站 2022-03-01 17:54:20
...

相信BufferedReader应该是大家所熟悉的一个操作类,但是其中的mark,reset方法,不知大家是否有过关注,
近日工作中碰到问题,不解,所以就Google并记录下来,给自己个记录,也希望与大家分享。
关于BufferedReader:

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->public   class  BufferedReader
extends  Reader

Read text from a character
- input stream, buffering characters so as to provide  for  the efficient reading of characters, arrays, and lines.

The buffer size may be specified, or the 
default  size may be used. The  default  is large enough  for  most purposes.

In general, each read request made of a Reader causes a corresponding read request to be made of the underlying character or 
byte  stream. It is therefore advisable to wrap a BufferedReader around any Reader whose read() operations may be costly, such as FileReaders and InputStreamReaders. For example,

 BufferedReader in
   
=   new  BufferedReader( new  FileReader( " foo.in " ));
 

will buffer the input from the specified file. Without buffering, each invocation of read() or readLine() could cause bytes to be read from the file, converted into characters, and then returned, which can be very inefficient.

Programs that use DataInputStreams 
for  textual input can be localized by replacing each DataInputStream with an appropriate BufferedReader.

Since:
    JDK1.
1
See Also:
    FileReader, InputStreamReader



关于它的mark,reset方法:

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->mark

public   void  mark( int  readAheadLimit)
          
throws  IOException

    Mark the present position in the stream. Subsequent calls to reset() will attempt to reposition the stream to 
this  point.

    Overrides:
        mark in 
class  Reader

    Parameters:
        readAheadLimit 
-  Limit on the number of characters that may be read  while  still preserving the mark. After reading  this  many characters, attempting to reset the stream may fail. A limit value larger than the size of the input buffer will cause a  new  buffer to be allocated whose size is no smaller than limit. Therefore large values should be used with care. 
    Throws:
        IllegalArgumentException 
-  If readAheadLimit is  <   0  
        IOException 
-  If an I / O error occurs

 

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->reset

public   void  reset()
           
throws  IOException

    Reset the stream to the most recent mark.

    Overrides:
        reset in 
class  Reader

    Throws:
        IOException 
-  If the stream has never been marked, or  if  the mark has been invalidated


在项目中有如下代码:

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->     protected   static  String readToTag(BufferedReader br)
    {
        String string 
=   "" ;
        
try
        {
            br.mark(
9 );
            
int  charVal  =  br.read();
            
            
while  (charVal  !=   ' < '   &&   ! isFileEnd(br))
            {
                
if (charVal  ==   ' \r ' ){
                        currentLineNo 
++ ;
                }
                
                string 
+=  ( char )charVal;
                br.mark(
9 );
                charVal 
=  br.read();
            }

            br.reset();
            
if  (isFileEnd(br)  &&  charVal > 0 )
            {
                string 
+=  ( char )charVal;
            }

            
return  (string);
        }
        
catch  (IOException ioe)
        {
            Message.show(Message.error, ioe.getMessage());
            
return  ( null );
        }
    }


其功能是:在html文件解析中,读取当前BufferedReader至第一个tag。
其实,BufferedReader的功能是有很多用处的,比如统计文件行数,在html中读取发现tag后再将文件指针返回指向tag前面的位置;
1.在上面的code中,我查阅后(原作者已离职)的理解是:此处就是要在当前处mark一下,读取下一个char后,判断是否'<' ,重复画线处,直到发现'<',然后返回tag前的文本;则此处的9(就是这个9害我思索许久),不一定是9,可以是8,7...2,后面只读一次就又mark了; 1不行(后面讨论)。
2.在文件读取中,使用mark方法时,要注意,要设置mark参数int readAheadLimit=file.length + 1,否则就会爆出异常java.io.IOException: Mark invalid.
原因在于:

jdk中声明:
readAheadLimit - Limit on the number of characters that may be read while still preserving the mark. After reading this many characters , attempting to reset the stream may fail. A limit value larger than the size of the input buffer will cause a new buffer to be allocated whose size is no smaller than limit. Therefore large values should be used with care.

英文声明可能有些confused,来看中文的:
readAheadLimit - 在仍保留该标记的情况下,对可读取字符数量的限制。在读取达到或超过此限制的字符 后,尝试重置流可能会失败。限制值大于输入缓冲区的大小将导致分配一个新缓冲区,其大小不小于该限制值。因此应该小心使用较大的值。 //就是建议使用大于最大值的值

给大家一段代码可以参考运行:

<!-- <br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->import  java.io.BufferedReader;
import  java.io.CharArrayReader;
import  java.io.IOException;

public   class  BufferedReaderDemo {
    
public   static   void  main(String[] args)  throws  IOException {
        String s 
=   " Message.show(Message.error, ioe.getMessage()).一 " ;
        
char  buf[]  =   new   char [s.length()];
        s.getChars(
0 , s.length(), buf,  0 );
        CharArrayReader in 
=   new  CharArrayReader(buf);
        BufferedReader f 
=   new  BufferedReader(in);
        String d 
=   "" ;
        
int  c;
        System.out.println(s.length() );
        f.mark(s.length() 
+ 1 );
        
while  ((c  =  f.read())  !=   - 1 ) {
            d 
+=  ( char )c;
        }
        f.reset();
        System.out.println(d);
    }
}