Java 【I/O】流 学习

【I/O】流学习笔记

【I/O】数据流

数据输出流使应用程序以便携式方式将原始Java数据类型写入输出流,然后应用程序可以使用数据输入流来读取数据。

I/O流只能读写文件,不能读写文件夹。

import java.io.*;

/**
 * 数据流:
 * 1.先写出后读取
 * 2.读取的顺序与写出保持一致
 */
public class Datatest {
    public static void main(String[] args) throws IOException {
        //写出
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        DataOutputStream dataOutputStream = new DataOutputStream(new BufferedOutputStream(byteArrayOutputStream));
        //操作
        dataOutputStream.writeUTF("编码心酸泪");
        dataOutputStream.writeInt(18);
        dataOutputStream.writeBoolean(false);
        dataOutputStream.writeChar('a');
        dataOutputStream.flush();
        byte []datas = byteArrayOutputStream.toByteArray();
        //读取
        DataInputStream dataInputStream = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));
        //顺序与写出一致
        String msg = dataInputStream.readUTF();
        int age = dataInputStream.readInt();
        boolean flag = dataInputStream.readBoolean();
        char ch = dataInputStream.readChar();
        System.out.println(flag);
    }
}

输入流:数据源到程序(inputstream、reader读进来)

输出流:程序到目的地(outputstream、writer写出去)

流分类

  1. 按方向分:输入流 输出流
  2. 按功能分:节点流 处理流

节点流:可以直接从数据源或目的地读写数据

处理流(包装流):不直接连接到数据源或目的地,是其他流进行封装。目的主要是简化操作和提高性能。

节点流和处理流的关系:

  1. 节点流处于I/O操作的第一线,所有操作必须通过他们进行;

  2. 处理流可以对其他流进行处理(提高效率或操作灵活性)

  3. 按数据分:字节流 字符流

字节流:按照字节读取数据

字符流:按照字符读取数据,因为文件编码的不同,从而有了对字符进行高效操作的字符流对象

原理:底层还是基于字节流操作,自动搜寻了指定的码表。

File类

public class PathDemo01 {
    /**
     * \ / 名称分隔符 separator
     *
     */
    public static void main(String[] args) {
        String path = "F:\\Java一组项目";
        System.out.println(File.separatorChar);
    }
    /**
     * 建议:
     * 1.path = "F:\\Java一组项目";
     * System.out.println(path);
     * 2.常量拼接
     * path = "F:"+separator+"\\Java一组项目";
     *  System.out.println(path);
     */
}
import java.io.File;

public class FileDemo01 {
    /**
     * 构造File对象
     */
    public static void main(String[] args) {
        String path = "D:/java300/IO_study01/IO.png";
        //1.构造file对象
        File src = new File(path);
        System.out.println(src.length());
        //2.构建file对象
        src = new File("D:/java300/IO_study01","IO.png");
        src = new File("D:/java300/","IO_study01/IO.png");
        System.out.println(src.length());
        //3.构建file对象
        src = new File(new File("D:/java300/IO_study01"),"IO.png");
        System.out.println(src.length());
    }
}

import java.io.File;

public class FileDemo02 {
    /**
     * 构建file对象
     * 相对路径与绝对路径
     * 1.存在盘符:绝对路径
     * 2.不存在盘符:相对路径,相对于当前目录  user.dir
     */
    public static void main(String[] args) {
        String path = "D:/java300/IO_study01/IO.png";
        //绝对路径
        File src = new File(path);
        System.out.println(src.getAbsoluteFile());

        //相对路径
        System.getProperty("user.dir");
        src = new File("IO.png");
        System.out.println(src.getAbsoluteFile());

        //构建一个不存在的文件
        src = new File("aaa/IO2.png");
        System.out.println(src.getAbsoluteFile());
    }
}

File 类API
import java.io.File;
import java.io.IOException;

public class FileDemo05 {
    /**
     * 其他信息
     * length():文件的字节数
     * createNewFile() :不存在才创建 存在创建成功
     * delete():删除已经存在的文件
     */
    public static void main(String[] args) throws IOException {
        File src = new File("D:/java300/IO_study01/IO.txt");
        boolean flag = src.createNewFile();
        System.out.println(flag);

        System.out.println("------------");
        //不是文件夹
        src = new File("D:/java300/IO_study02");
        flag = src.createNewFile();
        System.out.println(flag);

        flag = src.delete();
        System.out.println(flag);

        //补充  con con3...  是操作系统的设备名 ,不能正确创建。
        src = new File("D:/java300/IO_study01/con");
        src.createNewFile();
    }

}
File 文件夹创建
import java.io.File;

/**
 * 创建目录
 * 1.mkdir():确保上级目录存在,不存在则创建失败
 * 2.mkdirs():上级目录可以不存在,不存在一同来创建。
 * 列出下一级
 * 1.list():列出下级名称
 * 2.listFiles():列出下级File对象
 * 列出所有的盘符 listroots()
 */
