基于bufferedreader的read()与readline()读取出错原因及解决
程序员文章站
2022-06-17 22:40:49
目录bufferedreader的read()与readline()读取出错bufferedreader中的readline()源码解析bufferedreader的read()与readline()...
bufferedreader的read()与readline()读取出错
以前学习java的时候也没有太在意,直到最近做项目时使用了才发现这个问题,总是第一个字符输不出来
bufferedreader这个类借用别人的话来说,就是一个包装类
它可以包装字符流,将字符流放入缓存里,先把字符读到缓存里,到缓存满了或者你flush的时候,再读入内存,就是为了提高读的效率而设计的。
读取一个txt文件,方法很多种而我使用的是字符流来读取
int c; filereader file = new filereader("d:\\emdemo.java"); bufferedreader br = new bufferedreader(file); while((c=br.read())!=-1){undefined system.out.println(br.readline()); }
发现每行的第一个字符都没有显示出来,后来发现 c=br.read())!=-1 每次都会先读取一个字节出来,所以后面的br.readline());
读取的就是每行少一个字节
所以,应该使用
string input = null; while ((input=br.readline())!=null){undefined system.out.println(input); }
这样就能解决了~
bufferedreader中的readline()源码解析
string readline(boolean ignorelf) throws ioexception { //行(hang)数据的缓冲s stringbuffer s = null; int startchar; synchronized (lock) { /*确保被bufferedreader包装的输入流没有关闭*/ ensureopen(); /* 如果 读到'\r',skiplf置为true, * 这是skip()方法里面的部分代码,它展示了通过skiplf来忽略'\n' * if (skiplf) { skiplf = false; if (cb[nextchar] == '\n') { nextchar++; } } *ignorelf一直就是false **/ boolean omitlf = ignorelf || skiplf; /* bufferloop主要是不断地遍历底层的数组cb,并取两个换行符之间的数据付给行缓冲s。当底层数组遍历完要用fill()把数据从流中填充到cb,直到流的末尾 *charloop,主要是遍历缓冲数组cb,以确定'\n','\r'的位置 nextchar:下次读取缓冲字符数组cb的位置, nchars:缓冲字符数组cb的length */ bufferloop: for (;;) { //1、如果缓冲数组的数据不足,或者已经读到了数组的末尾时: //1.1如果下次读取的位置已经到了or超过数组的长度,从流中读数据到缓冲数组cb中 if (nextchar >= nchars) fill(); /*1.2如果从流中读数据到数组cb之后, nextchar,nchars的大小关系没有改变. 说明到了文件的末尾,end of file.返回s */ if (nextchar >= nchars) { /* eof */ if (s != null && s.length() > 0) return s.tostring(); else return null; } //2 缓冲数组中有足够的数据时: /*从本个换行符所在的索引位置开始,遍历char [] cb ,直到找到\n \r,把两个换行符之间的字符序列填充进s *eol:end of line *类属性char [] cb ,也就是bufferreader类的缓冲数组。length由构造器指定,若不指定默认为8 * 1024 = 8192,与内存页大小密切相关 * */ boolean eol = false; char c = 0; int i; if (omitlf && (cb[nextchar] == '\n')) nextchar++; skiplf = false; omitlf = false; charloop: for (i = nextchar; i < nchars; i++) { c = cb[i]; if ((c == '\n') || (c == '\r')) { eol = true; break charloop; } } /*2.1找到换行符后,从上个换行符到本换行符之间的序列,填充给s*/ startchar = nextchar; nextchar = i; if (eol) { string str; /*2.1.1如果是第一次遍历到换行符,*/ if (s == null) { str = new string(cb, startchar, i - startchar); } /*2.1.2至少遍历到一次换行符时*/ else { s.append(cb, startchar, i - startchar); str = s.tostring(); } //更新下次读取的位置 nextchar++; if (c == '\r') { skiplf = true; } return str; } //2.2如果没有换行符 if (s == null) //类属性int defaultexpectedlinelength = 80 s = new stringbuffer(defaultexpectedlinelength); //填充s,从上个换行符到最后 s.append(cb, startchar, i - startchar); } } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。