zoukankan      html  css  js  c++  java
  • Java-IO流总结

    IO流:

    IO流分为两大类:字节流和字符流

     

    IO的作用就是为了读写操作的。

       每种流都分为输入流(Input)、输出流(Output);站在java程序的角度来说,java程序进行读取操作时,就是输入流;如果java程序向其他地方(硬盘,其他的设备)写入操作时,就是输出流。

    IO流只能操作文件,不能操作文件夹,否则会报错。

     

    字节流:

    字节输入流:InputStream

    字节输出流:OutputStream

    OutputStream

    可以向文件中写入字节,进行写入常用的是OutputStream的子类:FileOutputStream,常用的写入方法是write(byte[]),传入byte数组。

     

    下面将是演示利用FileOutputStream来进行写入文件:

     

    package com.xiaoshitou_io;
    
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class Test {
    
        /**
         * 使用FileOutputStream来写入文件
         * @throws IOException 
         * 
         */
        public static void main(String[] args) throws IOException {
            // 创建FileOutputStream对象
            // write.txt 文件在项目的根目录下面
            FileOutputStream fos = new FileOutputStream("write.txt");
            // 准备byte数组
            byte[] b = "Hello every body!".getBytes();
            
            // 写入整个数组
            fos.write(b);
            // 写入换行符,System.lineSeparator()方法返回一个字符串,表示跨平台的换行符
            fos.write(System.lineSeparator().getBytes());
            // 写入数组的一部分
            fos.write(b, 0, 5);// 应该写入的是Hello
            
            // 关闭输出流
            fos.close();
            // 文件的内容为:
            /*
            Hello every body!
            Hello
            */
            
            
        }
    
    }

     

       如果写入的文件存在,会被覆盖掉;要想在文件的末尾进行追加内容(保留以前的内容),就需要在创建FileOutputStream对象是,向构造器传入一个true;下面演示向文件中追加内容:

    package com.xiaoshitou_io;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class Test {
    
        /**
         * 使用FileOutputStream来写入文件
         * 直接在Write.txt文件追加内容
         * @throws IOException 
         * 
         */
        public static void main(String[] args) throws IOException {
            // 创建FileOutputStream对象
            // write.txt 文件在项目的根目录下面
            
            File writeFile = new File("write.txt");
            // 在创建对象传入一个true
            FileOutputStream fos = new FileOutputStream(writeFile, true);
            // 准备byte数组
            byte[] b = (System.lineSeparator()+"我是追加的内容,哈哈").getBytes();
            // 写入文件
            fos.write(b);
            
            // 关闭输出流
            fos.close();
            // 文件的内容为:
            /*
            Hello every body!
            Hello
            我是追加的内容,哈哈
            */
            
            
        }
    
    }

    InputStream:

      进行文件的读取经常使用的是InputStream的子类,FileInputStream可以读取任何文件,经常用的方法就是直接读入一个byte数组,这样是为了提高读取效率,不是用一个一个字节的读取。

      下面演示一个文件的复制,文件的复制,就是利用字节输入流读取文件,然后利用输出流写入文件。下面是复制一个视频文件(同时用了输入流和输出流)

    package com.xiaoshitou_io;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class Test {
    
        /**
         * 将C:UsersBeckDesktop	emp目录下all.avi文件复制到
         * 当前文件中,名字为copy.avi
         */
        public static void main(String[] args){
            // 创建输入输出流
            FileInputStream fis = null;
            FileOutputStream fos = null;
            try{
                File file = new File("C:/Users/Beck/Desktop/temp");
                fis = new FileInputStream(new File(file, "all.avi"));
                fos = new FileOutputStream(new File(file, "copy.avi"));
                // 进行读写操作
                int len = -1;
                // 每次读入1M
                byte[] b = new byte[1024*1024];
                while ((len=fis.read(b)) != -1){
                    // 写入
                    fos.write(b, 0, len);
                }
                
            }catch (IOException e){
                e.printStackTrace();
                throw new RuntimeException("文件复制失败!");
            }finally{
                // 关闭流对象
                try{
                    if (fos != null){
                        fos.close();
                    }
                }catch (IOException e){
                    e.printStackTrace();
                    throw new RuntimeException("释放资源失败!");
                }finally{
                    try{
                        if (fis != null){
                            fis.close();
                        }
                    }catch (IOException e){
                        e.printStackTrace();
                        throw new RuntimeException("释放资源失败!");
                    }
                }
            }
            System.out.println("复制文件完毕!");
            // 输出结果:
            /*复制文件完毕!*/
        }
    
    }

    BufferedInputStream&BufferedOutputStream:

      字符缓冲输入流和字符缓冲输出流,这两个流的作用的是提高输入输出的效率。BufferedInputStream&BufferedOutputStream,接收的参数分别是InputStreamOutputStream,底层还是利用字节的输入输出流,只是对输入输出流进行了封装。

      下面利用BufferedInputStream&BufferedOutputStream进行文件的复制:

    package com.xiaoshitou_io;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class Test {
    
        /**
         * 将C:UsersBeckDesktop	emp目录下all.avi文件复制到
         * 当前文件中,名字为copy.avi
         * 这次使用的是BufferedInputStream 和 BufferedOutputStream来完成
         */
        public static void main(String[] args){
            // 创建缓冲输入输出流
            BufferedInputStream bis = null;
            BufferedOutputStream bos = null;
            try{
                File file = new File("C:/Users/Beck/Desktop/temp");
                bis = new BufferedInputStream(new FileInputStream(new File(file, "all.avi")));
                bos = new BufferedOutputStream(new FileOutputStream(new File(file, "copy.avi")));
                // 进行读写操作
                int len = -1;
                // 每次读入1M
                byte[] b = new byte[1024*1024];
                while ((len=bis.read(b)) != -1){
                    // 写入
                    bos.write(b, 0, len);
                }
                
            }catch (IOException e){
                e.printStackTrace();
                throw new RuntimeException("文件复制失败!");
            }finally{
                // 关闭流对象
                try{
                    if (bos != null){
                        bos.close();
                    }
                }catch (IOException e){
                    e.printStackTrace();
                    throw new RuntimeException("释放资源失败!");
                }finally{
                    try{
                        if (bis != null){
                            bis.close();
                        }
                    }catch (IOException e){
                        e.printStackTrace();
                        throw new RuntimeException("释放资源失败!");
                    }
                }
            }
            System.out.println("复制文件完毕!");
            // 输出结果:
            /*复制文件完毕!*/
        }
    
    }

    练习:把一个视频文件按照5M的大小切割成多个。

    package com.xiaoshitou_io;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    public class Test {
    
        /**
         * 将C:UsersBeckDesktop	emp目录下all.avi文件复制到
         * 这次是把all.avi视频文件切割成多个文件。按照每个文件5M的大小切割
         * @throws IOException 
         */
        public static void main(String[] args) throws IOException{
            // 这次我把IOException直接抛出去了没有捕获
            BufferedInputStream bis = new BufferedInputStream(
                    new FileInputStream("C:/Users/Beck/Desktop/temp/all.avi"));
            // 读取视频文件
            int len = -1;
            // 每次读入5M
            byte[] bytes = new byte[1024*1024*5];
            int flag = 0;
            while ((len=bis.read(bytes)) != -1 ){
                flag++;
                // 把读入的文件写入到一个文件中
                writeToFile(bytes, len, flag);
            }
            // 关闭输入流
            bis.close();
            System.out.println("切割完成!");
            
            
        }
    
        // 将一个byte数组的内容写入到一个文件中
        private static void writeToFile(byte[] bytes, int len, int flag) throws IOException {
            BufferedOutputStream bos = new BufferedOutputStream(
                    new FileOutputStream("C:/Users/Beck/Desktop/temp/copy_"+flag+".avi"));
            bos.write(bytes, 0, len);
            bos.close();
        }
    }

      切割结果:

    字符流:

    输出流:Writer

    输入流:Reader

    字符流的底层是字节流+编码表

    字符流只能操作文本文件,进行文本文件的读写,如果是为了复制文件的话,最好选择字节流进行复制。

    Writer

    Writer下面有两个常用的字符输出流:OutputStreamWriterFileWriter

     

    OutputStreamWriter:接收的参数是一个OutputStream参数,也可以传一个charset编码字符串,这样就可以按照你设置的编码写入文本文件中。

     

    utf-8编码形式向文本文件中写入内容:

     

    package com.xiaoshitou_io;
    
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    
    public class Test {
        /*
         * 以utf8的格式向文件中写入字符串
         */
        public static void main(String[] args) throws IOException{
            // 创建 OutputStreamWriter对象
            OutputStreamWriter osw = new OutputStreamWriter(
                    new FileOutputStream("wirter.txt"),"utf-8");
            
            osw.write("我是OutputStreamWriter写入的,");
            osw.write("我的编码是UTF-8格式的。");
            // 字符流需要自己刷新
            osw.flush();
            // 关闭流
            osw.close();
            //输出结果,两句话在一行,因为没有写入换行符
            /*
            我是OutputStreamWriter写入的,我的编码是UTF-8格式的。
            */
            
        }        
    
    }

     

    FileWriter:可以接收的参数可以是File对象或者是String类型的;它的编码是系统默认的编码,我们的一般编码是使用的是GBK编码。

    使用FileWriter向文本文件中写入字符串:

     

    package com.xiaoshitou_io;
    
    import java.io.FileWriter;
    import java.io.IOException;
    
    public class Test {
        /*
         * 用FileWriter向文件中写入内容
         */
        public static void main(String[] args) throws IOException{
            // 创建 FileWriter对象
            FileWriter fw = new FileWriter("writer_gbk.txt");
            
            fw.write("我是用FileWriter写的");
            // 写入换行符
            fw.write(System.lineSeparator());
            fw.write("我的编码是用的是默认的,GBK");
            fw.flush();
            
            // 关闭流
            fw.close();
            // 输出结果
            /*
            我是用FileWriter写的
            我的编码是用的是默认的,GBK
            */
                    
        }
            
    
    }

     

    Reader:

    Reader下面有两个常用的字符流:InputStreamReaderFileReader

    InputStreamReader:可以按照指定的编码去读取文本文件,接收的参数是InputStream和一个编码字符串。

    utf-8的编码去读取一个文本文件:

     

    package com.xiaoshitou_io;
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    public class Test {
        /*
         * 以UTF-8去读取writer.txt
         * 这个文件是刚才用utf-8的格式写入的,
         * 也只能以utf8的格式去读取,否则会出现乱码
         */
        public static void main(String[] args) throws IOException{
            // 创建InputStreamReader对象
            InputStreamReader isr = new InputStreamReader(new FileInputStream("wirter.txt"), "utf-8");
            
            int len = -1;
            // 一次可以读取1024个字符,2*1024个字节,2KB
            char[] ch = new char[1024];
            while ((len=isr.read(ch)) != -1){
                System.out.print(new String(ch, 0, len));
            }
            // 关闭流
            isr.close();
            // 输出结果:
            /*
            我是OutputStreamWriter写入的,我的编码是UTF-8格式的。
            */
        }
            
    
    }

     

    FileReader:以系统默认的编码去读取一个文本文件。接收的参数可以是一个File或者String

    FileReader去读取GBK的文件,系统默认的编码是GBK

     

    package com.xiaoshitou_io;
    
    import java.io.File;
    import java.io.FileReader;
    import java.io.IOException;
    
    public class Test {
        /*
         * 用FileReader来读取文件writer_gbk.txt
         * FileReader默认是用的是系统的默认编码
         * 本机的默认编码是GBK
         */
        public static void main(String[] args) throws IOException{
            // 创建FileReader对象
            FileReader fr = new FileReader(new File("writer_gbk.txt"));
            
            int len = -1;
            char[] ch = new char[1024];
            while ((len=fr.read(ch)) != -1){
                System.out.println(new String(ch,0,len));
            }
            
            // 关闭流
            fr.close();
            // 输出结果
            /*
            我是用FileWriter写的
            我的编码是用的是默认的,GBK
            */
            
        }
            
    
    }

     

    乱码:

    乱码产生的原因:用一个A编码表将字符转成字节, 又用B编码表将字节转回字符. 两个编码表对应的关系不同,因此查到的结果就不同.

    保证不乱码的方式 : 编码与解码保持相同.

     

    字符流复制文件原理:

    BufferedReader&BufferedWriter:

    BufferedReader&BufferedWriter:字符缓冲输入输出流,接收的参数分别是:ReaderWriter;作用是提高读写的速度,读写时字符的编码是系统默认的编码:

    BufferedReader特有的一个方式读取一行readLine(),不会读取换行符

    BufferedWrter特有的一个方法时,newLine()写入一个换行符

    在写入的数据之后,需要手动flush

    利用BufferedReader&BufferedWriter进行文本文件的读写:

     

    package com.xiaoshitou_io;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    
    public class Test {
        /*
         * 利用BufferedReader&BufferedWriter进行文本文件的读写:
         * 复制文件:test.properties
         */
        public static void main(String[] args) throws IOException{
            BufferedReader br = new BufferedReader(new FileReader("test.properties"));
            BufferedWriter bw = new BufferedWriter(new FileWriter("test_copy.properties"));
            
            // 进行读写,缓冲流特有的方法就是可以按照行来读取,如果读取结束返回null
            String line = null;
            while ((line=br.readLine()) != null){
                bw.write(line);
                // 写入换行
                bw.newLine();
                // 刷新
                bw.flush();
            }
            
            // 关闭流
            bw.close();
            br.close();
            
        }
            
    }

     

    字节流和字符流的总结:

      IO流只能操作文件”文件”,不能操作文件夹(目录),否则会出现异常。

    打印流:

      PrintStream,PrintWriter:字节打印流,字符打印流;打印流只有输出流,没有输入流;输出的目的可以是文件,也可以是其他流。PrintStream自带刷新功能,PrintWriter需要手动开启。

      PrintStream:打印出来的字符的编码使用的是系统默认编码。

    package com.xiaoshitou_io;
    
    import java.io.IOException;
    import java.io.PrintStream;
    
    public class Test {
        /*
         * 使用打印流:PrintStream
         */
        public static void main(String[] args) throws IOException{
            
            PrintStream ps = new PrintStream("print.txt");
            ps.println("旺旺");
            ps.println("欢欢");
            ps.println("乐乐");
            ps.close();
            // 结果:
            /*
            旺旺
            欢欢
            乐乐
            */
        }
            
    
    }

      PrintWriter:

    package com.xiaoshitou_io;
    
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    
    public class Test {
        /*
         * 使用打印流:PrintWriter
         */
        public static void main(String[] args) throws IOException{
            // 创建PrintWriter对象时,开启自动刷新功能
            PrintWriter pw = new PrintWriter(new FileWriter("print.txt"), true);
            
            pw.println("我是PrintWriter");
            pw.println("出来的");
            
            pw.close();
            // 结果:
            /*
            我是PrintWriter
            出来的
            */
        }
            
    
    }

    序列化&反序列化:

    序列化:就是将对象写入文件的过程

    反序列化:从文件读入对象的过程

    ObjectOutputStream&ObjectInputStream:需要序列化的对象必须去实现Serializable接口,否则在序列化的时候会出错。

    序列化的注意点:

    1、static修饰的成员不能被序列化

    2、要想成员变量不被序列化,可以用transient关键字修饰

    3、为了不发生序列号冲突,设置:serialVersionUID

    下面就进行序列化和反序列化:

     

    package com.xiaoshitou_io;
    
    import java.io.Serializable;
    
    public class Student implements Serializable{
        private static final long serialVersionUID = -5214244848175027425L;
        private String name;
        private String id;
        private transient String phone;
        
        
        public Student(String name, String id, String phone) {
            super();
            this.name = name;
            this.id = id;
            this.phone = phone;
        }
        public Student() {
            super();
            
        }
        
        @Override
        public String toString() {
            return "Student [name=" + name + ", id=" + id + ", phone=" + phone
                    + "]";
        }
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
        public String getPhone() {
            return phone;
        }
        public void setPhone(String phone) {
            this.phone = phone;
        }
        
    }
    
    package com.xiaoshitou_io;
    
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    
    public class Test {
        /*
         * 进行序列化和反序列化
         * 对Student对象序列化
         */
        public static void main(String[] args) throws IOException, ClassNotFoundException{
            // 创建ObjectOutputStream对象,绑定目的地
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("tmp.txt"));
            // 创建Student对象
            Student stu = new Student("张三", "T001", "15522223333");
            // 写入对象
            oos.writeObject(stu);
            // 关闭流
            oos.close();
            System.out.println("序列化成功!");
            System.out.println("==============分割==============");
            
            // 进行反序列化
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("tmp.txt"));
            // 读取对象
            Object obj = ois.readObject();
            if (obj instanceof Student){
                Student s = (Student)obj;
                System.out.println(s);
            }
            // 关闭流
            ois.close();
            System.out.println("反序列化成功!");
            // 结果:phone是transient关键字修饰的,所以没有被序列化
            /*
            序列化成功!
            ==============分割==============
            Student [name=张三, id=T001, phone=null]
            反序列化成功!
            */
            
            
        }
            
    
    }

    Properties

    Properties类是HashTable的一个子类,实现了Map接口,所以里面保存的是键值对,元素的存取是无序的,这个类经常被用来处理配置文件。

    利用Properties来读写文件:

     

    package com.xiaoshitou_io;
    
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Properties;
    
    
    
    public class Test {
        /*
         * 利用Properties来读写文件
         */
        public static void main(String[] args) throws IOException{
            // 读取Properties文件:pro.properties
            Properties pro = new Properties();
            // 加载文件
            pro.load(new FileReader("pro.properties"));
            // 根据key来读取值
            String key = pro.getProperty("key");
            System.out.println(key);
            String value = pro.getProperty("匿名");
            System.out.println(value);
            System.out.println("=============================");
            
            // 修改Properties内的值,或者添加新的值
            pro.setProperty("key", "我是修改的值");
            pro.setProperty("add", "我是新添加的值");
            // 保存进文件
            pro.store(new FileWriter("pro.properties"),"");
            System.out.println("修改完成");
            // 控制台打印结果:
            /*
            姥姥阿里
            娇娇
            =============================
            修改完成
            */
            // pro.properties 文件中的内容:
            /*
            #
            #Sun Jun 11 08:53:22 CST 2017
            key=我是修改的值
            张嘴=监控
            匿名=娇娇
            add=我是新添加的值
            */
        }
    }

     

     

     

     

     

     

     

     

  • 相关阅读:
    观察者模式的新纪录
    字符串和json之间的互相转化
    改变自己:工作几年就该给自己“清零”啦
    观察者模式的记录
    background-position的百分比
    豌豆荚前端面试中的一个算法题
    javascript的原型与继承(2)
    javascript的原型和继承(1)
    百度客户端首页的图片轮换效果
    javascript中闭包的概念
  • 原文地址:https://www.cnblogs.com/xiaoshitoutest/p/6991179.html
Copyright © 2011-2022 走看看