6、IO(2)

2.7 打印流

package cn.itcast.day159.stream;
import java.io.*;
import java.util.Scanner;
/*
 * 三个常量
 * 1、System.in
 * 2、System.out
 * 3、System.err
 * 其中后面两个实质上没有区别,只是会给错误加上颜色以示区别
 * FileDescriptor.out:表示控制台输出
 * FileDescriptor.in:表示控制台输入
 * */
public class Demo03 {
    public static void main(String[] args) throws FileNotFoundException {
        test1();
    }
    
    public static void test3() throws FileNotFoundException{
        System.out.println("test");//输出到控制台
        //重定向
        File src = new File("D:/FQ/parent/data.txt");
        //true表示自动刷新
        System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream(src)), true));
        System.out.println("test");//打印输出到文件
        //再次重定向到控制台
        System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out)), true));
        System.out.println("test");
    }
    
    public static void test2() {
        InputStream is = System.in;//标准键盘输入
        //is = new BufferedInputStream(new FileInputStream("D:/FQ/parent/data.txt"));
        Scanner sc = new Scanner(is);//这里is是一个输入流,于是我们可以替换为其他的输入流,比如文件输入流,如上
        System.out.println("请输入: ");
        System.out.println(sc.nextLine());
    }
    
    public static void test1(){
        System.out.println("test");
        System.err.println("err");//会自动加上颜色
    }
}

说明:打印流也是一个处理流,这个流方便我们控制输入输出的位置。使用较为简单,这里不多数。

三、文件夹拷贝

在对文件夹进行拷贝的时候我们不仅要拷贝子孙目录,同时对于目录中的文件也需要进行拷贝。

