Java--IO流

一、概念

流:流动、流向,从一端移动到另一端,源头到目的地

程序 与 数据源(文|数组|网络连接|数据库),以程序为中心

二、IO流分类

1.流向:输入流与输出流  (以程序为中心)

2.数据:字节流:二进制,可以处理一切文件,包括纯文本、doc、音频、视频等等

     字符流:文本文件,只能处理纯文本

3.功能:节点流,包裹源头(离源头最近)

     处理流,增强功能,提供性能

三 字符流与字节流(重点)

1.字节流

  输入流:InputStream(抽象类)

                           FileInputStream()


  输出流:    OutputStream (抽象类)

                            FileOutputStream()


2.字符流

  输入流:Reader(抽象类)

                            FileReader()


  输出流:   Writer(抽象类)

                           FileWriter()


四、操作

1.举例:搬家    ----------------------->读取文件

   (1)关联房子  ----------------->建立与文件的联系--->File对象

             (2)选择搬家 ------------------>选取对应流

             (3)搬家    ---------------->读取|写出

                        (a)卡车大小 -------------->数组大小

                        (b)运输         ----------------->读取、写出

             (4)打发over  -------------->释放资源

五、字节流的读取与写出

FileInputStream构造器


public class Demo01 {
    public static void main(String[] args) {
        //建立联系 File对象
        File src = new File("/home/deepin/Desktop/test/aa.txt");
        //选择流
        //InputStream is = new FileInputStream("/home/deepin/Desktop/test/aa.txt");
        InputStream is = null;
        try {
            is = new FileInputStream(src);
            //操作  不断读取缓冲数组
            byte[] car = new byte[10];
            int len =0;  //接收实际读取大小
            //循环读取
            while (-1 != (len = is.read(car))) {
                //字节数组转成字符串
                String info = new String(car, 0, len);
                System.out.println(info);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("文件不存在");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("读取文件失败");
        }finally {
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("关闭文件输入流失败");
                }
            }
        }


    }
}

FileOnputStream构造器


public class Demo02 {
    public static void main(String[] args) {
        //建立联系 File对象
        File dest = new File("/home/deepin/Desktop/test/aa.txt");
        //选择流
        OutputStream os = null;
        try {
            //以追加的形式
            os = new FileOutputStream(dest,true);
            //操作
            String str = "heyuying\n";
            //字符串转字节数组
            byte[] data = str.getBytes();
            os.write(data,0,data.length);
            //强制刷新出去,由于有管道,只有管道满时,才会写到文件
            os.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("文件未找到");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("文件写出失败");
        }finally {
            try {
                if (null != os) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("关闭输出流失败");
            }
        }
    }
}

文件与文件夹的拷贝

public class FileUtil {
    //文件的拷贝
    public static void copyFile(String srcPath, String destPath) throws IOException {
        //1.建立联系 源(存在且为文件)+ 目的地(文件可不存在)
        copyFile(new File(srcPath),new File(destPath));
    }
    public static void copyFile(File src,File dest) throws IOException {

        if (!src.isFile()) {
            //System.out.println("只能拷贝文件");
            throw new IOException("只能拷贝文件");
        }

        //dest为已经存在的文件夹,不能建立与文件夹同名的文件
        if (dest.isDirectory()) {
            System.out.println(dest.getAbsolutePath()+"不能建立与文件夹同名的文件");
            throw new IOException(dest.getAbsolutePath()+"不能建立与文件夹同名的文件");
        }
        //2.选择流
        InputStream is = new FileInputStream(src);
        OutputStream os = new FileOutputStream(dest);
        //文件的拷贝  循环读取+写出
        byte[] flush = new byte[1024];
        int len = 0;
        while (-1 != (len = is.read(flush))) {
            os.write(flush, 0, len);
        }
        os.flush();
        //关闭流
        os.close();
        is.close();
    }

