码迷,mamicode.com
首页 > 其他好文 > 详细

黑马程序员 - IO流(上)

时间:2015-08-20 23:47:02      阅读:303      评论:0      收藏:0      [点我收藏+]

标签:

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

IO流
用于处理设备间的数据传输
按操作数据分:字节流和字符流
按流向分:输入流和输出流
IO流常用基类:
字节流的抽象基类:
InputStream OutputStream
字节流的抽象基类:
Reader Writer
注意:这4个类派生出的子类名称均以其父类名作为子类名的后缀。
数据的最常见体现形式是:文件
下面代码演示常用的写入,读取操作。

import java.io.*;
class  FWDemo{                       //输出流演示
    public static void main(String[] args)throws IOException{ //只使用try时,可以不抛出异常
        fw1show();                   //演示文件创建及写入数据
        fw2show();
        fw3show();
    }
    //文件的创建及操作
    public static void fw1show() throws IOException{    
        //创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件。
        //而且该文件会被创建到指定目录下。如果该目录下已经有同名文件,原文件将会被覆盖。
        FileWriter fw1 = new FileWriter ("d:\\demo1.txt");
        fw1.write("abcde");//将字符串写入内存中的流对象中。
        fw1.flush();       //刷新该流的缓存,将数据写入文件,后面可以继续操作流。
        fw1.close();       //关闭流资源,但是关闭之前会刷新一次内部缓冲的数据。
                           //close()不能再调用 fw.write 。
    }
    //IO异常的处理方式
    public static void fw2show(){
        //注意变量在代码块中的作用域,所以在外部定义变量,在代码块中初始化    
        FileWriter fw2 = null;    
        try{
            fw2 = new FileWriter ("d:\\demo2.txt");
            fw2.write("aaaaa");        
        }
        catch (IOException e){
            System.out.println(e.toString()); //打印异常信息
        }
        finally {                              //放入必须执行的数据
            try{
                if(fw2!=null)
                    fw2.close();
            }
            catch (IOException e){
                System.out.println(e.toString());
            }
        }
    }
    //续写已有文件
    public static void fw3show(){
        FileWriter fw3 = null;
        try{
            //传递一个true参数,代表不覆盖已有文件,在文件末尾处添加数据。
            fw3 = new FileWriter ("d:\\demo1.txt",true);
            fw3.write("+aa\r\naaa");        //在demo1.txt 文件末尾添加字符串。
        }    //注意,在windows中换行符是两个组成的是: \r\n   
        catch (IOException e){
            System.out.println(e.toString());
        }
        finally{  //放入必须执行的数据    
            try{
                if(fw3!=null)
                    fw3.close();
            }
            catch (IOException e){
                System.out.println(e.toString());
            }
        }
    }
}
class FRDemo{    //输入流演示
    public static void main(String[] args){
        fr1show();       //读取文件并打印
    }
    public static void fr1show(){
        //创建一个文件读取流对象,和指定名称的文件相关联
        //必须确保读取的文件存在,否则会发生异常
        FileReader fr1 = null ;
        FileReader fr2 = null ;
        try{
            fr1 = new FileReader("d:\\demo1.txt");
            fr2 = new FileReader("d:\\demo1.txt");
            while (true){
                //read():一次读一个字符,而且会自动往下读取。
                //read()读取的是字符的字码表数值。
                int ch = fr1.read();         
                if(ch==-1)              //判断是否已经读取到文件末尾
                    break;
                System.out.println((char)ch);
            }
            System.out.println("------------");
            //定义一个字符数组
            //read(char[]) 将字符串存入字符数组返回的是读取到的字符个数
            char [] buf = new char [3]; //一般char[]数组长度取1024,一个字节。
            int num = 0;
            while ((num = fr2.read(buf))!= -1){
                System.out.println("ch="+(new String(buf,0,num)));
            }    
        }
        catch (IOException e){
            System.out.println("fr1:"+e);
        }
        finally{
            try{
                if(fr1!=null)
                    fr1.close();
                if(fr2!=null)
                    fr2.close();
            }
            catch (IOException e){
                System.out.println(e.toString());
            }
        }
    }
}

输入流与输出流的应用演示

需求:将d盘的一个文件复制到d盘并重命名

步骤:
1.在d盘创建一个文件,用于存储d盘源文件的数据。
2.定义读取流和d盘源文件关联。
3.通过不断的读写完成数据存储。
4.关闭资源。