package cn.itcast.day146.stream;
import java.io.File;
import java.io.IOException;
//文件夹的拷贝
//如果目标是一个文件夹则我们需要创建,如果是一个文件则直接拷贝即可
public class DirCopy {
    public static void main(String[] args) {
        String srcPath = "D:/FQ/parent";
        File src = new File(srcPath);
        String destPath = "D:/FQ/parent_back";
        File dest = new File(destPath);
        copy(src, dest);
    }
    //拷贝文件夹
    private static void copyDir(File src, File dest) {
        if(src.isFile()){
            try {
                FileCopyUtil.fileCopy(src, dest);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else if(src.isDirectory()){
            //确保目标文件夹存在
            dest.mkdirs();
            //获取子孙级
            for(File sub : src.listFiles()){
                copyDir(sub, new File(dest, sub.getName()));
            }
        }
    }
    
    //封装成一个工具类
    public static void copy(File src, File dest){
        //之所以有下面这个判断,是因为我们不仅需要将源文件夹中内容拷贝,
        //同时还要将源文件夹拷贝,也就是要将最上一级的目录拷贝下来
        if(src.isDirectory()){//如果是目录
            dest = new File(dest, src.getName());
            System.out.println(dest);//D:\FQ\parent_back\parent
        }
        copyDir(src, dest);
    }
    public static void copy(String srcPath, String destPath){
        File src = new File(srcPath);
        File dest = new File(destPath);
        copy(src, dest);
    }
}

说明:程序中对文件的拷贝可以使用之前的程序,这里就不再给出了。

四、文件的分割与合并

package cn.itcast.day159.stream;
import java.io.*;
import java.util.*;
import cn.itcast.day189.socket_.CloseUtil;

public class Demo07 {
    private String filePath;// 文件的路径
    private long blockSize;// 每块的大小
    private int size;// 块数
    private List blockPath;// 各块的名字
    private String fileName;// 文件名
    private long length;// 文件大小
    private String destPath;//分割后的存放目录

    public Demo07() {
        blockPath = new ArrayList();
    }

    public Demo07(String filePath, String destPath) {
        this(filePath, 1024, destPath);
    }

    public Demo07(String filePath, long blockSize, String destPath) {
        this.filePath = filePath;
        this.destPath = destPath;
        this.blockSize = blockSize;
        init();
    }

    // 初始化操作,计算块数和文件名
    public void init() {
        File src = null;
        if (filePath == null || !((src = new File(filePath)).exists())) {
            return;
        }
        // 如果不是文件,而是目录,不能分割
        if (src.isDirectory()) {
            return;
        }
        // 文件名
        this.fileName = src.getName();
        // 计算块数
        this.length = src.length();
        // 如果blockSize比文件实际大小还大
        if (this.blockSize > length) {
            this.blockSize = length;
        }
        // 确定块数,ceil表示取大于等于参数值的最小整数,两个整数相除的时候有可能为0,这里乘上一个1.0
        this.size = (int) (Math.ceil(length * 1.0 / this.blockSize));
        initPathName();// 确定文件路径
    }

    private void initPathName() {
        for (int i = 0; i < size; i++) {
            String str = this.destPath + "/" + this.fileName + ".part" + i;
            this.blockPath.add(str);// 添加一个文件路径
        }
    }

    // 文件分割
    // 第几块、起始位置、实际大小
    // destPath:分割文件的存放目录
    public void split(String destPath) {
        long beginPos = 0;// 起始点
        long actualBlockSize = blockSize;// 实际大小
        // 计算所有块的大小、索引、位置
        for (int i = 0; i < size; i++) {
            if (i == size - 1) {
                actualBlockSize = this.length - beginPos;
            }
            splitDetail(i, beginPos, actualBlockSize);
            beginPos += actualBlockSize;
        }
    }
    /*
     * 文件的拷贝
     */
    private void splitDetail(int index, long beginPos, long actualBolockSize) {
        // 创建源
        File src = new File(this.filePath);
        File dest = new File(this.blockPath.get(index));
        RandomAccessFile raf = null;// 输入流
        BufferedOutputStream bos = null;// 输出流
        // 选择流
        try {
            raf = new RandomAccessFile(src, "r");
            bos = new BufferedOutputStream(new FileOutputStream(dest));
            // 读取文件
            raf.seek(beginPos);//设置读取的起始位置
            byte[] buffer = new byte[1024];
            int len = 0;
            while (-1 != (len = raf.read(buffer))) {
                // 写出
                if (actualBolockSize - len >= 0) {
                    bos.write(buffer, 0, len);
                    actualBolockSize -= len;
                } else {
                    // 写出剩余量
                    bos.write(buffer, 0, (int) actualBolockSize);
                    break;
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            CloseUtil.closeAll(bos, raf);
        }
    }

    // 文件的合并
    public void mergeFile1(String destPath) {
        // 创建源
        File dest = new File(destPath);
        // 选择流
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;// 输出流
        try {
            bos = new BufferedOutputStream(new FileOutputStream(dest, true));// true表示追加
            for (int i = 0; i < this.blockPath.size(); i++) {
                bis = new BufferedInputStream(new FileInputStream(
                        this.blockPath.get(i)));

                byte[] buffer = new byte[1024];
                int len = 0;
                while (-1 != (len = bis.read(buffer))) {
                    bos.write(buffer, 0, len);
                }
                bos.flush();
                CloseUtil.closeAll(bis);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            CloseUtil.closeAll(bos);
        }
    }

    // 文件合并,使用SequenceInputStream
    public void mergeFile2(String destPath) {
        // 创建源
        File dest = new File(destPath);
        // 选择流
        // 创建一个容器
        Vector vi = new Vector();
        SequenceInputStream sis = null;
        BufferedOutputStream bos = null;// 输出流

        try {
            for (int i = 0; i < this.blockPath.size(); i++) {
                vi.add(new BufferedInputStream(new FileInputStream(
                        this.blockPath.get(i))));
            }

            bos = new BufferedOutputStream(new FileOutputStream(dest, true));// true表示追加
            sis = new SequenceInputStream(vi.elements());

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

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            CloseUtil.closeAll(bos);
        }
    }

    public static void main(String[] args) {
        Demo07 file = new Demo07("D:/FQ/parent/copy.txt", 500, "D:/FQ/parent");
        // System.out.println(file.size);
        // file.split("D:/FQ/parent");// 给出存放目录
        file.mergeFile1("D:/FQ/parent/merge.txt");
    }
}

说明:

  • 文件的分割时,我们使用了RandomAccessFile流,这个流可以设置读取文件的位置,便于进行文件的分割。而在文件合并的时候我们可以使用一般的方式,也可以使用SequenceInputStream这个类,这个流是一个合并流。

你可能感兴趣的:(6、IO(2))