黑马程序员技术交流社区

标题: 关于流的flush方法 [打印本页]

作者: 王少岩    时间: 2012-8-20 15:45
标题: 关于流的flush方法
各位大神们,请教一下,当一个流对象调用flush方法后,流中的数据会刷新到哪里?
BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(System.out);
bfw.write(line.toUpperCase());
bfw.newLine();
bfw.flush();//比如这句,如果不加的话,控制台会没有结果,按毕老师的话说,字符流只有刷新后才会显示结果,这个好理解一点,一刷新可以理解为就刷到控制台了

可是如果BufferedWriter bfw = new BufferedWriter(new FileWriter("test.txt"));的时候,执行flush方法的时候,流中的数据会到哪里啊?
因为我观察在程序整形过程中并没有创建文件(用的System.in,在输入over之前没有创建文件),程序结束后才创建的文件(输入over后,才在相应目录创建了文件)。
但是在程序运行过程中执行了多次的flush方法,这时不存在文件,那么执行flush方法后,流中的那些数据是存到哪里了呢?
最好还是讲讲flush的具体作用哈



作者: 刘芮铭    时间: 2012-8-20 15:53
flush()这个方法实质是将数据从数据流里面刷到目的地!
于是我们要清楚目的地在哪里?
1.如果目的地在控制台,那么刷到控制台上并显示!
2如果目的地是一个文件,那么是将数据刷到文件中!
于此同时close()这个方法可以在关闭流的同时刷一次数据!

作者: 刘圣伟    时间: 2012-8-20 16:22
flush ()方法,是把流中的(内存中)的数据,刷新到目的地。
当你没有执行,flush方法的,时候,其实数据,暂时是在内存中的。

关闭方法中,只有。write,有刷新操作,
在Reader的,close方法中,没有刷操作
作者: 杜鹏云    时间: 2012-8-20 16:41
本帖最后由 杜鹏云 于 2012-8-20 16:46 编辑

关于你的疑问 ,我们首先看一下JDK中的解释
首先我们来看看writer中的flush()

public abstract voidflush ()throws{}。。

刷新该流的缓冲。如果该流已保存缓冲区中各种 write() 方法的所有字符,则立即将它们写入预期目标。然后如果该目标是另一个字符或字节流,则将其刷新。因此,一次 flush() 调用将刷新 Writer 和 OutputStream 链中的所有缓冲区。 如果此流的预期目标是由底层操作系统提供的一个抽象(如一个文件),则刷新该流只能保证将以前写入到流的字节传递给操作系统进行写入,但不保证能将这些字节实际写入到物理设备(如磁盘驱动器)。


BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(System.out));
这句话调用bfw.flush(),将先刷新new BufferedWriter()中的缓冲区,然后再刷新new OutputStreamWriter(),
因为system.out表示“标准”输出流。此流已打开并准备接受输出数据。通常,此流对应于显示器输出或者由主机环境或用户指定的另一个输出目标。其本身public static final   PrintStream类型,与其他输出流不同,PrintStream 永远不会抛出 IOException;而是,异常情况仅设置可通过 checkError 方法测试的内部标志。另外,为了自动刷新,可以创建一个 PrintStream;这意味着可在写入 byte 数组之后自动调用 flush 方法,可调用其中一个 println 方法,或写入一个换行符或字节 ('\n')。 所以你外部bfw.flush(),他会自动刷新到控制台。


BufferedWriter bfw = new BufferedWriter(new FileWriter("test.txt"));而这个bfw.flush()其中bfw的预期目的是个文件,所以刷新该流只能保证将以前写入到流的字节传递给操作系统进行写入,但不保证能将这些字节实际写入到物理设备(如磁盘驱动器)。等你调用close()方法时,才会关闭所有的资源,操作系统自动将这些数据存入到对应的物理设备中,即你的test.txt中。

希望我的解答对你有用!!!

作者: 牛杨    时间: 2012-8-20 17:09
本帖最后由 牛杨 于 2012-8-20 17:11 编辑

关于flush方法的问题 。我建议楼主最好看看关于这些流对象的源代码。像我这么笨的人都能看懂,我相信楼主也一定行的
对于flush方法。我的理解总结就是:flush方法就是对那些有缓冲区的写入流对象来说的刷新才有效果,但是写程序的时候并非得一定要调用flush方法。当你使用写入流对象完毕的时候,你只需要调用其close方法即可,而不必非得调用其flush。(因为在调用close方法的时候这个方法里面就先调用了flush。)