    //拷贝文件夹
    public static void copyDir(String srcPath, String destPath) throws IOException {

        File src = new File(srcPath);
        File dest = new File(destPath);
        copyDir(src,dest);
    }
  //拷贝文件夹
    public static void copyDir(File src, File dest) throws IOException {
        if (src.isDirectory()) {  //文件夹
                             dest = new File(dest, src.getName());
        }
        if (dest.getAbsolutePath().contains(src.getAbsolutePath())) {
            System.out.println("不能将父目录拷贝到子目录中");
            return;
        }
        copyDirDetail(src, dest);
    }
    //拷贝文件夹的细节
    public static void copyDirDetail(File src, File dest)throws IOException {
        if (src.isFile()) {
            try {
                FileUtil.copyFile(src, dest);
            } catch (IOException e) {
                e.printStackTrace();
                throw e;
            }
        } else if (src.isDirectory()) { //文件夹
            //确保目标文件夹存在
            dest.mkdirs();
            //获取下一级目录|文件
            for (File sub : src.listFiles()) {
                copyDirDetail(sub,new File(dest,sub.getName()));
            }
        }
    }
}

六、字符流

字符流:文本文件,只能处理纯文本,全部为可见字符 .txt   .html

节点流  Reader     FileReader

                        Writer     FileWriter

1.纯文本读取

1)建立联系

2)选择流  Reader     FileReader

3)读取   char[]     flush = nwe char[1024];

4)关闭

//字符流的读取
public class CharReader {
    public static void main(String[] args) {
        //建立源
        File src = new File("/home/deepin/Desktop/test/test.txt");
        //选择流
        Reader reader = null;

        try {
            reader = new FileReader(src);
            //读取操作
            char[] flush = new char[10];
            int len = 0;
            while (-1 != (len = reader.read(flush))) {
                //字符数组转成字符串
                String str = new String(flush, 0, len);
                System.out.println(str);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("源文件不存在");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("读取文件失败");
        }finally {
            if (null != reader) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("关闭失败");
                }
            }
        }
    }
}

2.纯文本写出

1)建立联系

2)选择流    Writer     FileWriter

3)写出    write(字符数组,0,长度)+flush()

4)关闭

//字符流的写出
public class CharWriter {
    public static void main(String[] args) {
        //建立源
        File dest = new File("/home/deepin/Desktop/test/test.txt");
        //选择流
        Writer wr = null;
        try {
            //追加文件,而不是覆盖文件true
            wr = new FileWriter(dest,true);
            //写出
            String msg = "......当希望不再有,你还会坚持吗?";
            wr.write(msg);
            wr.append("加油");

            wr.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (null != wr) {
                try {
                    wr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("关闭流失败");
                }
            }
        }
    }

}

3.纯文件的拷贝     

//字符流的拷贝
public class CharCopyFile {
    public static void main(String[] args) {
        //建立源  仅限于纯文本
        File src = new File("/home/deepin/Desktop/test/test.txt");
        File dest = new File("/home/deepin/Desktop/test/aa.txt");
        //选择流
        Reader reader = null;
        Writer wr = null;

        try {
            reader = new FileReader(src);
            wr = new FileWriter(dest);
            //读取操作
            char[] flush = new char[1024];
            int len = 0;
            while (-1 != (len = reader.read(flush))) {
                wr.write(flush, 0, len);
            }

            wr.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("源文件不存在");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("读取文件失败");
        }finally {
            try {
                if (null != wr) {
                    wr.close();
                }
            }catch (IOException e) {
                e.printStackTrace();
            }

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

        }
    }

}

七、处理流  增强功能,提供性能,在节点流之上

1.节点流与处理流的关系  

   节点流处于io操作的第一线,所有操作必须通过它们进行;处理流可以对其他流进行处理(提高效率或操作灵活性)

    

2.缓冲流

1)字节缓冲流

BufferedInputStream

BufferedOutputStream

//字节流文件拷贝+缓冲流 提高性能
public class BufferedByteDemo {
    public static void copyFile(String srcPath, String destPath) throws IOException {
        File src = new File(srcPath);
        File dest = new File(destPath);
        if (!src.isFile()) {
            //System.out.println("只能拷贝文件");
            throw new IOException("只能拷贝文件");
        }
        //2.选择流
        InputStream is = new BufferedInputStream(new FileInputStream(src));
        OutputStream os = new BufferedOutputStream(new FileOutputStream(dest));
        //文件的拷贝  循环读取+写出
        byte[] flush = new byte[1024];
        int len = 0;
        while (-1 != (len = is.read(flush))) {
            os.write(flush, 0, len);
        }
        os.flush();
        //关闭流
        os.close();
        is.close();
    }
}

