Java---I/O入门

Java I/O 对文件操作,其实是通过操作系统进行操作的。

File

统计文件数量及大小

package file;


import java.io.File;

// 统计某路径(文件夹)下文件数、文件夹数及所占空间大小(Byte)
public class DirCount {
    private String path;
    private File file;

    private long len;
    private long dirCount = -1;  // 去掉文件夹自身
    private long fileCount;

    public DirCount(String path) {
        this.path = path;
        this.file = new File(path);
        count(file, 0);
    }
    private void count(File file, int deep) {
        for(int i = 0; i < deep; i++) {
            System.out.print("-");
        }
        if(null == file || !file.exists()) {
            return;
        }else if(file.isDirectory()) {
            dirCount++;
            System.out.println(file.getAbsolutePath());
            for(File dir : file.listFiles()) {
                count(dir, deep+1);
            }
        }else {
            System.out.println(file.getAbsolutePath());
            len += file.length();
            fileCount++;
        }
    }

    public long getLen() {
        return len;
    }
    public long getDirSize() {
        return dirCount;
    }
    public long getFileSize() {
        return fileCount;
    }

    public static void main(String[] args) {
        DirCount dirCount = new DirCount(".");
        System.out.println(dirCount.getLen());
        System.out.println(dirCount.getDirSize());
        System.out.println(dirCount.getFileSize());
    }
}

字符集及编码解码

package file;

import java.io.UnsupportedEncodingException;

public class ContentDecode {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String s = "您好a";
        byte[] bytes = s.getBytes();    // 编码:字符 -> 字节
        System.out.println(bytes.length);   // 7 (UTF-8,汉字占 3 字节,数字和英文字母占 1 字节)

        s = new String(bytes, 0, bytes.length, "UTF-8");
        System.out.println(s);  // 您好a
        s = new String(bytes, 0, bytes.length-1, "UTF-8");
        System.out.println(s);  // 您好

        s = new String(bytes, 0, bytes.length-2, "UTF-8");
        System.out.println(s);  // 乱码(字节数量有问题)

        s = new String(bytes, 0, bytes.length-2, "UTF-16");
        System.out.println(s);  // 乱码(编码和解码所用字符集不一致)
    }
}

I/O

I/O 标准步骤

四大 I/O 流类,InputStream/OutputStream(字节) + Reader/Writer(字符)

// 输入流

package io;

import java.io.*;

