OutputStreamWriter, PrintWriter, BufferedWriter, FileWrite, PrintStream

一、OutputStreamWriter, PrintWriter, BufferedWriter
先看一个示例,当然实际不会这么用,这里只是说明一下三者的区别。

import  java.io.*;
 
public  class  WriterDemo 
{
     public  static  void  main(String[] args) 
     {
         OutputStreamWriter osw= null ;
         PrintWriter pw= null ;
         BufferedWriter bw= null ;
         try {
             osw= new  OutputStreamWriter( new  FileOutputStream( "c:/write.txt" , true ), "GBK" );
             pw= new  PrintWriter( "c:/write.txt" , "GBK" );
             bw= new  BufferedWriter( new  FileWriter( "c:/write.txt" , true ));
             String str= "9.    分别使用OutputStreamWriter、PrintWriter和BufferedWriter" ;
             String str2= "类将三行字符串写入到文本文件中," ;
             String str3= "仔细分析有何差别" ;
 
             String str4= "youedkdkdkdkdlkaldalelrladl" ;
             String str5= "youedkdkdkdkdlkaldalelrladl" ;
             String str6= "youedkdkdkdkdlkaldalelrladl" ;
 
             String str7= "ssssssssssssssssssdtfwserewdd" ;
             String str8= "ssssssssssssssssssdtfwserewdd" ;
             String str9= "ssssssssssssssssssdtfwserewdd" ;
 
             pw.println(str);
             pw.println(str2);
             pw.println(str3);
             
             osw.write(str4+ "\r\n" );
             osw.write(str5+ "\r\n" );
             osw.write(str6+ "\r\n" );
             
             bw.write(str7);
             bw.newLine();
             bw.write(str8);
             bw.newLine();
             bw.write(str9);
 
             
         }
         catch (UnsupportedEncodingException e){
             e.printStackTrace();
         }
         catch (IOException e){
             e.printStackTrace();
         }
         finally {
             if (osw!= null )
             try {
                 osw.close();
             } catch (IOException e){}
 
             if (pw!= null )
                 pw.close();
 
             if (bw!= null )
             try {
                 bw.close();
             } catch (IOException e){}
         }
     }
}


(1)只有pw 和osw 写时  只写如了 pw
(2)只有osw和bw写时  两个都有写入
(3)三个都写入时 只有pw 和bw写入

这是怎么回事 我看了API 没看明白 
这三个有什么区别  当然他们构造不同之类的 接受的参数不同 这些我已经看过API里看到了 还有别的吗

Thanks! 


看了看源码
这三个类都继承于抽象类Writer
而且不管是pw.println() osw.write() bw.write()
实际上调用的都是父类Writer的方法public void write(String str, int off, int len)
也就是说 全部调用的是同一个方法
就是下面这个方法 这个方法是同步的

     public  void  write(String str,  int  off,  int  len)  throws  IOException {
     synchronized  (lock) {
         char  cbuf[];
         if  (len <= writeBufferSize) {
         if  (writeBuffer ==  null ) {
             writeBuffer =  new  char [writeBufferSize];
         }
         cbuf = writeBuffer;
         else  {     // Don't permanently allocate very large buffers.
         cbuf =  new  char [len];
         }
         str.getChars(off, (off + len), cbuf,  0 );
         write(cbuf,  0 , len);
     }
     }
在构造PrintWriter的时候 实际内部调用了另一个构造函数
就是这个

public  PrintWriter(String fileName)  throws  FileNotFoundException {
     this ( new  BufferedWriter( new  OutputStreamWriter( new  FileOutputStream(fileName))),
          false );
     }
也就是说PrintWriter用的是BufferedWriter的write()方法 而这个方法又调用父类Writer的方法
OutputStreamWriter的write()方法直接调用父类的方法, 所以都是用的同一个方法。

因为Writer里的write(cbuf, 0, len)是个抽象方法; 所以还是有些区别

实际上他们调用的这个write(cbuf, 0, len)的实现 都是OutputStreamWriter里的实现
但是在BufferedWriter里做了点扩展 有了自动刷新缓冲区的功能,其他大概都差不多。


“Buffered的作用,就是缓冲,也就是数据只有在flush或者close得时候才会写入。 ”
这句话也可以说正确 flush不一定是手动 也可能是自动,当要写入的数据大于它默认的容量 它就会自动flush
但不是只有Buffered能缓冲 其实其他流也是一样 也能自动flush。

Buffered的缓冲 实际上缓冲的是N个write()的内容。而其他流的缓冲 缓冲的是1个write()或print()的内容。


当没有设置自动提交时,在楼主的代码中这三个流都是在close()的时候才写入文件,所以顺序应该是osw>pw>bw,

楼主的代码在创建ows和bw时都带了参数true,造成了这两个流在写文件时只是往文件末尾添加内容,而pw则不同,在pw=new PrintWriter("c:/write.txt","GBK")一句执行时,文件的内容会被清空,而在pw.close()执行时,pw也会把文件清空,然后把自己的内容写进文件,这就是为什么osw总是写不进去的原因,至于楼主说的“我在每一写入后面加一个flush() 那所有的都会写入”是因为你加了flush的话,流就会在flush()的时候写入文件,写入的顺序就变成了pw>osw>bw,而后两个流都不覆盖,所以都写进去了,但是当你再次执行这个程序的话pw=new PrintWriter("c:/write.txt","GBK")又会把文件清空,所以文件内容没有变化。

二、看一下PrintWrite和FileWrite的区别

java.io 
Class FileWriter
java.lang.Object
  |
  +--java.io.Writer
        |
        +--java.io.OutputStreamWriter
              |
              +--java.io.FileWriter

public class FileWriter
Convenience class for writing character files. The constructors of this class assume that the default character encoding and the default byte-buffer size are acceptable. To specify these values yourself, construct an OutputStreamWriter on a FileOutputStream. 

java.io 
Class PrintWriter
java.lang.Object
  |
  +--java.io.Writer
        |
        +--java.io.PrintWriter

public class PrintWriter
Print formatted representations of objects to a text-output stream. This class implements all of the print methods found in PrintStream. It does not contain methods for writing raw bytes, for which a program should use unencoded byte streams. 

写文件最佳组合
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(filename)))
PrintWriter 提供print系方法
BufferedWriter 提供缓冲,用以加速
FileWriter 用于写文件

