黑马程序员技术交流社区

标题: 老毕讲的IO流中的一些技术点,个人摘录(二)。 [打印本页]

作者: 王永杰    时间: 2012-9-8 15:00
标题: 老毕讲的IO流中的一些技术点,个人摘录(二)。
二、
1.  BufferedWriter
java.io
类 BufferedWriter
java.lang.Object
java.io.Writer
java.io.BufferedWriter
所有已实现的接口:
Closeable, Flushable, Appendable
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,此概念由系统属性 line.separator 定义。并非所有平台都使用新行符 ('\n') 来终止各行。因此调用此方法来终止每个输出行要优于直接写入新行符。
通常 Writer 将其输出立即发送到基础字符或字节流。除非要求提示输出,否则建议用 BufferedWriter 包装所有其 write() 操作可能开销很高的 Writer(如 FileWriters 和 OutputStreamWriters)。例如,
PrintWriter out
   = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
将缓冲 PrintWriter 对文件的输出。如果没有缓冲,则每次调用 print() 方法会导致将字符转换为字节,然后立即写入到文件,而这是极其低效的。
2.  BuffereReader
java.io
类 BufferedReader
java.lang.Object
java.io.Reader
java.io.BufferedReader
所有已实现的接口:
Closeable, Readable
直接已知子类:
LineNumberReader
从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取。
可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
通常,Reader 所作的每个读取请求都会导致对基础字符或字节流进行相应的读取请求。因此,建议用 BufferedReader 包装所有其 read() 操作可能开销很高的 Reader(如 FileReader 和 InputStreamReader)。例如,
BufferedReader in = new BufferedReader(new FileReader("foo.in"));
将缓冲指定文件的输入。如果没有缓冲,则每次调用 read() 或 readLine() 都会导致从文件中读取字节,并将其转换为字符后返回,而这是极其低效的。
可以对使用 DataInputStream 进行按原文输入的程序进行本地化,方法是用合适的 BufferedReader 替换每个 DataInputStream。
3.  通过缓存区复制文本文件
public class CopyTextByBuf {
        /**
         * 通过缓冲区复制一个.java文件
         * @param args
         */
        public static void main(String[] args) {
                // TODO Auto-generated method stub
            BufferedReader bufr = null;
            BufferedWriter bufw = null;
            try{
                    bufr = new BufferedReader(new FileReader("BufferedWriterDemo.java"));
                    bufw = new BufferedWriter(new FileWriter("bufWriter_Copy.txt"));
                    String line = null;
                   
                    while ((line = bufr.readLine())!= null) {
                                bufw.write(line);
                                bufw.newLine();
                                bufw.flush();
                               
                        }
            }catch(IOException e){
                    System.out.print(e.toString());
                    throw new RuntimeException("读写失败!");
            }finally{
                    try{
                            if(bufr != null){
                                    bufr.close();
                            }
                }catch(IOException e){
                           
                            throw new RuntimeException("读取关闭失败!");
                    }
                try{
                            if(bufw != null){
                                    bufw.close();
                            }
                }catch(IOException e){
                           
                            throw new RuntimeException("写入关闭失败!");
                    }
            }
            
        }
       
}
4.  ReadLine 的原理图例
readLine
public String readLine()
throws IOException
读取一个文本行。通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。
返回:
包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
抛出:
IOException- 如果发生 I/O 错误
无论是读一行,或者读取多个字符,其实最终都是在硬盘上一个一个读取。所以最终使用的还是Read 方法一次读一个的方法。其实在内部是有一个封装好的数组,分配在内存中的。
5.  MybufferedReader
public class MybufferedReader {
        private FileReader r;
        public MybufferedReader(FileReader r) {
                // TODO Auto-generated constructor stub
                this.r = r;
        }
       
        public  String  MyReaderLine () throws IOException{
                //定义一个临时容器
                StringBuilder sBuilder = new StringBuilder();
                int ch = 0;
                while ((ch = r.read())!= -1) {
                        if(ch =='\r')
                        continue;
                        if(ch =='\n')
                        return sBuilder.toString();
                        else
                                sBuilder.append((char)ch);
                       
                }
                if(sBuilder.length()!= 0){
                        return sBuilder.toString();
                }
                return null;
        }
        public void MyClose() throws IOException{
                r.close();
        }
        /**
         * @param args
         * @throws IOException
         */
        public static void main(String[] args) throws IOException {
                // TODO Auto-generated method stub
                        FileReader  fr = new FileReader("buf.txt");
                        MybufferedReader mybuf = new MybufferedReader(fr);
                        String line = null;
                        while ((line = mybuf.MyReaderLine())!=null) {
                                System.out.print(line);
                        }
                        mybuf.MyClose();
        }
}

这是老毕讲的IO流第二阶段的一部分视频的内容。有时间把你们总结的内容也给我分享分享,我很希望看看大家从视频中都看到的有什么。





