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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© ysdolls 中级黑马   /  2014-8-5 23:30  /  2356 人查看  /  18 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 ysdolls 于 2014-8-8 08:55 编辑

老毕写错了?io流MyBufferedReaderDemo 第19天 第五个视频12分20秒运行的程序
看的时候就感觉输出应该重复了 readline应该是调用一次读一行 如读取数据为:
abcd1
abcd2
abcd3
则调用三次readline 不加换行的话输出应为:
abcd1abcd2abcd3
加了就和读取的一样
老毕视频里也确实对了,和读取内容一样是三行,可发出来的源代码运行后却不是这样输出的 如下:
asdk1
asdk1asdk2
asdk1asdk2asdk3
asdk1asdk2asdk3asdk4
asdk1asdk2asdk3asdk4asdk5
因为每次读数据都没清空StringBuilder 所以每次输出都带着之前所有读过的 虽然源代码老毕进行了 继承 重写代码的完善 可主要功能部分没有变,为何视频里输出正确,而相同代码再运行却出现了这样的情况呢?
有大神能来分析一下 数据读取的过程嘛?总结问题如下:
1.我不明白了,StringBuilder是在方法里定义的,应该每次调用 都new了一个StringBuilder,都是不同的StringBuilder,可为什么输出的sb一直带有之前读取的?
2.sun的readLine是一个数组一个数组的读一行数据到内存中。然后write方法通过write调用flush()方法将内存中的数据存入文件。而老毕的是一个字符一个字符的读到内存中来凑够一行。根本和直接调用read方法是一样的,重写readline没有了意义。
3.我看了一下String line 每次指向的字符串如下:
asdk1
asdk1asdk2
asdk1asdk2asdk3
asdk1asdk2asdk3asdk4
asdk1asdk2asdk3asdk4asdk5
所以 String line 每次被赋予的字符串就是 方法每次被调用返回的字符串。很明显 方法内部 的StringBuilder  sb =new StringBuilder();每次都是一个对象没有新的引用覆盖。
请大神详细讲解数据的流向内存的步骤,学了一天 脑袋有点迷糊。
我用的是去深圳黑马领导的光盘里的内容 粘贴出程序如下:


  1. /*
  2. 明白了BufferedReader类中特有方法readLine的原理后,
  3. 可以自定义一个类中包含一个功能和readLine一致的方法。
  4. 来模拟一下BufferedReader
  5. */
  6. import java.io.*;
  7. class MyBufferedReader extends Reader
  8. {
  9.         
  10.         private Reader r;
  11.         MyBufferedReader(Reader r)
  12.         {
  13.                 this.r = r;
  14.         }

  15.         //可以一次读一行数据的方法。
  16.         public String myReadLine()throws IOException
  17.         {
  18.                 //定义一个临时容器。原BufferReader封装的是字符数组。
  19.                 //为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串。
  20.                 StringBuilder sb = new StringBuilder();
  21.                 int ch = 0;
  22.                 while((ch=r.read())!=-1)
  23.                 {
  24.                         if(ch=='\r')
  25.                                 continue;
  26.                         if(ch=='\n')
  27.                                 return sb.toString();
  28.                         else
  29.                                 sb.append((char)ch);
  30.                 }

  31.                 if(sb.length()!=0)
  32.                         return sb.toString();
  33.                 return null;               
  34.         }

  35.         /*
  36.         覆盖Reader类中的抽象方法。

  37.         */
  38.         public int read(char[] cbuf, int off, int len) throws IOException
  39.         {
  40.                 return r.read(cbuf,off,len) ;
  41.         }

  42.         public void close()throws IOException
  43.         {
  44.                 r.close();
  45.         }
  46.         public void myClose()throws IOException
  47.         {
  48.                 r.close();
  49.         }
  50. }


  51. class  MyBufferedReaderDemo
  52. {
  53.         public static void main(String[] args) throws IOException
  54.         {
  55.                 FileReader fr = new FileReader("buf.txt");

  56.                 MyBufferedReader myBuf = new MyBufferedReader(fr);

  57.                 String line = null;

  58.                 while((line=myBuf.myReadLine())!=null)
  59.                 {
  60.                         System.out.println(line);
  61.                 }

  62.                 myBuf.myClose();
  63.         }
  64. }
复制代码





评分

参与人数 1技术分 +1 收起 理由
格子、 + 1

查看全部评分

18 个回复

倒序浏览
好像是吧
回复 使用道具 举报

好像是什么。。。我不明白老毕那个程序为什么输出对了,我明明运行的是原装的程序啊
回复 使用道具 举报
本帖最后由 masai158 于 2014-8-5 23:45 编辑

StingBuilder 写入的时候,还记得写一个换行符。
我之前做了一个题,就是将一个文件的内容反转过来。然后在反转回去。。这里如果简单的写换行符的话会出问题。我先留个标记。明天去公司在上代码看看
回复 使用道具 举报
ysdolls 发表于 2014-8-5 23:42
好像是什么。。。我不明白老毕那个程序为什么输出对了,我明明运行的是原装的程序啊 ...

