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=我是新添加的值
            */
        }
    }

     

     

     

     

     

     

     

     

  • 相关阅读:
    通用权限管理设计 之 数据库结构设计
    jQuery LigerUI 插件介绍及使用之ligerDateEditor
    jQuery LigerUI 插件介绍及使用之ligerTree
    jQuery LigerUI V1.01(包括API和全部源码) 发布
    jQuery liger ui ligerGrid 打造通用的分页排序查询表格(提供下载)
    jQuery LigerUI V1.1.5 (包括API和全部源码) 发布
    jQuery LigerUI 使用教程表格篇(1)
    jQuery LigerUI V1.0(包括API和全部源码) 发布
    jQuery LigerUI V1.1.0 (包括API和全部源码) 发布
    nginx keepalived
  • 原文地址:https://www.cnblogs.com/xiaoshitoutest/p/6991179.html
Copyright © 2011-2022 走看看