PrintStream类和PrintWriter类 

、PrintWriter与PrintStream

区别1:

PrintStream类和PrintWriter类 

PrintStream主要操作byte流,而PrintWriter用来操作字符流。读取文本文件时一般用后者。

java的一个字符(char)是16bit的,一个BYTE是8bit的 
PrintStrean是写入一串8bit的数据的。 
PrintWriter是写入一串16bit的数据的。 
String缺省是用UNICODE编码,是16bit的。因此用PrintWriter写入的字符串,跨平台性好一些吧。 
PrintStream的可能会出现字符集乱码吧。

PrintStream是用来操作byte, 
PrintWriter是用来操作Unicode, 
一般需要处理中文时用PrintWriter好了

Stream用于二进制文件(非文本) 
Writer/Reader用于文本文件(虽然也是二进制,不过是按照一定的字符编码规则,不像前者) 
当然Stream也可用于文本,只不过比writer/reader来的麻烦 

PrintStream主要操作byte流,而PrintWriter用来操作字符流。读取文本文件时一般用后者。

区别2:

 java 输出流中的PrintStream 和 PrintWriter有什么区别,好像很多场合都能混用
比如用于网络间通信,发送消息时,可用PrintStream 也可用 PrintWriter
    eg:
         Socket client;
          PrintStream output = new PrintStream(client.getOutputStream());
          output.println("aaa");
          output.flush();
        把上例中的 PrintStream 换成 PrintWriter效果是一样的。Java I/O流分为两类,字节流和字符流。字节流是指InputStream/OutputStream及其子类,字符流是指Reader/Writer及其子类。这两类I/O流的class hierarchy基本上是对等的,InputStreamReader/OutputStreamWriter是InputStream/OutputStream和Reader/Writer之间的桥梁。

         PrintStream是OutputStream的子类,PrintWriter是Writer的子类,两者处于对等的位置上,所以它们的API是非常相似的。PrintWriter实现了Writer的所有print方法。对于PrintStream,所有println方法都在内部调用相应的print方法,比如println(char x)的方法体就是调用print(x);再写入一个平台相关的换行符。PrintStream构建时会在内部new一个BufferedWriter,所有print方法都在内部调用这个Writer的write方法(write(String)或write(char[]))——对于print(char[]),直接调用write(char[]);对于其他的print方法,先用String.valueOf获得参数的字符串表示,然后调用write(String)。
         对于PrintWriter,所有println方法也都在内部调用print方法,然后再调用一个没有参数的println()来换行,print方法调用write方法。传入OutputStream时,PrintWriter会在内部构造一个BufferedWriter;而传入Writer时,PrintStream内部直接使用该Writer,此时PrintWriter是否进行了缓冲全看该Writer。
所以,对于使用print系列方法的场合,二者没什么区别。

         但是,PrintStream是字节流,它有处理raw byte的方法,write(int)和write(byte[],int,int);PrintWriter是字符流,它没有处理raw byte的方法。PrintStream和PrintWriter的auto flushing机制有点不同,前者在输出byte数组、调用println方法、输出换行符或者byte值10(即\n)时自动调用flush方法,后者仅在调用println方法时发生auto flushing。