class CopyDemo{
    public static void main(String[] args){
        copy();                  //调用复制函数
    }
    public static void copy(){
        FileWriter fw = null;    //定义输出流
        FileReader fr = null;     //定义输入流
        try{
            fr = new FileReader("d:\\demo1.txt");//将输入流与需创建文件相关联
            fw = new FileWriter("d:\\demo3.txt");//将输出流与需复制文件相关联
            char[] buf = new char [1024];         //定义一个中转数组用于存储输入流读取的数据
            int len = 0;                         //定义实数用于记录读取的字符串长度
            while ((len = fr.read(buf))!=-1){    //将输入流读取的数据传给中转数组,并将字符长度传给len
                fw.write(new String(buf,0,len)); //将数据写入输出流
            }
        }
        catch (IOException e){
            throw new RuntimeException("读写失败");//定义IO异常处理办法
        }
        finally{
            try{
                if (fw!=null)                       //关闭资源
                    fw.close();
                if (fr!=null)
                    fr.close();
            }
            catch (IOException e){
                throw new RuntimeException("读写失败");//定义IO异常处理办法
            }            
        }
    }
}

装饰设计模式:
当想要对已有的对象进行功能增强时,
可以定义类,将已有对象传入,给予已有的功能,并提供加强功能
那么自定义的该类称为装饰类

装饰模式比继承要灵活,避免流体系的臃肿
而且降低流类与类之间的关系。
装饰类因为增强流已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。
所以装饰类和被装饰类通常都是属于一个体系中。

字符流的缓冲区
缓冲区就是装饰设计模式的一种应用。
缓冲区提高了对数据的读写效率.
所以在创建缓冲区之前,必须现有流对象。
对应类
BufferedWriter BufferedReader

import java.io.*;
class BufferedDemo{
    public static void main(String[] args) throws IOException{
        bwshow();           //演示输出缓冲区
        brshow();            //演示输入缓冲区
    }
    public static void bwshow() throws IOException{
        //创建一个流对象,并将目标文件与其关联
        FileWriter fw =new FileWriter("d:\\buffered.txt");
        //为提高写入效率,加入缓冲技术
        //将需要提高效率的流对象作为参数传递给缓冲区
        BufferedWriter bw = new BufferedWriter (fw);
        bw.write("abcde");
        bw.newLine(); //缓冲区的换行方法
        bw.write("aa");
        bw.flush();
        //缓冲区的关闭,其实是关闭的是其缓冲的流对象,所以不需要单独在关闭流对象
        bw.close(); 
    }
    public static void brshow() throws IOException{
        FileReader fr1 =new FileReader("d:\\buffered.txt");
        FileReader fr2 =new FileReader("d:\\buffered.txt");
        //为提高写入效率,加入缓冲技术
        //将需要提高效率的流对象作为参数传递给缓冲区
        BufferedReader br = new BufferedReader (fr1);    
        while (true){
            String s1 = br.readLine(); //按照行读取,但是不包含行终止符。
            if (s1 == null)
                break;
            System.out.println(s1);
        }
        System.out.println("-------------------");
        //缓冲区的关闭,其实是关闭的是其缓冲的流对象,所以不需要单独在关闭流对象
        //传入自定义的buff对象
        MyBuffReader mybuff = new MyBuffReader (fr2);  //定义自定义的缓冲区,并将去与fr2输入流关联
        while (true)
        {
            String s2 = mybuff.myreadline(); //按照行读取,但是不包含行终止符。
            if (s2 == null)
                break;
            System.out.println(s2);
        }
        br.close(); 
        mybuff.myclose();
    }
}
//自定义缓存区,实现readLine()方法代码
class MyBuffReader{
    private FileReader r;                //定义输入流
    MyBuffReader(FileReader r){            //将输入流传入    
        this.r = r;
    }
    public String myreadline() throws IOException{    //定义自定义的readLine()函数
        //定义一个临时容器,原bufferReader封装的是字符数组
        StringBuilder sb = new StringBuilder ();    
        int ch = 0;
        while ((ch=r.read())!=-1){                    //判断输入流是否读取到文件末尾
            //判断字符串运行到回车符,就返回字符串,否则就继续向sb对象中存储字符。
            if(ch==‘\r‘)                            //判断是否是回车符的第一个字符,是就结束本次循环
                continue;
            if(ch==‘\n‘)                            //判断是否是回车符的第二个字符,是就返回现在StringBuilder中的数据
                return sb.toString();
            else                                    //如果读取的字符不属于回车符,就将字符存入StringBuilder
                sb.append((char)ch);
        }
        //当源字符串最后没有回车符时,就不能在循环中返回字符串,
        //此时字符串已经存储在sb对象中,需要添加判断返回字符串。
        if(sb.length()!=0)        
            return sb.toString();
        return null;
    }
    public void myclose() throws IOException{
        r.close();
    }
}

字节流
InputStream OutputStream

字节流可以操作字符和字节数据,但是在操作字符数据时没有字符流方便。

