Fork me on GitHub

JAVA基础学习day20--IO流二-缓冲流、字节流

一、缓冲流

1.1、字符流的缓冲区

缓冲区的出现是为了提高IO的读写效率

对应类

BufferedReader

BufferedWriter

缓冲区要结合流才可以使用

在流的基础上对流的功能进行了增强

1.2、BufferedReader、BufferedWriter

 

public class BufferedWriterextends Writer

 

构造方法摘要
BufferedWriter(Writer out)
创建一个使用默认大小输出缓冲区的缓冲字符输出流。
BufferedWriter(Writer out, int sz)
创建一个使用给定大小输出缓冲区的新缓冲字符输出流。

 

将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

 

可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。

 

该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,此概念由系统属性 line.separator 定义。并非所有平台都使用新行符 ('\n') 来终止各行。因此调用此方法来终止每个输出行要优于直接写入新行符。

 

通常 Writer 将其输出立即发送到底层字符或字节流。除非要求提示输出,否则建议用 BufferedWriter 包装所有其 write() 操作可能开销很高的 Writer(如 FileWriters 和 OutputStreamWriters)。例如,

 

PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));

将缓冲 PrintWriter 对文件的输出。如果没有缓冲,则每次调用 print() 方法会导致将字符转换为字节,然后立即写入到文件,而这是极其低效的。

 

public class BufferedReaderextends Reader

 

构造方法摘要
BufferedReader(Reader in)
创建一个使用默认大小输入缓冲区的缓冲字符输入流。
BufferedReader(Reader in, int sz)
创建一个使用指定大小输入缓冲区的缓冲字符输入流。

 

 

 

从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

 

可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。

 

通常,Reader 所作的每个读取请求都会导致对底层字符或字节流进行相应的读取请求。因此,建议用 BufferedReader 包装所有其 read() 操作可能开销很高的 Reader(如 FileReader 和 InputStreamReader)。例如,

 

BufferedReader in = new BufferedReader(new FileReader("foo.in"));

将缓冲指定文件的输入。如果没有缓冲,则每次调用 read() 或 readLine() 都会导致从文件中读取字节,并将其转换为字符后返回,而这是极其低效的。

通过用合适的 BufferedReader 替代每个 DataInputStream,可以对将 DataInputStream 用于文字输入的程序进行本地化

1.3、示例

在创建缓冲区之前,必须先有流对象

 

package com.pb.io.demo2;

/**
创建缓冲区之间必须,先创建流
使用缓冲区,要flush,刷新
*/
/**
创建缓冲区之间必须,先创建流
使用缓冲区,要flush,刷新
*/
import java.io.*;
class BufferedReaderAndWriterDemo1 
{
            public static void main(String[] args) 
            {
                File source=new File("d:\\demo.txt");
                File objFile=new File("d:\\a.txt");
                useBuffered(source,objFile);
            }
    public static void useBuffered(File source,File objFile){
        
        BufferedReader br=null;
        BufferedWriter bw=null;

        try{
            //声明缓冲区对象,并将字符流做为参数传入
            br=new BufferedReader(new FileReader(source));
            bw=new BufferedWriter(new FileWriter(objFile));
            //接收读取的长度
            String line=null;
            
            //读取内容并放入buf中,判断是不是最后
            while((line=br.readLine())!=null){
                //写入,有多长写多长
                bw.write(line,0,line.length());
                bw.newLine();
                
                }    
            System.out.println("读写完成!");
        }catch(IOException e){
            System.out.println(e.toString());
        
        }finally{
                        try{
                                if(bw!=null)
                                    bw.flush();
                                bw.close();
                        }catch(IOException e){
                        System.out.println(e.toString());
                        }
                        try{
                            if(br!=null)
                                br.close();

                        }catch(IOException e){
                        System.out.println(e.toString());
                        }

                }
    }
}

 

 

二、MyBuffered

2.1、示例

 

package com.pb.io.demo2;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class MyBuffered {

    private FileReader fr;

    public MyBuffered(FileReader fr) {
        this.fr = fr;
    }

    /*
     * 可以一次读一行的方法
     */
    public String myReadLine() throws IOException {
        // 定义一个临时 容器,原BufferedReader封装的是字符数组
        // 为了方便,定义一个StringBuilder
        StringBuilder sb = new StringBuilder();
        int ch = 0;

        while ((ch = fr.read()) != -1) {
            if (ch == '\r') {
                continue;
            }
            if (ch == '\n') {
                return sb.toString();
            }
            // 读一个存一个
            sb.append((char)ch);
        }
        if(sb.length()!=0){
            return sb.toString();
        }
        return null;
    }
    public void myClose() throws IOException{
        if (fr != null)
            fr.close();
    }
    public static void main(String[] args) throws IOException {
        
        File file=new File("d:\\demo.txt");
        MyBuffered mb=new MyBuffered(new FileReader(file));
        String line=null;
        while((line=mb.myReadLine())!=null){
            System.out.println(line);
        }
        mb.myClose();
    }
}

 

 

 