2)字符缓冲流

BufferedReader    readLine()

BufferedWriter      newLine()

//字符缓冲流+新增方法(不能发生多态)
public class BufferedCharDemo {
    public static void main(String[] args) {
        //建立源  仅限于纯文本
        File src = new File("/home/deepin/Desktop/test/test.txt");
        File dest = new File("/home/deepin/Desktop/test/aa.txt");
        //选择流
        BufferedReader reader = null;
        BufferedWriter wr = null;

        try {
            reader = new BufferedReader(new FileReader(src));
            wr = new BufferedWriter(new FileWriter(dest));

           /* char[] flush = new char[1024];
            int len = 0;
            while (-1 != (len = reader.read(flush))) {
                wr.write(flush, 0, len);
            }*/

            //读取操作   一行一行读取
            String line = null;
            while (null!=(line=reader.readLine())) {
                wr.write(line);
                wr.newLine();  //换行符
            }

            wr.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("源文件不存在");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("读取文件失败");
        } finally {
            try {
                if (null != wr) {
                    wr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

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

        }
    }

}

3.转换流:字节流 转换为字符流  处理乱码(编码集、解码集)

1)编码与解码概念

编码:字符 --编码字符集--> 二进制

解码:二进制 --解码字符集-->字符

2)乱码

<1>编码与解码的字符集不统一

//编码与解码字符集必须相同,否则乱码
public static void test1() throws UnsupportedEncodingException {
    //解码byte--->char  tf-8
    String str = "中国";
    //编码 char-->byte  tf-8
    byte[] data = str.getBytes();
    //编码与解码字符集统一
     System.out.println(new String(data));
    //设定编码字符集  utf-8
    data = str.getBytes("utf-8");
    System.out.println(new String(data));

    //编码
     byte[] data2 = "中国".getBytes("utf-8");
    //解码
     str = new String(data, "utf-8");
   System.out.println(str);
}

可以通过此方法设置解码字符集


<2>字节缺少,长度丢失

String str = "中国";
byte[] data = str.getBytes();
//字节数不完整
System.out.println(new String(data, 0, 2));

转换流:字节流转换为字符流

1.输出流:OutputStreamWriter    编码

2.输入流:InputStreamReader 解码


public class ConverDemo02 {
    public static void main(String[] args) throws IOException {
        //指定解码字符集
        BufferedReader br = new BufferedReader(
                new InputStreamReader(
                        new FileInputStream(
                                new File("/home/deepin/Desktop/test/test.txt")
                        ),"UTF-8"
                )
        );

        //写出文件
        BufferedWriter bw = new BufferedWriter(
          new OutputStreamWriter(
                  new FileOutputStream(
                          new File("/home/deepin/Desktop/test/aa.txt")
                  ),"Utf-8"
          )
        );


        String info = null;
        while (null != (info = br.readLine())) {
            System.out.println(info);
            bw.write(info);
            bw.newLine();
        }
        bw.flush();
        bw.close();
        br.close();
    }
}

IO流总结


八、其他流

1.节点流

1)字节数组   

  输入流:ByteArrayInputStream     read(byte[] b, int off, int len)

  输出流:ByteArrayOutputStream  write(byte[] b, int off, int len) + toByteArray()  不要使用多态

/*
 * 输入流 操作与文件输入流操作一致
 * 读取字节数组
 * */
public static void read(byte[] src) throws IOException {
    //数据源
    //String msg = "操作与文件输入流操作一致";
    //byte[] src = msg.getBytes();

    //选择流
    InputStream is = new BufferedInputStream(
            new ByteArrayInputStream(
                    src
            )
    );

    //操作
    byte[] flush = new byte[1024];
    int len = 0;
    while (-1 != (len = is.read(flush))) {
        System.out.println(new String(flush, 0, len));
    }
    //释放资源
    is.close();
}
/*
 * 输出流 操作与文件输入流操作有些不同,有新增方法,不是使用多态
 *
 * */