……
BufferedWriter bfw = new BufferedWriter(new FileWriter("test.txt"));的时候,执行flush方法的时候,流中的数据会到哪里啊?
首先要纠正楼主一下:只要执行了bfw.flush方法 。就应该创建test.txt 文件的。我验证过的。
对于这个问题 需要弄清楚这里的两个缓冲区:
在写这句new FileWriter("test.txt") 的时候, 这个(是个字符数组)注意:这个流里面的缓冲区并不是为了提高效率的 ,而是为了字符流的编码需要。
而写 new BufferedWriter(new FileWriter("test.txt"));的时候,这个BufferedWriter里面也有缓冲区(也是个字符数组)注意:这个缓冲区才是为了提高写入流的效率而创建的。
并且 FileWriter里面有个缓冲区要比BufferedWriter里面也有缓冲区要大得多。
所以在程序运行过程中执行了多次的flush方法的时候,其实是先刷新了BufferedWriter里面的缓冲区,把这个缓冲区里面的数据都刷到了 FileWriter的缓冲区 里面 。然后紧接着刷新FileWriter里面的缓冲区 ,把这个缓冲区里面数据都写到了test.txt文件中。所以在刷新这个缓冲区的时候,必须创建了文件test.txt 。
这也就是执行flush后 数据的流向了 。
希望对楼主有帮助哦! 如果楼主还有什么疑问 欢迎提出。
作者: 王少岩    时间: 2012-8-20 17:35
牛杨 发表于 2012-8-20 17:09
关于flush方法的问题 。我建议楼主最好看看关于这些流对象的源代码。像我这么笨的人都能看懂,我相信楼主也 ...

可是我确定在我输入over之后文件夹里面才出现的文件,这咋解释
作者: 牛杨    时间: 2012-8-20 17:43
王少岩 发表于 2012-8-20 17:35
可是我确定在我输入over之后文件夹里面才出现的文件,这咋解释

你确定么?  我按照你的要求 把你代码补充完整了,然后运行了一遍 在没有输入over的时候就创建了文件。
你把你的代码发过了 我看看
作者: 王少岩    时间: 2012-8-20 17:44
  1. import java.io.*;
  2. import java.util.*;

  3. class Student implements Comparable<Student>
  4. {
  5.         private String name;
  6.         private int ma;
  7.         private int cn;
  8.         private int en;
  9.         private int sum;

  10.         Student(String name,int ma,int cn,int en)
  11.         {
  12.                 this.name = name;
  13.                 this.ma = ma;
  14.                 this.cn = cn;
  15.                 this.en = en;
  16.                 sum = ma + cn + en;
  17.         }

  18.         public String getName()
  19.         {
  20.                 return name;
  21.         }

  22.         public int getSum()
  23.         {
  24.                 return sum;
  25.         }

  26.         public int compareTo(Student s)
  27.         {
  28.                 int num = new Integer(this.sum).compareTo(new Integer(s.sum));
  29.                 if(num==0)
  30.                         return this.name.compareTo(s.name);
  31.                 return num;
  32.         }

  33.         public int hashCode()
  34.         {
  35.                 return name.hashCode()+sum*34;
  36.         }

  37.         public boolean equals(Object obj)
  38.         {
  39.                 if(!(obj instanceof Student))
  40.                         throw new ClassCastException("类型不匹配");

  41.                 Student s = (Student)obj;

  42.                 return this.name.equals(s.name) && this.sum==s.sum;
  43.         }

  44.         public String toString()
  45.         {
  46.                 return "student["+name+" ,"+ma+" ,"+cn+" ,"+en+"]";
  47.         }

  48. }

  49. class StudentTools
  50. {
  51.         public static Set<Student> getStus()throws IOException
  52.         {
  53.                 return getStus(null);
  54.         }
  55.         public static Set<Student> getStus(Comparator<Student> cmp)throws IOException
  56.         {
  57.                 BufferedReader bufr =
  58.                         new BufferedReader(new InputStreamReader(System.in));

  59.                 String line = null;
  60.                 Set<Student> stus = null;
  61.                 if(cmp==null)
  62.                         stus = new TreeSet<Student>();
  63.                 else
  64.                         stus = new TreeSet<Student>(cmp);
  65.                 while((line = bufr.readLine())!=null)
  66.                 {
  67.                         if(line.equals("over"))
  68.                                 break;
  69.                         String[] info = line.split(",");
  70.                         Student stu = new Student(info[0],Integer.parseInt(info[1]),
  71.                                                                                         Integer.parseInt(info[2]),
  72.                                                                                         Integer.parseInt(info[3]));
  73.                         stus.add(stu);
  74.                 }

  75.                 bufr.close();
  76.                 return stus;
  77.         }

  78.         public static void writeTofile(Set<Student> stus)throws IOException
  79.         {
  80.                 BufferedWriter bufw = new BufferedWriter(new FileWriter("stuInfo.txt"));

  81.                 for(Student stu : stus)
  82.                 {
  83.                         bufw.write(stu.toString()+"\t");
  84.                         bufw.write(stu.getSum()+"");
  85.                         bufw.newLine();
  86.                         bufw.flush();
  87.                 }
  88.                 bufw.close();
  89.         }
  90. }

  91. class StudentInfoTest
  92. {
  93.         public static void main(String[] args) throws IOException
  94.         {
  95.                 Comparator<Student> cmp = Collections.reverseOrder();
  96.                 Set<Student> st = StudentTools.getStus(cmp);
  97.                 StudentTools.writeTofile(st);
  98.         }
  99.        
  100. }