作者: 王永杰    时间: 2012-9-8 15:00
6.  装饰设计模式
java中装饰设计模式(decorator)
Decorator定义:
动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活.
为什么使用Decorator?
我们通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的.
使用Decorator的理由是:这些功能需要由用户动态决定加入的方式和时机.Decorator提供了"即插即用"的方法,在运行期间决定何时增加何种功能.
我们先建立一个接口:
public interface Work
{
  public void insert();
}
接口Work有一个具体实现:插入方形桩或圆形桩,这两个区别对Decorator是无所谓.我们以插入方形桩为例:
public class SquarePeg implements Work{
  public void insert(){
    System.out.println("方形桩插入");
  }
}
现在有一个应用:需要在桩打入前,挖坑,在打入后,在桩上钉木板,这些额外的功能是动态,可能随意增加调整修改,比如,可能又需要在打桩之后钉架子(只是比喻).
那么我们使用Decorator模式,这里方形桩SquarePeg是decoratee(被刷油漆者),我们需要在decoratee上刷些"油漆",这些油漆就是那些额外的功能.
public class Decorator implements Work{
  private Work work;
  //额外增加的功能被打包在这个List中
  private ArrayList others = new ArrayList();
  //在构造器中使用组合new方式,引入Work对象;
  public Decorator(Work work)
  {
    this.work=work;
  
    others.add("挖坑");
    others.add("钉木板");
  }
  public void insert(){
    newMethod();
  }

  
  //在新方法中,我们在insert之前增加其他方法,这里次序先后是用户灵活指定的   
  public void newMethod()
  {
    otherMethod();
    work.insert();


  }
  public void otherMethod()
  {
    ListIterator listIterator = others.listIterator();
    while (listIterator.hasNext())
    {
      System.out.println(((String)(listIterator.next())) + " 正在进行");
    }

  }
}
在上例中,我们把挖坑和钉木板都排在了打桩insert前面,这里只是举例说明额外功能次序可以任意安排.
好了,Decorator模式出来了,我们看如何调用:
Work squarePeg = new SquarePeg();
Work decorator = new Decorator(squarePeg);
decorator.insert();
Decorator模式至此完成.
7.  装饰和继承的区别
装饰和继承。
装饰设计模式是一种解决某一类问题的思想。该类问题的有效解决方案。
解决给类提供增强型功能的问题。
继承:是面向对象的特征之一。
Writer
|--TextWriter.
|--MediaWriter
发现可以形成体系,就是无论操作什么数据,但都是操作数据,可以抽取。
操作数据的效率有些低,为了提高这个操作效率,
使用缓冲技术。通过面向对象三个特点中的继承,发现可以继承完成功能的增强。
那么对具体的功能对象进行子类的扩展。
形成了一下的体系。
Writer
|--TextWriter.
|--BufferedTextWriter
|--MediaWriter
|--BufferedMediaWriter
该体系是完全可以应用的。
但是一点不太爽,当该操作数据的体系中如果出现了新的功能对象。
Writer
|--TextWriter.
|--BufferedTextWriter
|--MediaWriter
|--BufferedMediaWriter
|--DataWriter---新的功能对象。
|--BufferedDataWriter
如果后期出现了象DataWriter这样新的功能对象时,为了提高该对象的操作效率,
该对象也需要有一个子类带有缓冲技术。
导致每出现一个新功能子类,该子类都要有一个带缓冲技术的子类。
对于扩展较为麻烦。而且让这个继承体系因为不断扩展而变得非常臃肿。
需要对该体系进行优化。
以前是让每一个功能对象都具备缓冲技术。
现在可不可以单独定义一个缓冲技术对象,要缓冲谁,就把谁传进来即可。
class BufferWriter{
BufferWriter(Writer w){
}
/*
BufferWriter(TextWriter tw){
}
BufferWriter(MediaWriter mw){
}
*/
}
将缓冲技术封装成对象后,那么每一个功能对象就没有必要在定义带有缓冲技术的子类对象了。
体系就变成了
Writer
|--TextWriter.
|--MediaWriter
|--DataWriter
|--BufferWriter
即具备了缓冲功能,又优化了继承体系。
这种优化方式,很爽。可以解决功能增强问题,并比继承更有灵活性。降低了继承体系的复杂性。
为了方便于以后继续使用该优化方式,就给其起了个名字:装饰设计模式。
要记住,装饰类通常和被装饰类都所属于同一个体系。或者同一个接口。
8.  自定义装饰类
public class MybufferedReader extends Reader{
private Reader r;
public MybufferedReader(Reader r) {
// TODO Auto-generated constructor stub
this.r = r;
}
public  String  MyReaderLine () throws IOException{
//定义一个临时容器
StringBuilder sBuilder = new StringBuilder();
int ch = 0;
while ((ch = r.read())!= -1) {
if(ch =='\r')
continue;
if(ch =='\n')
return sBuilder.toString();
else
sBuilder.append((char)ch);
}
if(sBuilder.length()!= 0){
return sBuilder.toString();
}
return null;
}
public int read(char[] cbuf,int off,int len)throws IOException{
return r.read(cbuf,off,len);
}
public void close()throws IOException{
r.close();
}
public void MyClose() throws IOException{
r.close();
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
FileReader  fr = new FileReader("buf.txt");
MybufferedReader mybuf = new MybufferedReader(fr);
String line = null;
while ((line = mybuf.MyReaderLine())!=null) {
System.out.print(line);
}
mybuf.MyClose();
}
}
9.  LineNumberReader
   java.io
