IO流的基本使用

IO流

    |--字节流
        |--字节输入流
            InputStream
                int read():一次读取一个字节
                int read(byte[] bys):一次读取一个字节数组

                |--FileInputStream
                |--BufferedInputStream
        |--字节输出流
            OutputStream
                void write(int by):一次写一个字节
                void write(byte[] bys,int index,int len):一次写一个字节数组的一部分

                |--FileOutputStream
                |--BufferedOutputStream
    |--字符流
        |--字符输入流
            Reader
                int read():一次读取一个字符
                int read(char[] chs):一次读取一个字符数组

                |--InputStreamReader
                    |--FileReader
                |--BufferedReader
                    String readLine():一次读取一个字符串
        |--字符输出流
            Writer
                void write(int ch):一次写一个字符
                void write(char[] chs,int index,int len):一次写一个字符数组的一部分

                |--OutputStreamWriter
                    |--FileWriter
                |--BufferedWriter
                    void newLine():写一个换行符

                    void write(String line):一次写一个字符串

案例- - - -复制多极文件夹

/*
 * 
 * 数据源:E:\JavaSE\day21\code\demos
 * 目的地:E:\\
 * 
 * 分析:
 *      A:封装数据源File
 *      B:封装目的地File
 *      C:判断该File是文件夹还是文件
 *          a:是文件夹
 *              就在目的地目录下创建该文件夹
 *              获取该File对象下的所有文件或者文件夹File对象
 *              遍历得到每一个File对象
 *              回到C
 *          b:是文件
 *              就复制(字节流)
 */
public class CopyFoldersDemo {
    public static void main(String[] args) throws IOException {
        // 封装数据源File
        File srcFile = new File("E:\\JavaSE\\day21\\code\\demos");
        // 封装目的地File
        File destFile = new File("E:\\");

        // 复制文件夹的功能
        copyFolder(srcFile, destFile);
    }

    private static void copyFolder(File srcFile, File destFile)
            throws IOException {
        // 判断该File是文件夹还是文件
        if (srcFile.isDirectory()) {
            // 文件夹
            File newFolder = new File(destFile, srcFile.getName());
            newFolder.mkdir();

            // 获取该File对象下的所有文件或者文件夹File对象
            File[] fileArray = srcFile.listFiles();
            for (File file : fileArray) {
                copyFolder(file, newFolder);
            }
        } else {
            // 文件
            File newFile = new File(destFile, srcFile.getName());
            copyFile(srcFile, newFile);
        }
    }

    private static void copyFile(File srcFile, File newFile) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
                srcFile));
        BufferedOutputStream bos = new BufferedOutputStream(
                new FileOutputStream(newFile));

        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = bis.read(bys)) != -1) {
            bos.write(bys, 0, len);
        }

        bos.close();
        bis.close();
    }
}

案例:把a.txt内容复制到当前的b.txt中—-Bufferd-w-r

/*
*
* 数据源:
* a.txt – 读取数据 – 字符转换流 – InputStreamReader – FileReader – BufferedReader
* 目的地:
* b.txt – 写出数据 – 字符转换流 – OutputStreamWriter – FileWriter – BufferedWriter
*/

public class CopyFileDemo2 {
    public static void main(String[] args) throws IOException {
        // 封装数据源
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        // 封装目的地
        BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));

        // 读写数据
        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        // 释放资源
        bw.close();
        br.close();
    }


Properties
----------

/*
 * Properties:属性集合类。是一个可以和IO流相结合使用的集合类。
 * Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。 
 * 
 * 是Hashtable的子类,说明是一个Map集合。
 */