public static byte[] write() throws IOException {
    //目的地
    byte[] dest;
    //选择流
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    //写出
    String msg = "操作与文件输入流操作一致";
    byte[] info = msg.getBytes();
    bos.write(info,0,info.length);
    //获取数据
    dest = bos.toByteArray();
    bos.close();
    return dest;
}

文件流与字节数组流对接完成文件的拷贝(之前是:文件--程序-->文件)

1.文件--程序-->字节数组

2.字节数组--程序-->文件


/*
*1.文件--程序-->字节数组
* 文件输入流
* 字节数组输出流
* 2.字节数组--程序-->文件
* 字节数组输入流
* 文件输出流
* */
public class ByteArrayDemo02 {
    public static void main(String[] args) throws IOException {
        byte[] data = getBytesFromFile("/home/deepin/Desktop/test/test.txt");
        System.out.println(new String(data));
        toFileFromByteArray(data,"/home/deepin/Desktop/test/test1.txt");
    }

    //2.字节数组--程序-->文件
    public static void toFileFromByteArray(byte[] src,String destPath) throws IOException {
        //创建源
        //目的地
        File dest = new File(destPath);

        //选择流
        //字节数组输入流
        InputStream is = new BufferedInputStream(new ByteArrayInputStream(src));
        //文件输出流
        OutputStream os = new BufferedOutputStream(new FileOutputStream(dest));

        //操作 不断读取字节数组
        byte[] flush = new byte[1024];
        int len = 0;
        while (-1 != (len = is.read(flush))) {
            //写出到文件中
            os.write(flush, 0, len);
        }
        os.flush();
        //释放资源
        os.close();
        is.close();

    }

    //1.文件--程序-->字节数组
    public static byte[] getBytesFromFile(String srcPath) throws IOException {
        //创建文件源
        File src = new File(srcPath);
        //创建字节数组目的地
        byte[] dest = null;

        //选择流
        //文件输入流
        InputStream is = new BufferedInputStream(new FileInputStream(src));
        //字节数组输出流  不能使用多态
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        //操作  不断地读取文件写出到字符数组流中
        byte[] flush = new byte[1024];
        int len = 0;
        while (-1 != (len = is.read(flush))) {
            //写出到字节数组流中
            bos.write(flush, 0, len);
        }
        bos.flush();
        //获取数据
        dest = bos.toByteArray();
        //释放资源
        bos.close();
        is.close();
        return dest;
    }
}

2)字符数组

          输入流:CharArrayReader

  输出流:CharArrayWriter

2.处理流

1)基本类型+String 保留数据+类型

输入流 : DataInputStream   readXX

输出流:DataOutputStream  writeXX

1>向文件写数据+类型和从文件读取数据+类型

/*
 * 数据类型(基本数据类型+String)处理流
 * 1.输入流 DataInputStream
 *  2.输出流 DataOutputStream
 *  新增方法不能用多态
 *  java.io.EOFException 没有读取到相关内容
 * */
public class DataDemo01 {
    public static void main(String[] args) throws IOException {
        write("/home/deepin/Desktop/test/aa.txt");
        //read("/home/deepin/Desktop/test/test.txt");  //文件存在,但为非法内容
           read("/home/deepin/Desktop/test/aa.txt");

    }

    /*
     * 从文件读取数据+类型
     * */
    public static void read(String destPath) throws IOException {
        File src = new File(destPath);
        DataInputStream dis = new DataInputStream(
                new BufferedInputStream(new FileInputStream(src))
        );
        //操作 读取顺序与写出一致,若读取顺序不一致,则数据会有问题
           double num1 = dis.readDouble();
        long num2 = dis.readLong();
        String str2 = dis.readUTF();
        dis.close();

        System.out.println(num1+"-->"+num2+"-->"+str2);
    }
    /*
     * 数据+类型输出到文件
     * */
   
 public static void write(String destPath) throws IOException {
        double point = 2.5;
        long num = 100l;
        String str = "数据类型";

        //创建源
                  File dest = new File(destPath);
        DataOutputStream dos = new DataOutputStream(
                new BufferedOutputStream(new FileOutputStream(dest))
        );

        //操作 写出的顺序为读取准备
                   dos.writeDouble(point);
        dos.writeLong(num);
        dos.writeUTF(str);
        dos.flush();
        dos.close();
    }
}