复制代码

作者: 王少岩    时间: 2012-8-20 17:46
牛杨 发表于 2012-8-20 17:43
你确定么?  我按照你的要求 把你代码补充完整了,然后运行了一遍 在没有输入over的时候就创建了文件。
...

贴上面了,瞅瞅
作者: 牛杨    时间: 2012-8-20 19:15
王少岩 发表于 2012-8-20 17:46
贴上面了,瞅瞅

我知道你为什么 在输入over后 才创建了文件了。
楼主这个函数 public static Set<Student> getStus(Comparator<Student> cmp)throws IOException 中 是获取 屏幕上你输入的内容然后 构造成student对象,然后再把这个student对象加入 …… 。
但是这里你只是把屏幕上的内容读取下来了 ,只要你这里不读取结束(就是你不输入over) 那么这个函数就一直执行下去。这个函数不执行结束,那么这个writeTofile 的函数就不会被执行,(也即不会向文件中写数据)也即就不会执行到 bufw.flush()了,所以就不会创建文件了。

其实楼主 还是这句话 :只要执行了bfw.flush方法 。就应该创建test.txt 文件的

如果楼主想在 输入over之前就创建文件 ,那么你就需要把writeTofile这个函数里面的内容移到 这个函数 public static Set<Student> getStus(Comparator<Student> cmp)throws IOException 中。也即使 你在屏幕上输入一条内容,就把这条内容写到这个文件中。
可以这样写:蓝色为所加代码
BufferedWriter bufw = new BufferedWriter(new FileWriter("stuInfo.txt"));
while((line = bufr.readLine())!=null)
{
     if(line.equals("over"))

          break;

    bufw.write(line);//每读取一条就向流bufw中写入一条
     bufw.newLine();
     bufw.flush();  
//每读取一条就把bufw中的一条刷到文件中去,这一步是在 输入over前就创建文件的 关键

     String[] info = line.split(",");

     Student stu = new Student(info[0],Integer.parseInt(info[1]),

     Integer.parseInt(info[2]),

     Integer.parseInt(info[3]));

     stus.add(stu);

}
bufr.close();
bufw.close();
return stus;


作者: 王少岩    时间: 2012-8-20 19:21
牛杨 发表于 2012-8-20 19:15
我知道你为什么 在输入over后 才创建了文件了。
楼主这个函数 public static Set getStus(Comparator cmp ...

是啊,真是这个问题,看来还得注重细节,写完代码应该好好的分析一下逻辑,谢谢
作者: 王少岩    时间: 2012-8-20 19:21
问题以解决
作者: 牛杨    时间: 2012-8-20 19:35
王少岩 发表于 2012-8-20 19:21
问题以解决

为啥子 版主不给我加分 ,都给你加了 ?:o
作者: 王少岩    时间: 2012-8-20 19:43
牛杨 发表于 2012-8-20 19:35
为啥子 版主不给我加分 ,都给你加了 ?

爱莫能助啊




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2