public class DirDemo01 {
    public static void main(String[] args) {
        File dir= new File("D:/java300/IO_study01/dir/test");
        //创建目录mkdirs()
        boolean flag = dir.mkdirs();//mkdirs()常用,推荐使用
        System.out.println(flag);
        //创建目录 mkdir()
        dir = new File("D:/java300/IO_study01/dir/test2");
        flag = dir.mkdirs();
        System.out.println(flag);

        //列出下级名称
        String [] subNames = dir.list();
        for (String s:subNames){
            System.out.println(s);
        }
        //下级对象 ListFiles()
        File[] subFiles = dir.listFiles();
        for (File s:subFiles){
            System.out.println(s.getAbsoluteFile());
        }

        //所有盘符
        File[] roots = dir.listRoots();
        for (File r:roots){
            System.out.println(r.getAbsoluteFile());
        }


    }
}

递归的复习
public class DirDemo02 {
 /** 
 *递归:方法自己调用自己(递归会一直占用内存)
 * 递归头:何时结束递归
 * 递归体:重复调用
 */
    public static void main(String[] args) {
        printTen(1);
    }
    //打印1-10数字
    public static void printTen(int n){
        if(n>10) {
            return;
        }
        System.out.println(n);
        printTen(n+1);//方法自己调用自己
    }
}

文件编码与解码

字符到字节:编码

字节到字符:解码

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;

/**
 * 编码:字符串—-->字节
 * 解码:字节--->字符串
 */
public class ContentEncode {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String msg = "性命生命使命";
        //编码
        byte[]datas = msg.getBytes();//默认使用工程的字符集
        System.out.println(datas.length);
        //编码:其他字符集
        datas = msg.getBytes(StandardCharsets.UTF_16LE);
        System.out.println(datas.length);

        datas = msg.getBytes("GBK");
        System.out.println(datas.length);

        //解码:字符串
        msg = new String(datas,0, datas.length-2,"utf-8");
        System.out.println(msg);
        /**
         * 乱码问题:
         * 1.字节数不够
         * msg = new String(datas,0, datas.length-2,"utf-8");
         * System.out.println(msg);
         * msg = new String(datas,0, datas.length-1,"utf-8");
         * System.out.println(msg);
         * 2.字符集不统一
         * msg = new String(datas,0, datas.length-1,"GBK");
         * System.out.println(msg);
         */

    }
}

I/O流标准步骤

import java.io.*;
/**
 * 第一个程序:理解操作步骤
 * 1.创建源
 * 2.选择流
 * 3.操作
 * 4.释放资源
 */