no。你肯定不对。你肯定写错了。好好看看
回复 使用道具 举报
本帖最后由 masai158 于 2014-8-5 23:57 编辑
ysdolls 发表于 2014-8-5 23:42
好像是什么。。。我不明白老毕那个程序为什么输出对了,我明明运行的是原装的程序啊 ...

你每写出一次。记得将缓冲区清空吧sb.delete(0,sb.length())
回复 使用道具 举报
masai158 发表于 2014-8-5 23:55
你每写出一次。记得将缓冲区清空吧sb.delete(0,sb.length())

老毕就没有清,为什么他的运行对了?我俩的是一样的程序
回复 使用道具 举报
有时候我也觉得老毕写错了,为什么他的可以运行,我的却不可以,到最后才发现原来是我的其他位置不是字母错了,就是字符错了,细心就会发现的。
回复 使用道具 举报
ysdolls 发表于 2014-8-6 07:37
老毕就没有清,为什么他的运行对了?我俩的是一样的程序

asdk1
asdk1asdk2
asdk1asdk2asdk3
asdk1asdk2asdk3asdk4
asdk1asdk2asdk3asdk4asdk5

每次都出现上一次。肯定是你没有清。我记得老毕第一次 是没有清就是为了演示这个问题。然后最后清了就正常了。你清添加清楚?正常吗?
回复 使用道具 举报
  1. /**将一个文件中的内容倒序(不允许用第二个文件)*/
  2. import java.io.*;
  3. import java.util.*;
  4. class Test6
  5. {
  6.         public static void main(String[] args)         throws IOException
  7.         {
  8.                 String fileName = "Test6.txt";

  9.                 ArrayList<String> al = new ArrayList<String>();//使用一个容器来装每一段数据

  10.                 File fr = new File(fileName);

  11.                 fileToSb(fr,al); //将读取的到文件每一段数据都读到集合中

  12.                 alToFile(al,new File(fileName)); //将集合的每一段数据写到文件中

  13.         }

  14.         public static void fileToSb(File fr,ArrayList<String> al) throws IOException
  15.         {
  16.                 BufferedReader bufr =new BufferedReader(new FileReader(fr));
  17.                
  18.                 String flag ;

  19.                 while((flag=bufr.readLine())!=null)
  20.                 {
  21.                         al.add(flag);        //将每一行读取的信息保存到集合中
  22.                 }
  23.                 bufr.close();
  24.         }

  25.         public static void alToFile(ArrayList<String> al,File fw) throws IOException
  26.         {
  27.                 fw.delete();                //将源文件删掉

  28.                 BufferedWriter bufw = new BufferedWriter(new FileWriter(fw)); //创建一个文件

  29.                 for(int end=al.size()-1; end>=0; end--)
  30.                 {
  31.                         bufw.write(al.get(end).toString());
  32.                         bufw.newLine();
  33.                 }
  34.                 bufw.close();
  35.         }
  36. }
  37. 希望能帮助你
复制代码
回复 使用道具 举报
沐小北 发表于 2014-8-6 07:53
有时候我也觉得老毕写错了,为什么他的可以运行,我的却不可以,到最后才发现原来是我的其他位置不是字母错 ...

这个是复制老毕的代码。。。而且运行是成功的,只是结果不同
加一句 read没有flush方法,因为read不需要写入数据
回复 使用道具 举报
本帖最后由 ysdolls 于 2014-8-6 09:40 编辑
masai158 发表于 2014-8-6 08:09
asdk1
asdk1asdk2
asdk1asdk2asdk3

你记错了,我又重新看了一次,他确实没请,老毕也没演示过什么第一次没清,第二次清了,他倒是演示过newLine 和print_ln而且 为什么 这个程序没清 却可以结束? 不清不是sb里一直有数据?
asdk1
asdk1asdk2
asdk1asdk2asdk3
1.每次输出都带有之前的内容,所以每次调用MyReadLine都带有之前的数据
2.sb始终没清,那代表sb里始终有内容,而程序却可以结束,只有当返回null的时候才会结束while循环,而if(sb!=null)的话则一直有返回值,程序是怎么结束的呢?
3如果sb是每次调用MyReadLine都新建引用(也就是都清空),那应该是每次MyReadLine每次被调用,read()方法都是从文件最开始开始读,那他是怎么跳过if \r\n来返回两行如:asdk1asdk2,甚至3行的数据呢?
回复 使用道具 举报
ysdolls 发表于 2014-8-6 09:33
你记错了,我又重新看了一次,他确实没请,老毕也没演示过什么第一次没清,第二次清了,他倒是演示过newLi ...

我也记得他演示过错误的情况。。。我是看他写之前就自己写了一遍,我注意到了要清空的情况,所以写完之后看他第一次写没清就想他肯定要出错了,果不其然,后来他改过来了。
回复 使用道具 举报
老毕的视频中有一些错别字,但这都不是事

主要是跟着听就明白,那些错别字或者代码小错误大家明白就好了

高效率的打字难免有手误
回复 使用道具 举报
路过~~   
回复 使用道具 举报
没有清的话。我又回忆起了。好像他又new了一个 sb。。
回复 使用道具 举报
是我打开方式不对了吗。。。QAQ
回复 使用道具 举报
谁来讲解一下呀?为什么程序是这样输出的?
回复 使用道具 举报
路过,顶一帖
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马