public class IOTest01 {
    public static void main(String[] args) {
        // 1. 找到源
        File file = new File("xxx.txt");    // xxx.txt 在工程根目录下。。
        InputStream inputStream = null;
        try {
            // 2. 选择流
            inputStream = new FileInputStream(file);
//            int tmp;
//            // 3. 读/写
//            while ((tmp = inputStream.read()) != -1) {    // 每次读取 1 字节
//                System.out.println((char)tmp);
//            }
            byte[] tmp = new byte[3];   // 每次读 3 字节
            // 3. 读/写
            while (inputStream.read(tmp) != -1) {
                String s = new String(tmp, 0, tmp.length);
                System.out.println(s);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(null != inputStream) {
                    // 4. 关闭(告诉操作系统可以关闭文件了)
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


文件拷贝(字节流)

package io;

import java.io.*;

public class IOTest02 {
    public static void main(String[] args) {
        File src = new File("src.txt"); // src.txt 在工程根目录下
        File out = new File("out.txt");
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            inputStream = new FileInputStream(src);
            outputStream = new FileOutputStream(out, true); // 是否是追加方式写

            byte[] tmp = new byte[3];	// 这么读取中文,不同字符集编码方式可能乱码
            while (inputStream.read(tmp) != -1) {
                outputStream.write(tmp, 0, tmp.length);
            }
            outputStream.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(null != outputStream) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                if(null != inputStream) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

文件拷贝(字符流)

package io;

import java.io.*;

public class IOTest02 {
    public static void main(String[] args) {
        File src = new File("src.txt"); // src.txt 在工程根目录下
        File out = new File("out.txt");
        Reader reader = null;
        Writer writer = null;
        try {
            reader = new FileReader(src);
            writer = new FileWriter(out, true); // 是否是追加方式写

            char[] tmp = new char[3];	// 不会中文乱码
            while (reader.read(tmp) != -1) {
                writer.write(tmp, 0, tmp.length);
            }
            writer.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(null != writer) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                if(null != reader) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

ByteArrayOutputStream/ByteArrayInputStream

字节数组输入输出流是和内存打交道,不能直接读写文件,这有别于文件输入输出流(跟文件打交道,其实是通过操作系统)。

装饰器设计模式

package io;

/**
 * 装饰器模式(以对原味咖啡加糖、加牛奶为例,方法增强)
 * 1. 抽象组件
 * 2. 具体组件(继承抽象组件)
 * 3. 抽象装饰器(继承抽象组件,并组合进抽象组件)
 * 4. 具体装饰器(继承抽象装饰器)
 */

abstract class Drink {
    abstract String info();
    abstract double cost();
}

class Coffee extends Drink {
    public String info() {
        return "原味咖啡";
    }
    public double cost() {
        return 10.0;
    }
}

abstract class Decorate extends Drink {
    private Drink drink;
    public Decorate(Drink drink) {
        this.drink = drink;
    }
    @Override
    public String info() {
        return drink.info();
    }
    @Override
    public double cost() {
        return drink.cost();
    }
}

class MilkCoffee extends Decorate {
    public MilkCoffee(Drink drink) {
        super(drink);
    }
    @Override
    public String info() {
        return super.info() + "加入牛奶";
    }
    @Override
    public double cost() {
        return super.cost() + 5.0;
    }
}
class SugarCoffee extends Decorate {
    public SugarCoffee(Drink drink) {
        super(drink);
    }
    @Override
    public String info() {
        return super.info() + "加入蔗糖";
    }
    @Override
    public double cost() {
        return super.cost() + 3.0;
    }
}

public class DecorateTest01 {
    public static void main(String[] args) {
        Drink coffee = new Coffee();
        Drink milkCoffee = new MilkCoffee(coffee);
        Drink sugarCoffee = new SugarCoffee(coffee);
        System.out.println(coffee.info() + "---" + coffee.cost());  // 原味咖啡---10.0
        System.out.println(milkCoffee.info() + "---" + milkCoffee.cost());  // 原味咖啡加入牛奶---15.0
        System.out.println(sugarCoffee.info() + "---" + sugarCoffee.cost());    // 原味咖啡加入蔗糖---13.0

        milkCoffee = new MilkCoffee(sugarCoffee);
        System.out.println(milkCoffee.info() + "---" + milkCoffee.cost());  // 原味咖啡加入蔗糖加入牛奶---18.0
    }
}

下图就是利用了装饰器设计模式的一些流类!装饰器流/处理流其实是对节点流的装饰。比如 BuffedInputStream 维护了一个缓冲区,搞一定数量的字节后一次性运输,提高性能。

一般地,BuffedInputStream 和 BuffedOutputStream 传入 InputStream 和 OutputStream 使用。BufferedReader 和 BufferedWriter 传入 Reader 和 Writer 使用。
在这里插入图片描述在这里插入图片描述

转换流

InputStreamReader 和 OutputStreamWriter,把字节流转为字符流。如果字节流全是文本,就可用使用这两个转换流,再用缓冲字符流包一下,很方便。

package io;

import java.io.*;

public class ConvertTest01 {
    public static void main(String[] args) {
        try (
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out))){

            String s = "";
            while (!(s = reader.readLine()).equals("exit") ) {
                writer.write(s);
                writer.newLine();
                writer.flush(); // 强制刷新,不然由于输入的内容少,达不到缓冲区大小,就不会进行写操作
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

package io;

import java.io.*;
import java.net.URL;

public class ConvertTest02 {
    public static void main(String[] args) {
        try (
            BufferedReader reader = new BufferedReader(
                                        new InputStreamReader(
                                                new URL("https://www.baidu.com").openStream(), "UTF-8"));
            BufferedWriter writer = new BufferedWriter(
                                        new OutputStreamWriter(
                                                new FileOutputStream("baidu.html"), "UTF-8"))){

            String s = "";
            while ((s = reader.readLine()) != null) {
                writer.write(s);
                writer.newLine();
            }
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

数据流

DataInputStream 和 DataOutputStream,数据读写字节流,可以按照实际基本数据类型和字符串读写。

package io;

import java.io.*;

public class DataTest {
    public static void main(String[] args) throws IOException{
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        DataOutputStream dataOutputStream = new DataOutputStream(
                                                    new BufferedOutputStream(byteArrayOutputStream));
        dataOutputStream.writeBoolean(true);
        dataOutputStream.writeInt(123);
        dataOutputStream.writeUTF("hello");
        dataOutputStream.flush();   // 注意强制刷新下。。

        byte[] bytes = byteArrayOutputStream.toByteArray();

        DataInputStream dataInputStream = new DataInputStream(
                                                new BufferedInputStream(
                                                        new ByteArrayInputStream(bytes)));
        // 读取顺序和写入顺序要一致
        boolean flag = dataInputStream.readBoolean();
        int i = dataInputStream.readInt();
        String s = dataInputStream.readUTF();

        System.out.println(flag);
        System.out.println(i);
        System.out.println(s);
    }
}

对象流

对象流类似数据流,比数据流更强大些,读写对象!

package io;

import java.io.*;

class Employee implements Serializable{
    private String name;
    private transient String pwd;   // 该字段不序列化

    public Employee(String name, String pwd) {
        this.name = name;
        this.pwd = pwd;
    }

    public String getName() {
        return name;
    }

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

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "name=" + name + ", pwd=" + pwd;
    }
}

public class ObjectTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        // 序列化(对象-->字节流)
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(
                                                    new BufferedOutputStream(byteArrayOutputStream));
        objectOutputStream.writeBoolean(true);
        objectOutputStream.writeInt(123);
        objectOutputStream.writeUTF("hello");
        objectOutputStream.writeObject(new Employee("李明", "ming")); // 写入的对象要实现 Serializable
        objectOutputStream.flush();   // 注意强制刷新下。。

        byte[] bytes = byteArrayOutputStream.toByteArray();

        // 反序列化(字节流-->对象)
        ObjectInputStream objectInputStream = new ObjectInputStream(
                                                new BufferedInputStream(
                                                        new ByteArrayInputStream(bytes)));
        // 读取顺序和写入顺序要一致
        boolean flag = objectInputStream.readBoolean();
        int i = objectInputStream.readInt();
        String s = objectInputStream.readUTF();

        System.out.println(flag);
        System.out.println(i);
        System.out.println(s);

        Object employee = objectInputStream.readObject();
        if(employee instanceof Employee) {
            Employee employeeObj = (Employee) employee;
            System.out.println(employeeObj);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值