A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 马甲大王 中级黑马   /  2013-3-13 22:32  /  4073 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张栓紧 于 2013-3-14 09:57 编辑
  1. import java.io.BufferedReader;
  2. import java.io.FileInputStream;
  3. import java.io.InputStreamReader;


  4. public class ReflectDemo2 {
  5.         public static void main(String[] args) throws Exception {        
  6.                 BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\1.txt")));
  7.                
  8.                 String str = null;
  9.                 while((str=br.readLine())!=null){
  10.                         System.out.println(str);
  11.                 }
  12.         }
  13. }
复制代码
1.txt的内容是
lisi
zhangsan
wangwu
maliu
zhaoqi
我想问的是zhaoqi后没有回车符,怎么str=br.readLine()能读到,而且打印出来了?


8 个回复

倒序浏览
它不为空,肯定可以打印出来
回复 使用道具 举报
李易烜 发表于 2013-3-13 22:54
它不为空,肯定可以打印出来

readLine()读取到回车符才会有数据啊。
回复 使用道具 举报
readLine() 的内部代码类似下面代码:
//
定义一个缓冲区
tringBuilder sb = new StringBuilder();
                     int ch = 0;
//文件结尾返回-1
                     while((ch=r.read())!=-1){
                            if(ch=='\r')
                                   continue;
                            if(ch=='\n')
                                   //如果读到换行符,则把缓冲区的内容转为字符串返回
                                   return sb.toString();
                            else
                                   //往缓冲区添加字符
                                  sb.append((char)ch);
                     }
                     //如果最后一行没有回车符也表读到未尾了,就把这些字符串返回去。
                     if(sb.length()!=0)
                            return sb.toString();
                     return null;

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
小路飞 来自手机 中级黑马 2013-3-14 01:01:32
报纸
谢洋 发表于 2013-3-13 23:58
readLine() 的内部代码类似下面代码:
//定义一个缓冲区tringBuilder sb = new StringBuilder();           ...

从本质找问题所在,又学到了一招,谢了!
回复 使用道具 举报
补充下楼上的这段代码说明:
readLine()的内部算法是这样的:readLine( )虽然是一次读一行,但是归根结底他还是封装了read( )方法,进行一次一个字符的读取。
关键点:(1)判断一行结束的条件:通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。最后一行的比较特殊列外。
我们要讨论的也就是最后一行的问题:
   ※假设我们就只有一行字符,while执行结束后ch的值是不可能为0与-1,所以sb字符缓冲里面肯定有值。接着进行如下的判断
   if(sb.length()!=0)
  return sb.toString();
        return null;
我们返回的值是sb.toString
假设文档是空的,就返回一个null

回复 使用道具 举报
本帖最后由 明锦添 于 2013-3-14 02:00 编辑

    private static int defaultCharBufferSize = 8192;//默认缓冲区大小

    /**
     * Creates a buffering character-input stream that uses an input buffer of
     * the specified size.
     *
     *  //使用指定的字符数创建一个缓冲字节输入流
     *
     * @param  in   A Reader
     * @param  sz   Input-buffer size
     *
     * @exception  IllegalArgumentException  If sz is <= 0
     */
    public BufferedReader(Reader in, int sz) {
        super(in);
        if (sz <= 0)
            throw new IllegalArgumentException("Buffer size <= 0");
        this.in = in;
        cb = new char[sz];
        nextChar = nChars = 0;
    }

/**
     * Reads a line of text.  A line is considered to be terminated by any one
     * of a line feed ('\n'), a carriage return ('\r'), or a carriage return
     * followed immediately by a linefeed.
     *
     *//读取一个文本行一条线由任何一个终止一个换行符('\n'),回车('\r'),或一个回车紧接着一个换行。
     *
     * @param      ignoreLF  If true, the next '\n' will be skipped
     *
     * @return     A String containing the contents of the line, not including
     *             any line-termination characters, or null if the end of the
     *             stream has been reached
     *
     *//一个字符串包含内容不包括任何线终止字符,或NULL,如果为null表示流已经读取末尾了。
     *
     * @see        java.io.LineNumberReader#readLine()
     *
     * @exception  IOException  If an I/O error occurs
     */
    String readLine(boolean ignoreLF) throws IOException {
        StringBuffer s = null;
        int startChar;

        synchronized (lock) {
            ensureOpen();
            boolean omitLF = ignoreLF || skipLF;

        bufferLoop:
            for (;;) {

                if (nextChar >= nChars)
                    fill();
                if (nextChar >= nChars) { /* EOF */
                    if (s != null && s.length() > 0)
                        return s.toString();
                    else
                        return null;
                }
                boolean eol = false;
                char c = 0;
                int i;

                /* Skip a leftover '\n', if necessary */
                if (omitLF && (cb[nextChar] == '\n'))
                    nextChar++;
                skipLF = false;
                omitLF = false;

            charLoop:
                for (i = nextChar; i < nChars; i++) {
                    c = cb;
                  
if ((c == '\n') || (c == '\r')) {
                        eol = true;
                        break charLoop;
                    }
                }

                startChar = nextChar;
                nextChar = i;

                if (eol) {
                    String str;
                    if (s == null) {
                        str = new String(cb, startChar, i - startChar);
                    } else {
                        s.append(cb, startChar, i - startChar);
                        str = s.toString();
                    }
                    nextChar++;
                    if (c == '\r') {
                        skipLF = true;
                    }
                    return str;
                }
               
                if (s == null)
                    s = new StringBuffer(defaultExpectedLineLength);
                s.append(cb, startChar, i - startChar);
            }
        }
    }
//仔细研究了一下io包中的BufferedReader 的readLine() 的源码,如上,因数代码太多还有一部分我没有贴出来,
我结合这些代码看了一下,发现ReadLine()的实现,实际上只是将文件以字符数组的形式读到字符缓冲区中,然后根据'\r','\n'来拆分字符数组,返回整行(返回的行里面不包含任何行结束标识)。 楼主的情况是这样的:你的文件字符比较小 ,所以将会被一次性被读取到字符缓冲数组中,
你的文件在字符缓冲数组中应该显示为:l i s i z h a n g s a n \r \n w a n g w u \r \n m a l i u \r \n z h a o q i 一共37个字符:29字符+4对'\r' '\n',(为了便于看,我在每个字符间加了一个空格)然后,实现从这个数组中从前往后遍历(代码中实现的是对有效字符的遍历,即从下标[0]~[36]之间的字符的遍历),在本例中,会在四个'\r'的地方截断字符,并返回一条字符串(以StringBuffer连接单个字符,最后以toString()的形式返回字符串),当遇到指定需要忽略或是已经跳过一个字符而且本次字符是'\n'时,再次跳过本字符 。
如此往复,当字符遍历到最后一个有效字符时终止,并把拼接好的字符串返回,由些可见楼主的最后一行能正常读出来,跟最后一行是否有回车/换行符没有任何关系的,只是因为它的有效字符读完了就结束(断行结束)了。
若文件比较大,它会先读文件填满缓冲区,遍历(取整行返回)缓冲区到最后一个字符时,再次去从文件中读取字符填满缓冲区,再遍历(取整行返回)... 直到文件读完为止。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
谢洋 发表于 2013-3-13 23:58
readLine() 的内部代码类似下面代码:
//定义一个缓冲区tringBuilder sb = new StringBuilder();           ...

谢谢啦!呵呵
回复 使用道具 举报
谢洋 高级黑马 2013-3-14 10:12:06
9#
张栓紧 发表于 2013-3-14 09:57
谢谢啦!呵呵

不用客气,哥是从笔记那里翻出来的
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马