类 LineNumberReader

java.lang.Object
java.io.Reader     
java.io.BufferedReader
java.io.LineNumberReader
所有已实现的接口:
Closeable, Readable
public class LineNumberReader
extends BufferedReader
跟踪行号的缓冲字符输入流。此类定义方法 void setLineNumber(int) 和 int getLineNumber(),它们可分别用于设置和获取当前行号。
默认情况下,行编号从 0 开始。该行号随数据读取递增,并可以通过调用 setLineNumber(int) 进行更改。但要注意,setLineNumber(int) 不会实际更改流中的当前位置;它只更改将由 getLineNumber() 返回的值。
可认为行是由换行符('\n')、回车符('\r')或回车后面紧跟换行符中的任何一个终止的。
10  MyLineNumberReader
public class MyLineNumberReader extends MybufferedReader {
private int lineNumber;
MyLineNumberReader(Reader r) {
super(r);
// TODO Auto-generated constructor stub
}
public String MyReadLine() throws IOException{
lineNumber ++;
return super.MyReaderLine();
}
public void setLineNumber(int lineNumber){
this.lineNumber = lineNumber;
}
public int getLineNumber(){
return lineNumber;
}
}
/*
public class MyLineNumberReader{
private Reader r;
private int lineNumber;
MyLineNumberReader(Reader r){
this.r = r;
}
public String myReadLine() throws IOException{
lineNumber++;
StringBuilder sb = new StringBuilder();
int ch = 0 ;
while ((ch =r.read())!= -1) {
if(ch =='\r')
continue;
if(ch =='\n')
return sb.toString();
}
if(sb.length()!= 0)
return sb.toString();
return null;
}
public void setLineNumber(int lineNumber){
this.lineNumber = lineNumber;
}
public int getLinenumber(){
return lineNumber;
}
public void MyClose() throws IOException{
r.close();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
FileReader fr = new FileReader("CopyTextByBuf.java");
MyLineNumberReader mylnr = new MyLineNumberReader(r);
String line = null;
mylnr.setLineNumber(100);
while((line= mylnr.myReadLine())!=null){
System.out.println(mylnr.getLinenumber()+"::"+line);
}
mylnr.MyClose();
}
}
*/
11. 字节流File读写操作
字符流:
fileReader
FileWriter;
BufferedReader;
BufferedWriter;
字节流:
InputStream  
java.io
类 InputStream

java.lang.Object

java.io.InputStream
所有已实现的接口:
Closeable
直接已知子类:
AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, InputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream
public abstract class InputStream
extends Object
implements Closeable
此抽象类是表示字节输入流的所有类的超类。
需要定义 InputStream 的子类的应用程序必须始终提供返回下一个输入字节的方法。
OutPubStream
java.io
类 OutputStream

java.lang.Object
java.io.OutputStream
所有已实现的接口:
Closeable, Flushable
直接已知子类:
ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, OutputStream, PipedOutputStream
public abstract class OutputStream
extends Object
implements Closeable, Flushable
此抽象类是表示输出字节流的所有类的超类。输出流接受输出字节并将这些字节发送到某个接收器。
需要定义 OutputStream 子类的应用程序必须始终提供至少一种可写入一个输出字节的方法。
作者: 子龍    时间: 2012-9-14 08:47
哥们 你的东西好像整理了不少,不过后面好像还有些内容啊,还有哥们你能大个压缩包吗?那样我们就不用这么费劲的找帖子了。回头把你东西都发我把 呵呵。我感觉是我想要的
作者: 子龍    时间: 2012-9-19 13:49
这东西好像最近没人来看过啊!!! 这么好的东西不看多可惜啊。
作者: 皮卫凯    时间: 2012-9-19 14:30
{:soso_e179:}求个压缩包。
作者: 王永杰    时间: 2012-9-19 14:37
皮卫凯 发表于 2012-9-19 14:30
求个压缩包。

你好内容只总结了一部分,还没有完善的总结。压缩包我这两天尽量赶出来。希望你能等待。




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