三、装饰设计模式

3.1、装饰设计模式

装饰设计模式:

当想要对已经有的对象进行功能增强时,

可以定义类,将已经对象传入,基于已经有的功能,并提供加强功能。

那么自定义的该类就称为装饰类

 

package com.pb.io.demo3;

class Person{
    public void eat(){
        System.out.println("吃饭");
    }
}
class SuperPerson{
    private Person p;
    
    public SuperPerson(Person p) {
        super();
        this.p = p;
    }

    public void superEat(){
        System.out.println("开胃酒");
        p.eat();
        System.out.println("甜点");
        System.out.println("来一根");
    }
}

public class PersonTest {

    public static void main(String[] args) {
        Person p=new Person();
        p.eat();
        SuperPerson sp=new SuperPerson(p);
        sp.superEat();
        

    }

}

 

 

 

3.2、与继承之间的关系

装饰类通常会通过构造方法接收被被装饰的对象,并基于被装饰的对象的功能,提供更强的功能

装饰模式比继承灵活,避免了继承体系臃肿

而且降低了类于类之间的关系

装饰类因为增强已有对象,具备的功能和已经的是相同的,只不过提供了更强的功能。

所以装饰类和被装饰类通常是都属于一个体系中。

 

四、LineNumberReader

4.1、

构造方法摘要
LineNumberReader(Reader in)
使用默认输入缓冲区的大小创建新的行编号 reader。
LineNumberReader(Reader in, int sz)
创建新的行编号 reader,将字符读入给定大小的缓冲区。

方法摘要
int getLineNumber()
获得当前行号。
void mark(int readAheadLimit)
标记该流中的当前位置。
int read()
读取单个字符。
int read(char[] cbuf, int off, int len)
将字符读入数组中的某一部分。
String readLine()
读取文本行。
void reset()
将该流重新设置为最新的标记。
void setLineNumber(int lineNumber)
设置当前行号。
long skip(long n)
跳过字符。

4.2、示例

 

package com.pb.io.demo4;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;

public class LineNumberReaderDemo {