2>向字节数组写数据+类型和从字节数组读取数据+类型

public class DataDemo02 {
    public static void main(String[] args) {
        try {
            byte[] data = write();
            System.out.println(data.length);
            read(data);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    /*
     * 从字节数组中读取数据+类型
     * */
    public static void read(byte[] src) throws IOException {
        DataInputStream dis = new DataInputStream(
                new BufferedInputStream(new ByteArrayInputStream(src))
        );
        //操作 读取顺序与写出一致,若读取顺序不一致,则数据会有问题
                  double num1 = dis.readDouble();
        long num2 = dis.readLong();
        String str2 = dis.readUTF();
        dis.close();

        System.out.println(num1+"-->"+num2+"-->"+str2);
    }

    /*
     * 数据+类型输出到字节数组中
     * */
    public static byte[] write() throws IOException {

        //目标数组
                  byte[] dest;
        double point = 2.5;
        long num = 100l;
        String str = "数据类型";


        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(
                new BufferedOutputStream(bos)
        );

        //操作 写出的顺序为读取准备
                   dos.writeDouble(point);
        dos.writeLong(num);
        dos.writeUTF(str);
        dos.flush();
        dest = bos.toByteArray();
        dos.close();
        return dest;
    }
}

2)引用(对象)保留数据+类型

反序列化 输入流  ObjectInputStream       readObject()

序列化  输出流  ObjectOutputStream    writeObject()

注意:

1>先序列化再反序列化

2>不是所有对象都可以序列化,要实现java.io.Serializable接口的类的对象可序列化

3>不是所有的属性都需要序列化,不需要序列化的属性用transient修饰

public class ObjectDemo01 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        seri("/home/deepin/Desktop/test/aa.txt");
        read("/home/deepin/Desktop/test/aa.txt");

    }
    //反序列化
    public static void read(String destPath) throws IOException, ClassNotFoundException {
        File src = new File(destPath);
        ObjectInputStream ois = new ObjectInputStream(
          new BufferedInputStream(new FileInputStream(src))
        );
        //操作 
                   Object obj = ois.readObject();
        if (obj instanceof Employee) {
            Employee emp = (Employee) obj;
            System.out.println(emp.getName());
            System.out.println(emp.getSalary());
        }

        obj = ois.readObject();
        int[] arr = (int[]) obj;
        System.out.println(Arrays.toString(arr));
        ois.close();

    }

    //序列化
    public static void seri(String destPath) throws IOException {
        Employee emp = new Employee("bjsxt", 10000);
        int[] arr = {1, 2, 3, 4};
        //创建源
                  File dest = new File(destPath);
        ObjectOutputStream oos = new ObjectOutputStream(
                new BufferedOutputStream(new FileOutputStream(dest))
        );
        oos.writeObject(emp);
        oos.writeObject(arr);
        oos.flush();
        oos.close();
    }

}
3.编写工具类,实现关闭功能