public class PropertiesDemo {
    public static void main(String[] args) {
        // 作为Map集合的使用
        // 如果没有<>,就说明该类不是一个泛型类,在使用的时候就不能加泛型

    Properties prop = new Properties();
        // 添加元素
        prop.put("it002", "hello");
        prop.put("it001", "world");
        prop.put("it003", "java");

        // System.out.println("prop:" + prop);

        // 遍历集合
        Set<Object> set = prop.keySet();
        for (Object key : set) {
            Object value = prop.get(key);
            System.out.println(key + "---" + value)
    /*
     * 特殊功能:
     * public Object setProperty(String key,String value):添加元素
     * public String getProperty(String key):获取元素
     * public Set<String> stringPropertyNames():获取所有的键的集合
     */
    public class PropertiesDemo2 {
    public static void main(String[] args) {
        // 创建集合对象
        Properties prop = new Properties();
        // 添加元素
        prop.setProperty("张三", "30");
        prop.setProperty("李四", "40");
        prop.setProperty("王五", "50");

        // public Set<String> stringPropertyNames():获取所有的键的集合
        Set<String> set = prop.stringPropertyNames();
        for (String key : set) {
            String value = prop.getProperty(key);
            System.out.println(key + "---" + value);
        }
    }

    /*
      class Hashtalbe<K,V> { public V put(K key,V value) { ... } }
       class Properties extends Hashtable { public V setProperty(String key,String
      value) { return put(key,value); } }
     */

打印流
===

    /*
     * 需求:DataStreamDemo.java复制到Copy.java中
     * 数据源:
     *      DataStreamDemo.java -- 读取数据 -- FileReader -- BufferedReader
     * 目的地:
     *      Copy.java -- 写出数据 -- FileWriter -- BufferedWriter -- PrintWriter
     */
    public class CopyFileDemo {
        public static void main(String[] args) throws IOException {
            // 以前的版本
            // 封装数据源
            // BufferedReader br = new BufferedReader(new FileReader(
            // "DataStreamDemo.java"));
            // // 封装目的地
            // BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));
            //
            // String line = null;
            // while ((line = br.readLine()) != null) {
            // bw.write(line);
            // bw.newLine();
            // bw.flush();
            // }
            //
            // bw.close();
            // br.close();

        // 打印流的改进版
        // 封装数据源
        BufferedReader br = new BufferedReader(new FileReader(
                "DataStreamDemo.java"));
        // 封装目的地
        PrintWriter pw = new PrintWriter(new FileWriter("Copy.java"), true);

        String line = null;
        while((line=br.readLine())!=null){
            pw.println(line);
        }

        pw.close();
        br.close();
    }
}



序列化流
----

/*
 * NotSerializableException:未序列化异常
 * 
 * 类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。
 * 该接口居然没有任何方法,类似于这种没有方法的接口被称为标记接口。
 * 
 * java.io.InvalidClassException: 
 * cn.itcast_07.Person; local class incompatible: 
 * stream classdesc serialVersionUID = -2071565876962058344, 
 * local class serialVersionUID = -8345153069362641443
 * 
 * 为什么会有问题呢?
 *      Person类实现了序列化接口,那么它本身也应该有一个标记值。
 *      这个标记值假设是100。
 *      开始的时候:
 *      Person.class -- id=100
 *      wirte数据: oos.txt -- id=100
 *      read数据: oos.txt -- id=100   
 * 
 *      现在:
 *      Person.class -- id=200
 *      wirte数据: oos.txt -- id=100
 *      read数据: oos.txt -- id=100
 * 我们在实际开发中,可能还需要使用以前写过的数据,不能重新写入。怎么办呢?
 * 回想一下原因是因为它们的id值不匹配。
 * 每次修改java文件的内容的时候,class文件的id值都会发生改变。
 * 而读取文件的时候,会和class文件中的id值进行匹配。所以,就会出问题。
 * 但是呢,如果我有办法,让这个id值在java文件中是一个固定的值,这样,你修改文件的时候,这个id值还会发生改变吗?
 * 不会。现在的关键是我如何能够知道这个id值如何表示的呢?
 * 不用担心,你不用记住,也没关系,点击鼠标即可。
 * 你难道没有看到黄色警告线吗?
 * 
 * 我们要知道的是:
 *      看到类实现了序列化接口的时候,要想解决黄色警告线问题,就可以自动产生一个序列化id值。
 *      而且产生这个值以后,我们对类进行任何改动,它读取以前的数据是没有问题的。
 * 
 * 注意:
 *      我一个类中可能有很多的成员变量,有些我不想进行序列化。请问该怎么办呢?
 *      使用transient关键字声明不需要序列化的成员变量
 */
public class Person implements Serializable {
    private static final long serialVersionUID = -2071565876962058344L;

    private String name;

    // private int age;

    private transient int age;

    // int age;

    public Person() {
        super();
    }

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}
    /*
     * 序列化流:把对象按照流一样的方式存入文本文件或者在网络中传输。对象 -- 流数据(ObjectOutputStream)
     * 反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象。流数据 -- 对象(ObjectInputStream)
     */
    public class ObjectStreamDemo {
        public static void main(String[] args) throws IOException,
                ClassNotFoundException {
            // 由于我们要对对象进行序列化,所以我们先自定义一个类
            // 序列化数据其实就是把对象写到文本文件
            // write();
        read();
    }

        private static void read() throws IOException, ClassNotFoundException {
            // 创建反序列化对象
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                    "oos.txt"));

            // 还原对象
            Object obj = ois.readObject();

            // 释放资源
            ois.close();

            // 输出对象
            System.out.println(obj);
        }

        private static void write() throws IOException {
            // 创建序列化流对象
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
                    "oos.txt"));

            // 创建对象
            Person p = new Person("林青霞", 27);

            // public final void writeObject(Object obj)
            oos.writeObject(p);

            // 释放资源
            oos.close();
        }
    }


(1)字节打印流,字符打印流
    (2)特点:
        A:只操作目的地,不操作数据源
        B:可以操作任意类型的数据
        C:如果启用了自动刷新,在调用println()方法的时候,能够换行并刷新
        D:可以直接操作文件
            问题:哪些流可以直接操作文件呢?
            看API,如果其构造方法能够同时接收File和String类型的参数,一般都是可以直接操作文件的
    (3)复制文本文件

BufferedReader br = new BufferedReader(new FileReader("a.txt"));
    PrintWriter pw = new PrintWriter(new FileWriter("b.txt"),true);     
    String line = null;
    while((line=br.readLine())!=null) {
        pw.println(line);
    }
    pw.close();
    br.close();

“`

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值