    public static void main(String[] args) {
        LineNumberReader lnr=null;
        try {
             lnr=new LineNumberReader(new FileReader("d:\\demo.txt"));
             //设置开始行叼
             lnr.setLineNumber(100);
             String line=null;
             while((line=lnr.readLine())!=null){
                 //getLineNumber默认从1开始,设置后从设置的行号开始
                 System.out.println(lnr.getLineNumber()+":"+line);
             }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(lnr!=null)
                lnr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

 

 

4.3、自定义

 

package com.pb.io.demo4;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class MyLineNumberReader {

    private Reader reader;
    private int lineNumber;

    public MyLineNumberReader(Reader reader) {
        this.reader = reader;
    }

    /*
     * 读一行
     */
    public String myReadLine() throws IOException {
        lineNumber++;
        StringBuilder sb = new StringBuilder();
        int ch=0;
        while ((ch = reader.read()) != -1) {
            if (ch == '\r') 
                continue;
             if (ch == '\n') 
                return sb.toString();
            sb.append((char) ch);    
        }
        if (sb.length() != 0) 
            return sb.toString();    
    return null;

    }
    
    public void myClose() throws IOException{
        reader.close();
    }

    public Reader getReader() {
        return reader;
    }

    public void setReader(Reader reader) {
        this.reader = reader;
    }

    public int getLineNumber() {
        return lineNumber;
    }

    public void setLineNumber(int lineNumber) {
        this.lineNumber = lineNumber;
    }

    public static void main(String[] args) throws IOException {
        File file=new File("d:\\demo.txt");
        MyLineNumberReader mln=new MyLineNumberReader(new FileReader(file));
        String line=null;
        //mln.setLineNumber(100);
        while((line=mln.myReadLine())!=null){
            System.out.println(mln.getLineNumber()+":"+line);
        }
        mln.myClose();
    }

}

 

 

五、字节流

5.1、字节流

OutputStream写、InputStream读

FileOutputStream、FileInputStream 字节流输出、输入流

构造方法摘要
OutputStream()

方法摘要
void close()
关闭此输出流并释放与此流有关的所有系统资源。
void flush()
刷新此输出流并强制写出所有缓冲的输出字节。
void write(byte[] b)
b.length 个字节从指定的 byte 数组写入此输出流。
void write(byte[] b, int off, int len)
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
abstract void write(int b)
将指定的字节写入此输出流。

构造方法摘要
InputStream()

方法摘要
int available()
返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。
void close()
关闭此输入流并释放与该流关联的所有系统资源。
void mark(int readlimit)
在此输入流中标记当前的位置。
boolean markSupported()
测试此输入流是否支持 markreset 方法。
abstract int read()
从输入流中读取数据的下一个字节。
int read(byte[] b)
从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
int read(byte[] b, int off, int len)
将输入流中最多 len 个数据字节读入 byte 数组。
void reset()
将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。
long skip(long n)
跳过和丢弃此输入流中数据的 n 个字节。

5.2、FileInputStream与FileOutputStream

package com.pb.io.demo5;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 使用字节流复制文件
 *
 */
public class FileOutputAndFileInputStreamDemo {

    public static void main(String[] args) {
        File source=new File("d:\\1.jpg");
        File objFile=new File("d:\\4.jpg");
        InputAndOutput2(source,objFile);
    }
    public static void InputAndOutput(File source,File objFile){
        //声明字节流输入,输出对象
        FileInputStream fis=null;
        FileOutputStream fos=null;
        try {
            fis=new FileInputStream(source);
            fos=new FileOutputStream(objFile);
            //声明缓冲区
            byte [] buf=new byte[1024];
            int len=0;
            while((len=fis.read(buf))!=-1){
                fos.write(buf, 0, len);
            }
            System.out.println("=======读写完成========");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(fos!=null)
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fis!=null)
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        
    }
    /*
     * 不建议使用
     */
    public static void InputAndOutput2(File source,File objFile){
        //声明字节流输入,输出对象
        FileInputStream fis=null;
        FileOutputStream fos=null;
        try {
            fis=new FileInputStream(source);
            fos=new FileOutputStream(objFile);
            //声明大小刚刚缓冲区
            byte [] buf=new byte[fis.available()]; //不建议使用available
            
                fis.read(buf);
                fos.write(buf,0,buf.length);
            
            System.out.println("=======读写完成========");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(fos!=null)
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fis!=null)
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        
    }
}

 

 

 

六、字节流缓冲区

6.1、示例复制.mp3

 

package com.pb.io.demo5;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedStreamDemo {

    public static void main(String[] args) {
        File file1=new File("d:\\gm.mp3");
        File file2=new File("d:\\mg.mp3");
        copy1(file1,file2);
    }
    public static void copy1(File file1,File file2){
        //声明字节流缓冲区对象
        BufferedOutputStream bos=null;
        BufferedInputStream bis=null;
        try {
            bis=new BufferedInputStream(new FileInputStream(file1));
            bos=new BufferedOutputStream(new FileOutputStream(file2));
            
            //声明缓冲区大小
            int by=0;
            while((by=bis.read())!=-1){
                bos.write(by);
            }
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(bos!=null)
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(bis!=null)
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
    }

}

 

 

6.2、自定义

 

 

package com.pb.io.demo5;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class MyBufferedStream {

    private InputStream is;
    private byte[] buf = new byte[1024];

    private int pos = 0;
    private int count = 0;

    public MyBufferedStream(InputStream is) {
        this.is = is;
    }

    /*
     * 一次读一个字节,从缓冲区的(字节数组)获取
     */
    public int myRead() throws IOException {
        // 通过in对象读取硬盘上的数据,并存在buf中
        if (count == 0) {
            count = is.read(buf);
            if (count < 0) {
                return -1;
            }
            pos = 0;
            byte b = buf[pos];
            count--;
            pos++;
            return b & 0xff;
        } else if (count > 0) {
            byte b = buf[pos];
            count--;
            pos++;
            return b & 0xff;
        }
        return -1;

    }

    public void myClose() throws IOException {
        is.close();
    }

    public static void main(String[] args) {
        File file1 = new File("d:\\gm.mp3");
        File file2 = new File("d:\\kk.mp3");
        copy1(file1, file2);
    }

    public static void copy1(File file1, File file2) {
        // 声明字节流缓冲区对象
        BufferedOutputStream bos = null;
        MyBufferedStream mbs = null;
        try {
            mbs = new MyBufferedStream(new FileInputStream(file1));
            bos = new BufferedOutputStream(new FileOutputStream(file2));

            // 声明缓冲区大小
            int by = 0;
            while ((by = mbs.myRead()) != -1) {
                bos.write(by);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bos != null)
                    bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                mbs.myClose();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

 

 

七、转换

7.1、字节流转换字符流

InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

 

BufferedReader in
   = new BufferedReader(new InputStreamReader(System.in));

 

 

 

 

OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。 

Writer out
   = new BufferedWriter(new OutputStreamWriter(System.out));

 

 

7.2、示例

接收键盘输入,使用转换流实现

 

package com.pb.io.demo6;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
/**
 * 接收键盘输入,并将内容写入文件
 *
 */
public class Demo {

    public static void main(String[] args) {

        BufferedReader br=null;
        BufferedWriter bw=null;

        try {
            //声明输入流,使用转换流实现
            br=new BufferedReader(new InputStreamReader(System.in));
            
            //声明输出流,使用转换流实现
            bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d:\\t.txt")));
            
            //接收键盘录入
            String str=null;
            System.out.println("请输入要写入文件的内容,输入over结束!");
            //输入over结束
            while(!(str=br.readLine()).equals("over")){
                bw.write(str);
                bw.newLine();
            }
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(bw!=null)
                bw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            
            try {
                if(br!=null)
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

 

 

八、流操作的规律

1、明确源和目的

  源:输入流。InputStream,Reader

  目的:输出流 .OutputStream,Writer

2、操作的数据是否为纯文本

  是:字符流。Reader、Writer

  不是:字节流。InputStream、OutputStream

3、当体系明确后,在明确要使用哪个具体对象。

  通过设备来进行区别。

  源设备:内存、硬盘、键盘

  目的设备:内存、硬盘、控制台

九、重定向IO

9.1、示例

 

//设置输入流的
        System.setIn(new FileInputStream("d:\\demo.txt"));
        //设置的输出流的方向
        System.setOut(new PrintStream("d:\\zz.txt"));

 

 

 

 

十、系统信息

10.1、示例

 

package com.pb.io.demo6;


import java.util.Properties;

public class Demo1 {

    public static void main(String[] args) {
     Properties prop=System.getProperties();
     prop.list(System.out); //可以设置为输出流对象new PrintWriter(文件)
    }

}

 

-- listing properties --
java.runtime.name=Java(TM) SE Runtime Environment
sun.boot.library.path=C:\Java\jre1.8.0_60\bin
java.vm.version=25.60-b23
java.vm.vendor=Oracle Corporation
java.vendor.url=http://java.oracle.com/
path.separator=;
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
file.encoding.pkg=sun.io
user.script=
user.country=CN
sun.java.launcher=SUN_STANDARD
sun.os.patch.level=
java.vm.specification.name=Java Virtual Machine Specification
user.dir=F:\work\IODemo
java.runtime.version=1.8.0_60-b27
java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
java.endorsed.dirs=C:\Java\jre1.8.0_60\lib\endorsed
os.arch=amd64
java.io.tmpdir=C:\Users\ADMINI~1\AppData\Local\Temp\
line.separator=

java.vm.specification.vendor=Oracle Corporation
user.variant=
os.name=Windows 7
sun.jnu.encoding=GBK
java.library.path=C:\Java\jre1.8.0_60\bin;C:\Windows\Su...
java.specification.name=Java Platform API Specification
java.class.version=52.0
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
os.version=6.1
user.home=C:\Users\Administrator
user.timezone=
java.awt.printerjob=sun.awt.windows.WPrinterJob
file.encoding=UTF-8
java.specification.version=1.8
user.name=Administrator
java.class.path=F:\work\IODemo\bin
java.vm.specification.version=1.8
sun.arch.data.model=64
java.home=C:\Java\jre1.8.0_60
sun.java.command=com.pb.io.demo6.Demo1
java.specification.vendor=Oracle Corporation
user.language=zh
awt.toolkit=sun.awt.windows.WToolkit
java.vm.info=mixed mode
java.version=1.8.0_60
java.ext.dirs=C:\Java\jre1.8.0_60\lib\ext;C:\Window...
sun.boot.class.path=C:\Java\jre1.8.0_60\lib\resources.jar...
java.vendor=Oracle Corporation
file.separator=\
java.vendor.url.bug=http://bugreport.sun.com/bugreport/
sun.cpu.endian=little
sun.io.unicode.encoding=UnicodeLittle
sun.desktop=windows
sun.cpu.isalist=amd64

 

posted @ 2015-09-30 15:05  森林森  阅读(531)  评论(0编辑  收藏  举报