public class FileCloseUtil {
    /*
     * 工具类关闭流
     * 可变参数...只能形参最后一个位置,处理方式与数组一致
     * */
    public static void close(Closeable... io) {
        for (Closeable temp : io) {
            if ( null != temp) {
                try {
                    temp.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
 public static <T extends Closeable> void closeAll(T... io) {
        for (Closeable temp : io) {
            if ( null != temp) {
                try {
                    temp.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

4.打印流

1)输出到控制台-->文件

/*
* PrintStream打印流---->处理流
*
* */
public class PrintStreamDemo01 {
    public static void main(String[] args) throws FileNotFoundException {
        System.out.println("test");
        PrintStream ps = System.out;  //输出到控制台
           ps.println(false);

        //输出到文件
           File src = new File("/home/deepin/Desktop/test/print.txt");
        ps = new PrintStream(new BufferedOutputStream(new FileOutputStream(src)));
        ps.println("io is so easy...");
        ps.close();
    }
}

2)从控制台输入到从文件读取

/*
 * 三个常量
 * 1.System.in  --->InputStream对象, 输入流 键盘输入
 * 2.System.out --->OutputStream对象 输出流 控制台输出
 * 3.System.err---->OutputStream对象
 * */
public class SystemDemo01 {
    public static void main(String[] args) throws FileNotFoundException {
        //test1();
        InputStream is = System.in;  //键盘输入
        Scanner sc = new Scanner(is);
        System.out.println("请输入:");
        System.out.println(sc.nextLine());

        is = new BufferedInputStream(new FileInputStream("/home/deepin/Desktop/test/test.txt"));
        Scanner scanner = new Scanner(is);  //从文件中使用Scanner
        System.out.println(scanner.nextLine());

        /*重定向
          setIn()
          setOut()
          setErr()
          FileDescriptor.in  输入控制台
          FileDescriptor.out 输出控制台
          FileDescriptor.err
        * */
        System.setOut(new PrintStream(
                new BufferedOutputStream(
                        new FileOutputStream("/home/deepin/Desktop/test/print.txt")
                )
        ,true)
        );
        System.out.println("a"); //控制台-->文件
        //回控制台
        System.setOut(new PrintStream(
               new BufferedOutputStream(
                       new FileOutputStream(FileDescriptor.out)
               )
        ,true)
        );
        System.out.println("back....");
    }

    public static void test1() {
        System.out.println("test");
        System.err.println("err");  //打印一个错误信息
    }
}


3)用BufferedReader代替Scanner

public class BufferedIn {
    public static void main(String[] args) throws IOException {
        InputStream is = System.in;
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        System.out.println("请输入。。。。");
        String msg = br.readLine();
        System.out.println(msg);
    }
}

5.   IO -- 装饰设计模式

例子:对声音进行放大,用扩音器装饰


public class Voice {
    private int voice = 10;

    public Voice() {

    }

    public Voice(int voice) {
        this.voice = voice;
    }

    public int getVoice() {
        return voice;
    }

    public void setVoice(int voice) {
        this.voice = voice;
    }

    public void say() {

    }
}


/*类与类之间的关系
* 1.依赖:类作为方法的形参或局部变量
* 2.关联:属性(类用来声明属性)
*     聚合:属性 整体与部分 不一致的生命周期
*     组合:属性 整体与部分 一致的生命周期
* 3.继承:父子类的关系
* 4.实现:接口与实现类的关系
* */
public class Amplifier {
    private Voice voice;

    public Amplifier() {

    }

    public Amplifier(Voice voice) {
        this.voice = voice;
    }

    public void say() {
        System.out.println(voice.getVoice() * 1000);
    }
}

public class App {
    public static void main(String[] args) {
        Voice v = new Voice();
        v.say();
        Amplifier am = new Amplifier(v);
        am.say();
    }
}

6.文件的分割与合并

分割:RandomAccessFile

public class RndDemo01 {
    public static void main(String[] args) throws IOException {
        RandomAccessFile rnd = new RandomAccessFile(new File("/home/deepin/Desktop/test/test.txt"), "r");
        rnd.seek(0);//从第几个字节开始读
                  byte[] flush = new byte[1024];
        int len = 0;
        while (-1 != (len = rnd.read(flush))) {
            if (len >= 73) { //如果大于73,就读取73
                System.out.println(new String(flush, 0, 73));
                break;
            } else {//小于73,则读取全部
                System.out.println(new String(flush, 0, len));
            }
        }
        rnd.close();

    }
}

合并:SequenceInputStream

/*文件分割思路:
* 1.分割的块数 size n
* 2.每一块的大小 blockSize
*   最后一块:总的文件大小-(n-1)*blockSize
* */
public class SplitFile {
    //文件的路径
    private String filePath;
    //文件名
    private String fileName;
    //文件的大小
    private long fileLength;
    //块数
    private int size;
    //每块的大小
    private long blockSize;
    //分割后的存放目录
    private String destBlockPath;
    //每块的名称
    private List<String> blockPath;


    public SplitFile() {
        blockPath = new ArrayList<>();
    }

    public SplitFile(String filePath,String destBlockPath) {
        this(filePath, destBlockPath,1024);
    }

    public SplitFile(String filePath, String destBlockPath,long blockSize ) {
        this();
        this.filePath = filePath;
        this.destBlockPath = destBlockPath;
        this.blockSize = blockSize;
        init();
    }

    //初始化操作,计算块数、确定文件名
    public void init() {
        File src = null;
        if (null == filePath || !((src = new File(filePath)).exists())) {
            return;
        }
        if (src.isDirectory()) {
            return;
        }

        //文件名
        this.fileName = src.getName();

        //计算块数 文件实际大小 与每块大小
        this.fileLength = src.length();
        if (this.blockSize > this.fileLength) {
            this.blockSize = this.fileLength;
        }
        //确定块数
        size = (int) Math.ceil(this.fileLength * 1.0 / this.blockSize);
        //确定文件的路径
        initPathName();
    }

    private void initPathName() {
        for (int i = 0; i < size; i++) {
            this.blockPath.add(destBlockPath + "/" + this.fileName + ".part" + i);
        }
    }

    //文件的分割
    public void split() {
        long beginPos = 0;  //起始点
        long actualBlockSize = this.blockSize;
        //计算所有块的大小、位置、索引
        for (int i = 0; i < size; i++) {
            if (i == size - 1) { //最后一块
                actualBlockSize = fileLength - beginPos;
            }
            splitDetail(i, beginPos, actualBlockSize);
            beginPos += actualBlockSize;  //本次的终点,下一次的起点

        }

    }

    private void splitDetail(int idx, long beginPos, long actualBlockSize) {
        //1.创建源
        File src = new File(this.filePath);
        File dest = new File(this.blockPath.get(idx));
        //2.选择流
        RandomAccessFile raf = null;  //输入流
        BufferedOutputStream bos = null; //输出流


        try {
            raf = new RandomAccessFile(src, "r");
            bos = new BufferedOutputStream(new FileOutputStream(dest));

            //读取文件
            raf.seek(beginPos);
            byte[] flush = new byte[1024];
            int len = 0;
            while (-1 != (len = raf.read(flush))) {
                if (actualBlockSize - len >= 0) {  //查看是否足够
                    //写出
                    bos.write(flush, 0, len);
                    actualBlockSize -= len;  //剩余量
                } else { //写出最后一次的剩余量
                    bos.write(flush, 0, (int) actualBlockSize);
                    break;
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bos.close();
                raf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


    /*合并文件
     * */
    public void mergeFile(String destPath) {
        //创建源
        File dest = new File(destPath);
        //选择流
        BufferedOutputStream bos = null;//输出流
        try {
            bos = new BufferedOutputStream(new FileOutputStream(dest, true));//追加文件
            BufferedInputStream bis = null;
            for (int i = 0; i < this.blockPath.size(); i++) {
                bis = new BufferedInputStream(new FileInputStream(new File(this.blockPath.get(i))));
                byte[] flush = new byte[1024];
                int len = 0;
                while (-1 != (len = bis.read(flush))) {
                    bos.write(flush,0,len);
                }
                bos.flush();
                bis.close();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /*合并文件
     * */
    public void merge(String destPath) {
        //创建源
        File dest = new File(destPath);
        //选择流
        BufferedOutputStream bos = null; //输出流
        SequenceInputStream sis =null;//输入流

        //创建一个容器
        Vector<InputStream> v = new Vector<>();
        try {
            for (int i = 0; i < this.blockPath.size(); i++) {
                v.add(new BufferedInputStream(new FileInputStream(new File(this.blockPath.get(i)))));
            }
            bos = new BufferedOutputStream(new FileOutputStream(dest, true));//追加文件
            sis = new SequenceInputStream(v.elements());

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

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        SplitFile file = new SplitFile("/home/deepin/Desktop/test/print.txt","/home/deepin/Desktop/test" ,50);
        //System.out.println(file.size);
        //file.split();
        file.merge("/home/deepin/Desktop/test/merge2");

    }

}

7.IO总结

一、步骤:创建源 选择流 操作(读取|写出)释放

二、流


三、重点


四、操作

0.打印文件|目录

1.文件拷贝

2.关闭流方法

3.文件分割与合并

猜你喜欢

转载自blog.csdn.net/yuyinghe0612/article/details/80427727