import java.io.*;
class  FODemo{
    public static void main(String[] args)  throws IOException{
        long start = System.currentTimeMillis();
        //fw1show();
        //fr1show();
        copy();
        long end = System.currentTimeMillis();
        System.out.println((end-start)+"ms");
    }
    public static void fw1show()  throws IOException{
        FileOutputStream fo = new FileOutputStream("d:\\demo1.txt");//将需写入文件与输出流相关联
        fo.write("aabcde".getBytes());                                //写入数据,注意,当前为字节流,所以写入的应为字符的字节数据。
        fo.close();
    }    
    public static void fr1show() throws IOException{                //演示字节输入流的3种读取方法
        FileInputStream fi1 = new FileInputStream ("d:\\demo1.txt");
        FileInputStream fi2 = new FileInputStream ("d:\\demo1.txt");
        FileInputStream fi3 = new FileInputStream ("d:\\demo1.txt");
        int ch = 0;
        //每次读取一个字符
        while ((ch=fi1.read())!=-1){
            System.out.println((char)ch);
        }
        fi1.close();
        //每次读取一个字符串
        byte [] cha1 = new byte [1024];                                //因为是字节流,所以定义一个字节数组
        int len = 0;
        while((len=fi2.read(cha1))!=-1){                            //讲数据写入字节数组并判断是否已读取到文件末尾
            System.out.println(new String(cha1,0,len));                //将读取的数据转换成字符串并打印
        }
        fi2.close();
        //available方法返回的是可最大连续读取的字节数。
        //注意所使用的内存是否够用
        int num = fi3.available();
        byte [] cha2 = new byte [num];
        int len2 = fi3.read(cha2);
        System.out.println(new String (cha2,0,len2));
    }
    public static void copy(){                                        //字节流可对非文本文件进行复制
        FileOutputStream fo = null;                                    //定义输出流    
        FileInputStream fi = null;                                    //定义输入流
        byte [] cha1 = new byte [1024];
        int len = 0;
        try{
            fo = new FileOutputStream("d:\\demo4.jpg");                //将需写入文件与输出流关联
            fi = new FileInputStream ("d:\\demo1.jpg");                //将需读取文件与输入流关联
            while((len=fi.read(cha1))!=-1){                            //将数据写入字节数组并判断是否已在文件末尾
                fo.write(cha1);                                        //将字节数组写入输出流
            }
        }
        catch (IOException e){                                        //定义IO异常处理办法
            System.out.println(e);
        }
        finally{
            try{
                fi.close();                                            //关闭资源
                fo.close();
            }
            catch (IOException e){
                System.out.println(e);
            }
        }
    }
}

键盘录入数据
System.out:标准输出设备 控制台
System.in:标准输入设备 键盘

流操作的基本规律:
1.明确源和目的
源:输入流
目的:输出流
2.操作的数据是否是纯文本
是:字符流
否:字节流
3.明确使用那些具体对象
源设备:内存,硬盘,键盘
目的设备:内存,硬盘,控制台


需求:使用键盘输入数据,并用控制台打出,然后保存为一个文本文件

扩展:想要把录入的数据按照指定编码表(utf-8)存入文件。

class TransInDemo{
    public static void main(String[] args) throws IOException{
        //回去键盘录入对象
        InputStream in = System.in;
        //将字节流转换成字符流
        InputStreamReader isr = new InputStreamReader (in);
        //为了提高效率 将字符串进行缓冲区技术
        BufferedReader buf = new BufferedReader (isr);
        //同理设置使用了缓冲技术的字节流转字符流输出
        BufferedWriter bufw =        //将输出流与控制台关联
            new BufferedWriter (new OutputStreamWriter(System.out));
        BufferedWriter bufw1=        //将输出流与写入文件相关联,并定义其编码为utf-8        
            new BufferedWriter (new OutputStreamWriter(new FileOutputStream("d:\\demo05.txt",true),"utf-8"));

        String line = null;                        //定义空字符串line
        while ((line=buf.readLine())!=null){    //将输入流种数据按行读取写入字符串line,并判断是否读取至数据末尾
            if ("over".equals(line))            //定义关闭命令
                break;
            bufw.write(line);                    //向控制台写入line中的数据
            bufw1.write(line);                    //向关联的文件中写入line的数据
            bufw.newLine();                        //换行
            bufw1.newLine();    
            bufw.flush();                        //刷新内存,将输出缓冲区中的数据写入目的地
            bufw1.flush();
        }
        buf.close();                            //关闭缓冲区
        bufw1.close();
        bufw.close();
    }
}

 

黑马程序员 - IO流(上)

标签:

原文地址:http://www.cnblogs.com/myblog-cl/p/4746414.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!