区别3:

PrintStream类是过滤器类中一个不可忽视的成员,最基本的标准输出就要借助于它——我们常用的System.out变量就是PrintStream实例。与之对应的字符流类是PrintWriter类。 
  PrintStream有两个构造函数(在新版API中已标记为过时): 
  ■public PrintStream(OutputStream out) 
  ■public PrintStream(OutputStream out,boolean autoFlush) 
其中,autoFlush置为true时,每当输出遇到换行符,缓冲区的内容就被强制全部输出,如同调用了一次flush()。但要注意,如果没遇到换行符,还是会有数据“憋”在缓冲区里。 
  方法(已熟悉的就不解释): 
  ■public void write(int b) 
  ■public void write(byte b,int offset,int length) 
  ■public void flush() 
  ■public void close() 
  ■public void print(Object obj) 
  这个方法功能是 非常强大的,它可以输出任何对象,而不必另加说明。此外print()方法有许多重载形式,即有多种参数。它们是字符串(String)、字符数组 (char[])、字符(char)、整数(int)、长整数(long)、浮点数(float)、双精度浮点数(double)、布尔值 (boolean)。其中,输出多个数单位的print()方法(也就是指参数为String和char[]的)是同步(synchronized)方 法。 
  ■public void println()输出一个换行符。 
  ■public synchronized void println(Object obj) 
  println()方法有9个重载形式,几乎就是print()方法的翻版。唯一的区别在于println()方法都是同步的。 
  ■public boolean checkError() 
  检查输出过程中有什么错误,如有,返回true值。只要输出流中出现一次错误,则出错后的任意对checkError()的调用均会返回真值。 
  下面介绍PrintWriter类。 
  如同第二节中所说,PrintWriter是JDK1.1版增加了与字节流I/O相对应的字符流I/O。但是,为了保持兼容性,原先的类几乎没有改 动。再加之调试的需要,PrintStream类被保留,并且System类中的成员变量out、err仍作为它的对象。然而,PrintWriter用 于大多数输出比PrintStream更为合适。因此1.1版的API中建议新开发的代码使用PrintWriter类,并将 PrintStream类的两个构造函数标记为过时。这样,虽然使用System.out输出不会产生问题,在程序中创建新的PrintStream对象 时却会产生编译时的警告。 
  PrintWriter类与PrintStream类的方法是对应的。有一个不同之外需提请读者注意,就是当前者的自动清空缓冲区的功能被使能时(构 造函数中autoFlush置为true),仅当println()方法被调用时才自动清缓冲区,而不是像PrintStream一样遇到一个换行符就清 缓冲。 PrintStream,它可以将Java的基本资料型态等资料,直接转换为系统预设编码下对应的字元,再输出至OutputStream中,而这边要介 绍的 PrintWriter其功能上与PrintStream类似,除了接受OutputStream之外,它还可以接受Writer物件作为输出的对象,当 您原先是使用Writer物件在作处理 ,而现在想要套用println()之类的方法时,使用PrintWriter会是比较方便的作法。 

下面这个程式显示了PrintStream与PrintWriter两个物件在处理相同输出目的时的作法,程式将会在荧幕上显示 "简体中文" 四个字元: 

[java]  view plain  copy
 print ?
  1. StreamWriterDemo.java   
  2. package onlyfun.caterpillar; import java.io.*;   
  3. public class StreamWriterDemo   
  4. {  
  5.   
  6.  public static void main(String[] args)  {   
  7.   
  8. try  {  
  9.   
  10. byte[] sim = {(byte)0xbc, (byte)0xf2// 简   
  11. (byte)0xcc, (byte)0xe5// 体   
  12. (byte)0xd6, (byte)0xd0// 中   
  13. (byte)0xce, (byte)0xc4}; // 文   
  14. InputStreamReader inputStreamReader = new InputStreamReader(new ByteArrayInputStream(sim), "GB2312");   
  15. PrintWriter printWriter =new PrintWriter(new OutputStreamWriter(System.out, "GB2312"));   
  16. PrintStream printStream =new PrintStream(System.out, true"GB2312");   
  17. int in;   
  18. while((in = inputStreamReader.read()) != -1)  {  
  19.   
  20. printWriter.println((char)in);   
  21.   
  22. printStream.println((char)in);  
  23.   
  24. }   
  25. inputStreamReader.close();   
  26. printWriter.close();   
  27. printStream.close();   
  28.   
  29. }   
  30. catch(ArrayIndexOutOfBoundsException e)  {  
  31.   
  32.  e.printStackTrace();  
  33.   
  34.  }   
  35. catch(IOException e) {  
  36.   
  37.  e.printStackTrace();   
  38.   
  39. }   
  40.   
  41. }  
  42.   
  43. }   


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值