public class IOTest02 {
    public static void main(String[] args) {
        //1.创建源
        File src = new File("abc.txt");
        //2.选择流
        InputStream is = null;
        try {
             is = new FileInputStream(src);
            //3.操作(读取)
            int temp;
            while ((temp = is.read()) != -1) {
                System.out.println((char) temp);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.释放资源
            try {
                if (null!=is) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
            }

I/O文件字节流

import javax.imageio.IIOException;
import java.io.*;

/**
 * 文件字节输出流
 * 1.创建源
 * 2.选择流
 * 3.操作
 * 4.释放资源
 */
public class IOTest04 {
    public static void main(String[] args) {
        //1.创建源
        File dest = new File("dest.txt");
        //2.选择流
        OutputStream os = null;
        try {
            os = new FileOutputStream(dest, true);
            //3.操作(写出)
            String msg = "change\r\n";
            byte[] datas = msg.getBytes();//字符串-->字节数组(编码)
            os.write(datas, 0, datas.length);
            os.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.释放资源
            try {
                if (null != os) {
                    os.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

I/O文件拷贝

package cn.sxt.gao;
import java.io.*;

/**
 * 文件拷贝:文件字节输入、输出流
 * 思考:利用递归 制作文件夹的拷贝和删除
 */
public class Copy {
    public static void main(String[] args) {
        copy("src/com/sxt/io/Copy.java","copy.txt");
    }

    public static void copy(String srcPath,String destPath){
        //1.创建源
        File src = new File("p.png");//源头
        File dest = new File("pcopy.png");//目的地
        //2.选择流
        InputStream is = null;
        OutputStream os = null;
        try {
            is = new FileInputStream(src);
            os = new FileOutputStream(dest);
            //3.操作(分段读取)
            byte[]flush  = new byte[1024];//缓冲容器
            int len = -1;//接受长度
            while ((len=is.read(flush))!=-1){
                os.write(flush,0,len);
            }
            os.flush();
            }catch (FileNotFoundException e ){
            e.printStackTrace();
            }catch (IOException e){
            e.printStackTrace();
            }finally {
                //4.释放资源,分开关闭,先打开的后关闭
                try {
                    if (null!=os){
                        os.close();
                    }
                }catch (Exception e ){
                }
                try {
                    if (null != is){
                        is.close();
                    }
                }catch (IOException e){
                    e.printStackTrace();
                }
        }
        }
}

public class Copy {
    public static void main(String[] args) {
        copy2("src/com/sxt/io/Copy.java","copy.txt");
    }

    public static void copy2(String srcPath,String destPath){
        //1.创建源
        File src = new File("p.png");//源头
        File dest = new File("pcopy.png");//目的地
        //2.选择流 内部会自动释放
        try (InputStream is= new FileInputStream(src);OutputStream os = new FileOutputStream(dest)){
            //3.操作(分段读取)
            byte[]flush  = new byte[1024];//缓冲容器
            int len = -1;//接受长度
            while ((len=is.read(flush))!=-1){
                os.write(flush,0,len);
            }
            os.flush();
            }catch (FileNotFoundException e ){
            e.printStackTrace();
            }catch (IOException e){
            e.printStackTrace();
            }
        }
        }

思考题

利用递归实现文件夹的拷贝

执行文件拷贝操作时从键盘接受两个文件夹路径,并把其中一个文件夹夹包含内容拷贝到另一个文件夹中。

删除文件夹首先要获取该文件夹下的所有文件和文件夹数组,然后遍历该数组,在遍历过程中若判断是文件就直接删除,如果是文件夹则递归调用该删除方法。循环结束后,要把空文件夹删除。

注意:被删除的文件夹是不会进入到回收站的,删除后难以恢复,要谨慎操作

import javax.imageio.IIOException;
import java.io.*;
import java.util.Scanner;

public class Copy1 {
    public static void main(String[] args) {
        File src = getDir();
        File dest = getDir();
        deleteAll(getDir());
        try {
            //判断是否是一个目录
            if (src.equals(dest)){
                System.out.println("目标文件夹是源文件夹的子文件夹");
            }else {
                copy(src,dest);
            }
        }catch (IOException e) {
            e.printStackTrace();
        }
        }
 //调用删除方法,还需要一个从控制台直接输入获取文件路径的方法。
    private static File getDir() {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入文件夹的路径");
        while (true){
            String nextLine = scanner.nextLine();
            File dir = new File(nextLine);
            if (!dir.exists()){
                System.out.println("抱歉!输入的路径不存在,请重新输入");
            }else if (dir.isFile()){
                System.out.println("抱歉,输入的是文件,请重新输入");
            }else {
                return dir;
            }
        }
    }

    static void copy(File src,File dest) throws IOException {
        File newDir = new File(dest,src.getName());
        newDir.mkdirs();

        File []subFiles  = src.listFiles();
        for (File subFile : subFiles){
            if (subFile.isFile()){
                BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(subFile));
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(new File(newDir,subFile.getName())));
                int b;
                while ((b =bufferedInputStream.read())!= -1){
                    bufferedOutputStream.write(b);
                }
                bufferedInputStream.close();
                bufferedOutputStream.close();
            }else {
                copy(subFile,newDir);
            }
        }
    }
    static void deleteAll(File file){
        if (file.isDirectory()){
            File [] listFiles = file.listFiles();
            for (File file1:listFiles){
                deleteAll(file);
            }
            file.delete();
        }else {
            file.delete();
        }
    }
}

删除文件夹时遇到的异常

StackOverflowError
原因 : 函数调用栈太深了,注意代码中是否有了循环调用方法而无法退出的情况

当执行时栈的深度大于了规定的深度,就会抛出StackOverflowError错误。

B`Z_S@OIOELJJ@W5U6GJPYE

IO文件流

import java.io.*;
import java.util.Locale;

/**
 * 四个步骤:分段读取 文件字符输入流
 * 1.创建源
 * 2.选择流
 * 3.操作
 * 4.释放资源
 */
public class IOTest05 {
    public static void main(String[] args) {
        //1.创建源
        File dest = new File("dest.txt");
        //2.选择流
        Writer writer = null;
        try {
            writer = new FileWriter(dest);
            //3.操作(写出)
            //写法一:
            //String msg = "IO is so easy\r\n尚学堂欢迎你";
            //char[] datas = msg.toCharArray();//字符串-->字节数组
            //writer.write(datas, 0, datas.length);
            //写法二:
            /*String msg = "IO is so easy\r\n尚学堂欢迎你";
            writer.write(msg);
            writer.write("add");
            writer.flush();*/
            //写法三:
            writer.append("IO is so easy\\r\\n").append("尚学堂欢迎你");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.释放资源
            try {
                if (null != writer) {
                    writer.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

IO字节数组流

字节数组输入流
import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * 字节数组输入流
 * 1.创建源 :源头数字节数组,不要太大
 * 2.选择流
 * 3.操作
 * 4.释放资源:可以不用处理
 */
public class IOTest07 {
    public static void main(String[] args) {
        //1.创建源
        byte[] src = "talk is cheap show me the code".getBytes();
        //2.选择流
        InputStream is = null;
        try {
            is = new ByteArrayInputStream(src);
            //3.操作(分段读取)
            byte[] flush = new byte[5];//缓冲容器
            int len = -1;//接受长度
            while ((len = is.read(flush)) != -1) {
                //字节数组-->字符串(解码)
                String str = new String(flush, 0, len);
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.释放资源
            try {
                if (null != is) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

字节数组输出流
import java.io.*;
import java.util.Scanner;

/**
 * 字节数组输出流
 * 1.创建源 : 内部维护
 * 2.选择流 : 不关联源
 * 3.操作 : (写出内容)
 * 4.释放资源:可以不用
 * 获取数据 :toByteArray()
 */
public class IOTest08 {
    public static void main(String[] args) {
        //1.创建源
        byte [] dest = null;
        //2.选择流(新增方法)
        ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            //3.操作(写出)
            String msg = "show me the code";
            byte[] datas = msg.getBytes();//字符串-->字节数组(编码)
            byteArrayOutputStream.write(datas, 0, datas.length);
            byteArrayOutputStream.flush();
            //获取数据
            dest = byteArrayOutputStream.toByteArray();
            System.out.println(dest.length+"-->"+new String(dest,0,byteArrayOutputStream.size()));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.释放资源
            try {
                if (null != byteArrayOutputStream) {
                    byteArrayOutputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

思考题

IO之对接流样例,图片读到字节数组中,再写出到文件实现拷贝

/**
 * 1.图片读取到字节数组中
 * 1)图片到程序  FileInputStream
 * 2)程序到字节数组  ByteArrayOutputStream
 * 2.字节数组写出到文件
 * 1)字节数组读取到程序中 ByteArrayInputStream
 * 2)程序写出到文件  FileOutputStream
 */
import java.io.*;

public class IOTest09 {
    public static void main(String[] args) {
        byte []datas = fileToByteArray("C:\\Users\\Lenovo\\IdeaProjects\\learn\\out\\production\\learn\\cn\\sxt//girl.png");
        System.out.println(datas.length);
        byteArrayToFile(datas,"copygirl.png");
    }
    public static byte[] fileToByteArray (String filepath) {
        File src = new File(filepath);
        byte[] dest = null;
        InputStream is = null;
        ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            is = new FileInputStream(src);
            byteArrayOutputStream = new ByteArrayOutputStream();
            byte [] buffer = new byte[1024*10];
            int len = -1;
            while ((len= is.read(buffer))!=-1){
                byteArrayOutputStream.write(buffer,0,len);//写出到字节数组中
            }
            byteArrayOutputStream.flush();
            return byteArrayOutputStream.toByteArray();
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            if (null!=is){
                try {
                    is.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
            if(null!=byteArrayOutputStream){
                try {
                    byteArrayOutputStream.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public static void byteArrayToFile(byte[] datas,String destpath){
        File dest= new File(destpath);
        OutputStream os = null;
        try {
            os  = new FileOutputStream(dest);
            os.write(datas,0,datas.length);
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            if (null!=os){
                try {
                    os.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
}

IO工具类

import java.io.*;

/**
 * 1.封装拷贝
 * 2.封装释放资源
 */
public class FileUtils {
    public static void main(String[] args) {
        //文件到文件
        try {
            InputStream is = new FileInputStream("abc.txt");
            OutputStream os = new FileOutputStream("abc-copy.txt");
            copy(is, os);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //文件到字节数组
        byte[] datas = null;
        try {
            InputStream is = new FileInputStream("copygirl.png");
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            copy(is, os);
            datas = os.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //字节数组到文件
        try {
            InputStream is = new ByteArrayInputStream(datas);
            OutputStream os = new FileOutputStream("p-copy.png");
            copy(is, os);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
//此部分代码可简化,具体参考下方。
        /**
         * 对接输入输出流
         * @param is
         * @param os
         */
        public static void copy(InputStream is,OutputStream os) {
            try {
                //3.操作(分段读取)
                byte[] flush = new byte[1024];//缓冲容器
                int len = -1;//接受长度
                while ((len = is.read(flush)) != -1) {
                    os.write(flush, 0, len);
                }
                os.flush();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //4.释放资源,分开关闭,先打开的后关闭
                close(is,os);
            }
        }
        //关闭输入输出流()可删去
    public static void close(InputStream is,OutputStream os){
        try {
            if (null != os) {
                os.close();
            }
        } catch (Exception e) {
        }
        try {
            if (null != is) {
                is.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 释放资源
     * @param ios
     */
    public static void close(Closeable...ios){
            for (Closeable io:ios){
                try {
                    if (null!= io){
                        io.close();
                    }
                }catch (IOException e){
                    e.printStackTrace();
                }

            }

    }
    }

使用try…with…resource简化代码
/**
     * 对接输入输出流
     * try ... with...resource
     * @param is
     * @param os
     */
    public static void copy(InputStream is, OutputStream os) {
        try (is;os){
            //3.操作(分段读取)
            byte[] flush = new byte[1024];//缓冲容器
            int len = -1;//接受长度
            while ((len = is.read(flush)) != -1) {
                os.write(flush, 0, len);
            }
            os.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        }
    }

IO原理剖析

装饰器设计模式

GOF设计模式 解决复杂代码的固定攻略 追求高内聚低耦合的代码模式。

装饰器模式又名包装模式(Wrapper)模式。装饰器模式以对客户拓展对象的功能,是继承关系的一种替代方案。

装饰器相对于继承来说,可以在运行时保持原来接口不变的情况下动态的给原对象增加新功能,而继承是静态的。

理想的装饰器模式的装饰者接口跟组件接口应该保持一模一样,这样每次传入一个数据进去,都只对组件接口的各个方法增加功能,返回依旧由组件接口接收,这样调用同一个对象的同一个方法会有不同的实现,调用者完全不必要知道具体调用的是哪个对象,这个也称之为透明装饰器

/**
 * 实现放大器对声音的放大功能
 */
public class DecorateTest01 {
    public static void main(String[] args) {
        Person person = new Person();
        person.say();
        //装饰
        Amplifier amplifier = new Amplifier(person);
        amplifier.say();
    }
}
interface Say{
    void say();
}
class Person implements Say {
    //属性
    private int voice = 10;
    @Override
    public void say() {
        System.out.println("人的声音为" + this.getVoice());
    }

    public int getVoice() {
        return voice;
    }

    public void setVoice(int voice) {
        this.voice = voice;
    }
}
class Amplifier implements Say {
    private Person p;
    Amplifier(Person p){
        this.p = p;
    }
    public void say() {
        System.out.println("人的声音为" + p.getVoice()*100);
        System.out.println("噪音。。。");
    }
}

/**
 * 模拟咖啡
 * 1.抽象组件:需要装饰的抽象对象(接口或抽象父类)
 *给出一个抽象接口,已规范准备接收附加责任的对象
 * 2.具体组件:需要装饰的对象
 *定义一个将要接收附加责任的类
 * 3.抽象装饰类:包含了对抽象组件的引用以及装饰者共有的方法
 *持有一个构件(component)对象的实例,并定义一个与抽象构件接口一致的接  	*口。
 * 4.具体装饰类:被装饰的对象
 *负责够构件加上附加的责任。
 */
public class DecorateTest02 {
    public static void main(String[] args) {
        Drink coffee = new Coffee();
        Drink sugar  = new Sugar(coffee);//装饰
        System.out.println(sugar.info()+"-->"+sugar.cost());
        Drink milk = new Milk(coffee);//装饰
        System.out.println(milk.info()+"-->"+milk.cost());

        milk = new Milk(sugar);//装饰
        System.out.println(milk.info()+"-->"+milk.cost());
    }
}
//抽象组件
interface Drink{
        double cost();//费用
        String info();//说明
}
//具体组件
 class Coffee implements Drink{
    private String name = "原味咖啡";
    @Override
    public double cost() {
        return 10;
    }

    @Override
    public String info() {
        return name;
    }
}
//抽象装饰类
abstract class Decorate implements Drink {
    private Drink drink;

    public Decorate(Drink drink){
        this.drink = drink;
    }

    @Override
    public double cost() {
        return this.drink.cost();
    }

    @Override
    public String info() {
        return this.drink.info();
    }
}
//具体装饰类
class Milk extends Decorate{

    public Milk(Drink drink) {
        super(drink);
    }
    @Override
    public double cost(){
        return super.cost()*4;
    }

    @Override
    public String info() {
        return super.info()+"加入了牛奶";
    }
}
class Sugar extends Decorate{

        public Sugar(Drink drink) {
            super(drink);
        }
        @Override
        public double cost(){
            return super.cost()*2;
        }

        @Override
        public String info() {
            return super.info()+"加入了蔗糖";
        }
}

IO字节缓冲流

缓冲流的基本原理:在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

try (InputStream is= new BufferedInputStream(new FileInputStream(src));OutputStream os = new BufferedOutputStream ( new FileOutputStream(dest)))

IO字符缓冲流

import javax.annotation.processing.Filer;
import java.io.*;

public class CopyTxt {
    public static void main(String[] args) {
        copy("abc.txt","abc-copy.txt");
    }
    public static void copy(String srcPath,String destPath){
        //1.创建源
        File src = new File(srcPath);//源头
        File dest = new File(destPath);//目的地
        //2.选择流 内部会自动释放 try内部放的是声明
        try (BufferedReader br= new BufferedReader(new FileReader(src)); BufferedWriter bw = new BufferedWriter(new FileWriter(dest))){
            //3.操作(分段读取)
            String line = null;
            while((line = br.readLine())!=null){
                bw.write(line);
                bw.newLine();
            }
            bw.flush();
        }catch (FileNotFoundException e ){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

IO转换流

功能:

  1. 字节流转换成字符流(需要是纯文本文件)是字符集和字节流之间的桥梁。
  2. 指定字符集
  • 可对读取到的字节数据经过指定编码转换成字符

  • 可对读取到的字符数据经过指定编码转换成字节

解码:字节数组—》字符串 编码:字符串—》字节数组

字符流 = 字节流+编码集

import java.io.*;

/**
 * 转换流 InputStreamReader:字节数组转换成字符串 OutputStreamWriter:字符串转换成字节数组
 * 1.以字符流的形式操作字节流(纯文本的)
 * 2.指定字符集
 */
public class ConvertTest01 {
    public static void main(String[] args) {
        //操作System.in 和 System.out
        try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter writer =new BufferedWriter(new OutputStreamWriter(System.out));){
            //循环获取键盘的输入(exit退出) 输出此内容
            String msg = "";
            while (!msg.equals("exit")){
                msg = reader.readLine();//循环读取
                writer.write(msg);//循环写出
                writer.newLine();
                writer.flush();//强制刷新
            }
        }catch (IOException e){
            e.printStackTrace();
        }


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

public class ConvertTest02 {
    public static void main(String[] args) {
        //操作网络流 下载百度源代码
        try(InputStreamReader is =
                    new InputStreamReader(new URL("https://hao.360.com/?a1004").openStream(),"UTF-8");){

            int temp;
            while((temp = is.read())!=-1){
                System.out.println((char)temp);//字节数不够出现乱码
            }
        }catch (IOException e){
            System.out.println("操作异常");
        }

}
}

import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;

public class convertTest03 {
    public static void main(String[] args) {
        try (BufferedReader reader=new BufferedReader(new InputStreamReader(new URL("https://hao.360.com/?a1004").openStream(), StandardCharsets.UTF_8));
             BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("baidu.html"),"UTF-8"));){
        String msg;
        while((msg=reader.readLine())!=null){
            writer.write(msg);//字符集不统一出现乱码
            writer.newLine();
        }
        writer.flush();
        }catch (IOException e){
            System.out.println("操作异常");
        }
    }
}
//字节流转化成字符流
    public static void testISR(String path){
        try (BufferedWriter bw = new BufferedWriter(new FileWriter(path));
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in))){
            String line= "";
            while ((line=br.readLine())!=null){
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
            br.close();
            bw.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
//采用指定的编码读取一个文件
    public static void testReader(String path,String charset){
        try{
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path),charset));
            String line = "";
            while ((line = br.readLine())!=null){
                System.out.println(line);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
//采用指定的编码输出一个文件
    public static void testWriter(String path,String charset){
        try {
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path),charset));
            bw.write("轩轩最帅");
            bw.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    //字符串转换成字节数组
    public static void testOSW(String path){
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(path));
            //字符流—->字节流
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
            String line  = null;
            while ((line = br.readLine())!= null){
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
            bw.close();
            br.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

IO数据流

使用数据流的write UTF()和read UTF() 可以进行数据的*)格式化顺序读写

注意:要用 DataInputStream 读取一个文件,这个文件必须是由DataOutStream 写出的,否则会出现EOFException,因为DataOutputStream 在写出的时候回做一些特殊标记,只有DataInputStream 才能成功的读取。


/**
 * 数据流:
 * 1.写出后读取
 * 2.读取的顺序与写出保持一致
 * DataOutputStream
 * DataInputStream
 */
public class DataTest {
    public static void main(String[] args) throws IOException {
        //写出
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        DataOutputStream dataOutputStream = new DataOutputStream( new BufferedOutputStream(byteArrayOutputStream));
        //操作数据类型+数据
        dataOutputStream.writeUTF("轩轩我男神");
        dataOutputStream.writeInt(18);
        dataOutputStream.writeBoolean(false);
        dataOutputStream.writeChar('a');
        dataOutputStream.flush();
        byte []datas = byteArrayOutputStream.toByteArray();
        //读取
        DataInputStream dataInputStream = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(datas)));
        //顺序与写出一致
        String msg = dataInputStream.readUTF();
        int age = dataInputStream.readInt();
        boolean flag = dataInputStream.readBoolean();
        char ch = dataInputStream.readChar();
        System.out.println(flag);
    }
}


import java.io.*;

public class JavaIOTest {
    public static void main(String[] args) {
        write();
        read();
    }
    public static void read(){
        File file = new File("abc.txt");
        try (FileInputStream fileInputStream = new FileInputStream(file);
             DataInputStream dataInputStream = new DataInputStream(fileInputStream))
        {
            boolean b = dataInputStream.readBoolean();
            int i  = dataInputStream.readInt();
            String str= dataInputStream.readUTF();
            System.out.println("布尔值:"+b);
            System.out.println("整数:"+i);
            System.out.println("毕业去向:"+str);
        }catch (IOException e){
            e.printStackTrace();
        }
        }
        public static void write(){
            File file = new File("abc.txt");
            try (FileOutputStream fileoutStream = new FileOutputStream(file);
                 DataOutputStream dataoutputStream = new DataOutputStream(fileoutStream))
            {
                dataoutputStream.writeBoolean(true);
                dataoutputStream.writeInt(488);
                dataoutputStream.writeUTF("保研至华中科技大学");

            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }


IO对象流

对象流主要是将Java中具体的对象转换成字节序列(配合文件流可以将对象保存在文件中)

也可以将序列化的对象反序列化转换成对象(配合文件流可以将文件中保存的对象读出来)

流操作对象的限制

public class Student implements Serializable{

对象必须实现Serializable这个空接口


import java.io.*;
import java.util.Date;

/**
 * 对象流:
 * 1.写出后读取
 * 2.读取的顺序与写出的保持一致
 * 3.不是所有的对象都可以序列化Serializable
 */
public class ObjectTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //写出-->序列化
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(baos));
        //操作数据类型+数据
        oos.writeUTF("编码辛酸泪");
        oos.writeInt(18);
        oos.writeBoolean(false);
        oos.writeChar('a');
        //对象
        oos.writeObject("谁解其中味");
        oos.writeObject(new Date());
        Employee emp = new Employee("马云",400);
        oos.writeObject(emp);
        oos.flush();
        byte[]datas = baos.toByteArray();
        System.out.println(datas.length);
        //读取-->反序列化
        ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())));
        //顺序与写出一致
        String msg = ois.readUTF();
        int age = ois.readInt();
        boolean flag = ois.readBoolean();
        char ch = ois.readChar();
        System.out.println(flag);
        //对象的数据还原
        Object str  = ois.readObject();
        Object date= ois.readObject();
        Object employee= ois.readObject();
        //手动转型
        if (str instanceof String){
            String strObj = (String)str;
            System.out.println(strObj);
        }
        if (date instanceof Date){
            Date dateObj = (Date) date;
            System.out.println(dateObj);
        }
        if (employee instanceof Employee){
            Employee empObj = (Employee) employee;
            System.out.println(empObj.getName()+"-->"+empObj.getSalary());
        }
    }
    //Javabean 封装数据
    static class Employee implements Serializable{
        private transient String name;//该数据不用序列化
        private double salary;
        public Employee(){
        }

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

        public String getName() {
            return name;
        }

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

        public double getSalary() {
            return salary;
        }

        public void setSalary(double salary) {
            this.salary = salary;
        }
    }
}

//序列化至文件
public class ObjectTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //写出-->序列化
        ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("abc.txt")));
        //操作数据类型+数据
        oos.writeUTF("编码辛酸泪");
        oos.writeInt(18);
        oos.writeBoolean(false);
        oos.writeChar('a');
        //对象
        oos.writeObject("谁解其中味");
        oos.writeObject(new Date());
        Employee emp = new Employee("马云",400);
        oos.writeObject(emp);
        oos.flush();
        oos.close();
        //读取-->反序列化
        ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream("abc.txt")));
        //顺序与写出一致
        String msg = ois.readUTF();
        int age = ois.readInt();
        boolean flag = ois.readBoolean();
        char ch = ois.readChar();
        System.out.println(flag);
        //对象的数据还原
        Object str  = ois.readObject();
        Object date= ois.readObject();
        Object employee= ois.readObject();
        ois.close();
        //手动转型
        if (str instanceof String){
            String strObj = (String)str;
            System.out.println(strObj);
        }
        if (date instanceof Date){
            Date dateObj = (Date) date;
            System.out.println(dateObj);
        }
        if (employee instanceof Employee){
            Employee empObj = (Employee) employee;
            System.out.println(empObj.getName()+"-->"+empObj.getSalary());
        }
    }
    //Javabean 封装数据
    static class Employee implements Serializable{
        private transient String name;//该数据不用序列化
        private double salary;
        public Employee(){
        }

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

        public String getName() {
            return name;
        }

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

        public double getSalary() {
            return salary;
        }

        public void setSalary(double salary) {
            this.salary = salary;
        }
    }
}

IO打印流

import java.io.*;

/**
 * 打印流 PrintStream
 */
public class PrintTest01 {
    public static void main(String[] args) throws FileNotFoundException {
        //打印流System.out
        PrintStream printStream = System.out;
        printStream.println("打印流");
        printStream.println(true);

        printStream = new PrintStream(new BufferedOutputStream(new FileOutputStream("print.txt")),true);
        printStream.println("打印流");
        printStream.println(true);
        printStream.close();
        //重定向输出端
        System.setOut(printStream);
        System.out.println("CHANGE");
        //重定向会控制台
        System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out))));
        System.out.println("i am backing");
    }
}

import java.io.*;

public class PrintTest02 {
    public static void main(String[] args) throws FileNotFoundException {
        PrintWriter pw = new PrintWriter(new BufferedOutputStream(new FileOutputStream("print.txt")));
        pw.println("打印流");
        pw.println(true);
        pw.close();
    }
}

IO文件分割——面向对象最终版

/**
 * 面向对象思想封装 分割
 */
public class SplitFile {
    //源头
    private File src;
    //目的地(文件夹)
    private String destDir;
    //所有分割后的文件存储路径
    private ArrayList<String> destPaths;
    //块数:多少块
    private int size;
    //每块大小
    int blockSize;
    public SplitFile(String srcPath, String destDir,int blockSize) {
        this.src = new File(srcPath);
        this.destDir = destDir;
        this.blockSize = blockSize;
        this.destPaths = new ArrayList<String>();
        //初始化
        init();

    }
    private void init() {
        //总长度
        long len = this.src.length();
        //块数:多少块
        this.size = (int) Math.ceil(len * 1.0 / blockSize);
        //路径
        for (int i = 0; i < size; i++) {
            this.destPaths.add(this.destDir + "/"+i+"-" + this.src.getName());
        }
    }
    /**
     * 分割
     * 1.计算每一块的起始位置及大小
     * 2.分割
     */
    public void split() throws IOException {
        //总长度
        long len = src.length();
        //起始位置和实际大小
        int beginPos = 0;
        int actualSize = (int) (blockSize > len ? len : blockSize);
        for (int i = 0; i < size; i++) {
            beginPos = i * blockSize;
            if (i == size - 1) {//最后一块
                actualSize = (int) len;
            } else {
                actualSize = blockSize;
                len -= actualSize;//剩余量
            }
            splitDetail(i, beginPos, actualSize);
        }
    }

        private void splitDetail(int i, int beginPos, int actualSize) throws IOException {
            RandomAccessFile randomAccessFile = new RandomAccessFile(this.src,"r");
            RandomAccessFile randomAccessFile2 = new RandomAccessFile((this.destPaths.get(i)),"rw");
            //随机读取
            randomAccessFile.seek(beginPos);
            //读取
            byte[] flush = new byte[1024];
            int len = -1;
            while ((len = randomAccessFile.read(flush)) != -1) {
                if (actualSize>len){
                    randomAccessFile2.write(flush,0,len);
                    actualSize-=len;
                }else {
                    randomAccessFile2.write(flush,0,len);
                    break;
                }
            }
            randomAccessFile2.close();
            randomAccessFile.close();
        }

    public static void main(String[] args) throws IOException {
            SplitFile sf = new SplitFile("src/cn/sxt/gao/Copy.java","dest",1024);
            sf.split();

    }

    }


IO 序列流

public void merge(String destPath) throws IOException {
        //输出流
        OutputStream os = new BufferedOutputStream(new FileOutputStream(destPath,true));
        Vector<InputStream> vi = new Vector<InputStream>();
        SequenceInputStream sis = null;
        //输出流
        for(int i=0;i<destPaths.size();i++) {
            vi.add(new BufferedInputStream(new FileInputStream(destPaths.get(i))));
        }
        sis = new SequenceInputStream(vi.elements());
            //拷贝
            byte []flush = new byte[1024];
            int len =-1;
            while ((len=sis.read(flush))!=-1){
                os.write(flush,0,len);
            }
            os.flush();
            sis.close();
            os.close();
    }

CommonsIO常用操作

import org.apache.commons.io.FileUtils;

import java.io.File;

/**
 * 大小
 */
public class CIOTest01 {
    public static void main(String[] args) {
        //文件大小
        long len = FileUtils.sizeOf(new File("src/com/sxt/commons/CIOTest01.java"));
        System.out.println(len);
        //目录大小
        len = FileUtils.sizeOf(new File("C:\\Users\\Lenovo\\IdeaProjects\\learn\\src\\cn\\sxt\\gao\\IOTest04.java"));
        System.out.println(len);
    }
}


import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.DirectoryFileFilter;
import org.apache.commons.io.filefilter.EmptyFileFilter;
import org.apache.commons.io.filefilter.SuffixFileFilter;

import java.io.File;
import java.util.Collection;
import java.util.Collections;
import static org.apache.commons.io.FileUtils.listFiles;

/**
 * 列出子孙级
 */
public class CIOTest02 {
    public static void main(String[] args) {
        Collection<File> files =FileUtils.listFiles(new File("C:\\Users\\Lenovo\\IdeaProjects\\learn\\src\\cn\\sxt\\gao"), new SuffixFileFilter("java"), DirectoryFileFilter.INSTANCE);
        for (File file:files){
            System.out.println(file.getAbsoluteFile());
        }
        System.out.println("-------------");
    }

}

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * 读取内容
 */
public class CIOTest03 {
    public static void main(String[] args) throws IOException {
        //读取文件
        String msg = FileUtils.readFileToString(new File("src/emp.txt"),"UTF-8");
        System.out.println(msg);
        byte []datas = FileUtils.readFileToByteArray(new File("src/emp.txt"));
        System.out.println(datas.length);

        //逐行读取
        List<String> msgs = FileUtils.readLines(new File("src/emp.txt"),"UTF-8");
        for (String string:msgs){
            System.out.println(string);
        }

        LineIterator it = FileUtils.lineIterator(new File("src/emp.txt"),"UTF-8");
        while (it.hasNext()){
            System.out.println(it.nextLine());
        }

    }
}


import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

import static java.nio.charset.StandardCharsets.UTF_8;

public class CIOTest04 {
    public static void main(String[] args) throws IOException {
        FileUtils.write(new File("happy.txt"),"学习是一件伟大的事业\r\n","UTF-8");
        FileUtils.writeStringToFile(new File("happy.txt"),"学习是一件辛苦的事业\r\n","UTF-8",true);
        FileUtils.writeByteArrayToFile(new File("happy.txt"),"学习是一件幸福的事业\r\n".getBytes(UTF_8),true);

        //写出列表
        List<String> datas = new ArrayList<String>();
        datas.add("马云");
        datas.add("马化腾");
        datas.add("弼马温");

        FileUtils.writeLines(new File("happy.txt"),datas,"******",true);
    }
}

CommonsIO 拷贝核心操作

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;

public class CIOTest05 {
    public static void main(String[] args) throws IOException {
        //复制文件
        //FileUtils.copyFile(new File("C:\\Users\\Lenovo\\IdeaProjects\\learn\\copygirl.png"),new File("p-copy.png"));
        //复制文件到目录
        //FileUtils.copyDirectory(new File("C:\\Users\\Lenovo\\IdeaProjects\\learn\\copygirl.png"),new File("lib"));
        //复制目录到目录
        //FileUtils.copyDirectoryToDirectory(new File("lib"),new File("lib2"));
        //复制目录
        //FileUtils.copyDirectory(new File("lib"),new File("lib2"));
        //拷贝URL内容
        //String url = "网址";
        //FileUtils.copyURLToFile(new URL(url),new File("marvel.jpg"));
        String datas = IOUtils.toString(new URL("http://www.163.com"),"gbk");
        System.out.println(datas);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值