JavaSE基础之IO流

Java中把输入/输出(input/output)操作称为流(Stream)。

流:即为起点到接收点有序的数据序列。

流的分类:

1.按照流的方向分为:

                输入流:只读,只会从流中读取数据;

               输出流:只写,只会向流中写入数据;

2.按照处理的数据分:

               字节流(InputStream/OutputStream):读或写的时候以字节为单位;

              字符流(Reader/Writer):读或写的时候以字符为单位;

       一般情况下(排除特殊情况),一个汉字占一个字符,一个字符占两个字节,如果读或写的时候只读或写一个字节的话,那么就会出现乱码。

3.按照功能分为:

              低级流:直接从数据的源头读取数据或者直接把数据写到目标位置的流,称为低级流,也称为节点流;

              高级流:对一个已经存在的流的连接和封装,称为高级流,也称为处理流;

先从字节流中的FileInputStream和FileOutputStream说起:以下是两者的模型

代码如下:

package com.Jevin.io;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class ByteStreamTest {

    public static void main(String[] args) {

        //readFile1();
        //readFile2();
        //writeFile1();
        writeFile2();
    }

    /**
     * 用FileInputStream读取文件的内容,一个一个字节的读取(出现中文乱码问题)
     */
    public static void readFile1() {
        FileInputStream fin = null;

        try {
            //文件的完整路径有三部分组成:路径名称+分隔符+文件名称;
            //如果指定文件不存在,或者他是一个目录,而不是一个常规文件,抑或因为其他原因无法打开进行读取,则抛出FileNotFoundException;
            //注意:FileInputStream只能读取并显示纯文本文件的内容(也就是能用记事本打开的文件)
            fin = new FileInputStream("d:\\aa.txt");

            int i = 0;
            //从文件中读取一个字节以int值返回,当读到文件末尾没有数据时返回-1;
            while((i=fin.read()) != -1){
                //byte->int->char
                System.out.print((char)i);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            //流打开之后,必须进行关闭
            try {
                if(fin != null){
                    fin.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 用FileInputStream读取文件的内容,一次读取多个字节的内容(有些中文没有乱码,有些乱码;并且还多读了一些内容)
     */
    public static void readFile2() {
        FileInputStream fin = null;

        try {
            fin = new FileInputStream("d:\\aa.txt");

            int i = 0;
            byte[] b = new byte[100];
            //从文件中读取100个字节,放大数组中,i返回的是读取到的字节的数量,当读到文件末尾没有数据时返回-1;
            while((i=fin.read(b)) != -1){
                //byte[] -> char[] -> String
                String str = new String(b);
                System.out.print(str);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            //流打开之后,必须进行关闭
            try {
                if(fin != null){
                    fin.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 用FileOutputStream写String到文件
     */
    public static void writeFile1(){
        FileOutputStream fout = null;

        try {
            //当目标文件不存在时,JVM会自动创建这个文件,若已存在,则将内容写到这个文件中;
            fout = new FileOutputStream("d:\\bb.txt",true); //true表示追加写文件

            String str = "2.用FileOutputStream写String到文件";

            //将String转换为byte[]
            byte[] b = str.getBytes();

            fout.write(b);
            System.out.println("文件写入完成");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            //流打开之后,必须进行关闭
            try {
                if(fout != null){
                    fout.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }



    /**
     * 用FileOutputStream写String到文件,解决换行
     */
    public static void writeFile2(){
        FileOutputStream fout = null;

        try {
            //当目标文件不存在时,JVM会自动创建这个文件,若已存在,则将内容写到这个文件中;
            fout = new FileOutputStream("d:\\bb.txt",true); //true表示追加写文件

            for(int i=0;i<=10;i++){
                //由于FileOutputStream不会处理换行,需要我们在String结尾加入\n
                //记事本不能识别\n,能够识别\r\n;
                String str = i+".用FileOutputStream写String到文件\r\n";
                //将String转换为byte[]
                byte[] b = str.getBytes();
                fout.write(b);
            }

            System.out.println("文件写入完成");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            //流打开之后,必须进行关闭
            try {
                if(fout != null){
                    fout.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

 然后将FileInputStream和FileOutputStream拼接起来,就组成了拷贝粘贴的功能;

但是这样直接使用低级流去读和写文件显然不是我们想要的,因为效率有点低,于是我们需要在低级流上接上一个高级流,像这样:

下面有代码来实现上面的过程,也即是拷贝文件的过程:

package com.Jevin.io;

import java.io.*;

/**
 * 文件拷贝器
 */
public class FileCoper {

    private FileCoper(){

    }

    /**
     * 拷贝文件的操作
     * @param srcFile 源文件
     * @param desPath 目标路径
     */
    public static void copyFile(String srcFile,String desPath){
        //从源文件的String中取出文件名称,也就是从例如:"D:\\tools\\Navicat.rar"中取到"Navicat.rar";
        String[] arr = srcFile.split("\\\\");
        String fileName = arr[arr.length-1];

        //组织目标文件:路径名称+分隔符+文件名称
        String desFile = desPath+"\\"+fileName;

        //声明输入流:
        FileInputStream fin = null;
        BufferedInputStream bin = null;

        //声明输出流:
        FileOutputStream fout = null; //低级输出流
        BufferedOutputStream bout = null; //高级输出流

        try {
            //创建输入流:
            fin = new FileInputStream(srcFile);
            bin = new BufferedInputStream(fin);

            //创建输出流:首先初始化低级流,然后初始化高级流
            fout = new FileOutputStream(desFile);
            bout = new BufferedOutputStream(fout);

            int i=0;
            byte[] b = new byte[1024*1024];
            while((i=bin.read(b))!=-1){
                bout.write(b,0,i);
            }

            /**
             * 如果关闭低级流,那么会导致小于8k的文件滞留在bout的缓冲区,所以要刷新缓存区
             * 拷贝过程中,只要文件的大小大于8k,则无需刷新缓存
             */
            //bout.flush();

            //由于采用了正确的流的关闭方式,所以无论文件大小,无需刷新缓存

            System.out.println("文件拷贝完成,"+srcFile+"拷贝到目标文件"+desFile+"完成");

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            //错误的关闭方式
            //if(fin != null){
            //    try {
            //        fin.close();
            //    } catch (IOException e) {
            //        e.printStackTrace();
            //    }
            //}
            //if(fout != null){
            //    try {
            //        fout.close();
            //    } catch (IOException e) {
            //        e.printStackTrace();
            //    }
            //}

            //正确的关闭方式
            //高级流在关闭的时候:1.会自动关闭低级流;2.会自动刷新缓存
                try {
                    if(bin != null){
                        bin.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }

                try {
                    //bout关闭的时候,会自动刷新缓冲区
                    if(bout != null){
                        bout.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }


        }
    }

    public static void main(String[] args){
        String file = "D:\\tools\\aa.txt";
        //String file = "D:\\tools\\Navicat.rar";
        copyFile(file,"d:\\");
    }
}

       但是上面的代码有点问题,问题出在取文件名和拼接目标文件路径上,采用了"\\"和"\\\\"这两种分隔符,但是不同操作系统上的分隔符是不一样的,这样写的话就写死了,违背java的可移植性特点,所以我们采用java.io.File来解决这个问题:

package com.Jevin.io;

import java.io.*;

/**
 * 文件拷贝器
 */
public class FileCoper {

    private FileCoper(){

    }

    /**
     * 拷贝文件的操作
     * @param srcFile 源文件
     * @param desPath 目标路径
     */
    public static void copyFile(String srcFile,String desPath){

        //从源文件的String中取出文件名称
        //File file = new File(srcFile);
        //copyFile(file,desPath);

        //继续简化
        copyFile(new File(srcFile),desPath);

    }

    /**
     * 拷贝文件的操作
     * @param srcFile 源文件
     * @param desPath 目标路径
     */
    public static void copyFile(File srcFile,String desPath){

        //从源文件的String中取出文件名称
        String fileName = srcFile.getName();

        //组织目标文件:路径名称+分隔符+文件名称
        String desFile = desPath+File.separator+fileName;

        //声明输入流:
        FileInputStream fin = null;
        BufferedInputStream bin = null;

        //声明输出流:
        FileOutputStream fout = null; //低级输出流
        BufferedOutputStream bout = null; //高级输出流

        try {
            //创建输入流:
            fin = new FileInputStream(srcFile);
            bin = new BufferedInputStream(fin);

            //创建输出流:首先初始化低级流,然后初始化高级流
            fout = new FileOutputStream(desFile);
            bout = new BufferedOutputStream(fout);

            int i=0;
            byte[] b = new byte[1024*1024];
            while((i=bin.read(b))!=-1){
                bout.write(b,0,i);
            }

            System.out.println("文件拷贝完成,"+srcFile+"拷贝到目标文件"+desFile+"完成");

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            //正确的关闭方式
            //高级流在关闭的时候:1.会自动关闭低级流;2.会自动刷新缓存
            try {
                if(bin != null){
                    bin.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                //bout关闭的时候,会自动刷新缓冲区
                if(bout != null){
                    bout.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }


        }
    }

    public static void main(String[] args){
        String file = "D:\\tools\\aa.txt";
        //String file = "D:\\tools\\Navicat.rar";
        copyFile(file,"d:\\");
    }
}

        但是这里还有一个问题,一个相对较大的文件拷贝是需要时间的,如果在拷贝的这段时间内,程序突然停下来的,文件看似拷贝下来了,但是这个文件是不完整的,那么该如何解决这个问题呢?下面代码演示:

package com.Jevin.io;

import java.io.*;

/**
 * 文件拷贝器
 */
public class FileCoper {

    private FileCoper(){

    }

    /**
     * 拷贝文件的操作
     * @param srcFile 源文件
     * @param desPath 目标路径
     */
    public static void copyFile(String srcFile,String desPath){

        //从源文件的String中取出文件名称
        //File file = new File(srcFile);
        //copyFile(file,desPath);

        //继续简化
        copyFile(new File(srcFile),desPath);

    }

    /**
     * 拷贝文件的操作
     * @param srcFile 源文件
     * @param desPath 目标路径
     */
    public static void copyFile(File srcFile,String desPath){

        //从源文件的String中取出文件名称
        String fileName = srcFile.getName();

        //判断目标路径是否存在,如果不存在,就把他创造出来;
        File dpath = new File(desPath);
        if(!dpath.exists()){
            dpath.mkdirs();
        }

        //组织目标文件:路径名称+分隔符+文件名称
        String desFile = desPath+File.separator+fileName;
        String tempFile = desFile + ".td"; //拷贝过程中的临时文件名称

        //声明输入流:
        FileInputStream fin = null;
        BufferedInputStream bin = null;

        //声明输出流:
        FileOutputStream fout = null; //低级输出流
        BufferedOutputStream bout = null; //高级输出流

        try {
            //创建输入流:
            fin = new FileInputStream(srcFile);
            bin = new BufferedInputStream(fin);

            //创建输出流:首先初始化低级流,然后初始化高级流
            fout = new FileOutputStream(tempFile);
            bout = new BufferedOutputStream(fout);

            int i=0;
            byte[] b = new byte[1024*1024];
            while((i=bin.read(b))!=-1){
                bout.write(b,0,i);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            //正确的关闭方式
            //高级流在关闭的时候:1.会自动关闭低级流;2.会自动刷新缓存
            try {
                if(bin != null){
                    bin.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                //bout关闭的时候,会自动刷新缓冲区
                if(bout != null){
                    bout.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            //当文件拷贝完成之后,把临时文件名称改成目标文件名称
            //这里注意:需要在流关闭的时候才可以重命名,要不然流将线程锁住,无法改名
            File file1 = new File(desFile);
            File file2 = new File(tempFile);
            if(file2.renameTo(file1)){
                System.out.println("文件拷贝完成,"+srcFile+"拷贝到目标文件"+desFile+"完成");
            }else{
                System.err.println("拷贝失败");
            }

        }
    }

    public static void main(String[] args){
        //String file = "D:\\tools\\aa.txt";
        String file = "D:\\tools\\Navicat.rar";
        copyFile(file,"d:\\abc");
    }
}

         但是这里还有一个问题,以上只是解决了拷贝一个文件到任意指定的文件夹中,但是实际还有将任意文件夹(包括其中的文件)拷贝到任意文件夹中,这个又该如何实现呢?一下代码演示:

package com.Jevin.io;

import java.io.*;

/**
 * 文件拷贝器
 */
public class FileCoper {

    private FileCoper(){

    }


    /**
     * 拷贝文件的操作
     * @param srcFile 源文件
     * @param desPath 目标路径
     */
    public static void copyFile(File srcFile,String desPath){

        //从源文件的String中取出文件名称
        String fileName = srcFile.getName();

        //判断目标路径是否存在,如果不存在,就把他创造出来;
        File dpath = new File(desPath);
        if(!dpath.exists()){
            dpath.mkdirs();
        }

        //组织目标文件:路径名称+分隔符+文件名称
        String desFile = desPath+File.separator+fileName;
        String tempFile = desFile + ".td"; //拷贝过程中的临时文件名称

        //声明输入流:
        FileInputStream fin = null;
        BufferedInputStream bin = null;

        //声明输出流:
        FileOutputStream fout = null; //低级输出流
        BufferedOutputStream bout = null; //高级输出流

        try {
            //创建输入流:
            fin = new FileInputStream(srcFile);
            bin = new BufferedInputStream(fin);

            //创建输出流:首先初始化低级流,然后初始化高级流
            fout = new FileOutputStream(tempFile);
            bout = new BufferedOutputStream(fout);

            int i=0;
            byte[] b = new byte[1024*1024];
            while((i=bin.read(b))!=-1){
                bout.write(b,0,i);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            //正确的关闭方式
            //高级流在关闭的时候:1.会自动关闭低级流;2.会自动刷新缓存
            try {
                if(bin != null){
                    bin.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                //bout关闭的时候,会自动刷新缓冲区
                if(bout != null){
                    bout.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            //当文件拷贝完成之后,把临时文件名称改成目标文件名称
            //这里注意:需要在流关闭的时候才可以重命名,要不然流将线程锁住,无法改名
            File file1 = new File(desFile);
            File file2 = new File(tempFile);
            if(file2.renameTo(file1)){
                System.out.println("文件拷贝完成,"+srcFile+"拷贝到目标文件"+desFile+"完成");
            }else{
                System.err.println("拷贝失败");
            }

        }
    }

    /**
     * 拷贝文件夹的功能
     * @param srcPath 原文件夹
     * @param desPath 目标路径
     */
    public static void copyDir(String srcPath,String desPath){
        copyDir(new File(srcPath),desPath);
    }


    /**
     * 拷贝文件夹的功能
     * @param srcPath 原文件夹
     * @param desPath 目标路径
     */
    public static void copyDir(File srcPath,String desPath){
        //判断srcPath是文件还是文件夹:
        if(srcPath.isFile()){
            //是文件,那么调用之前拷贝文件的方法:
            copyFile(srcPath,desPath);
        }else{
            //是文件夹:
            //从原文件中获取要拷贝的文件夹名称,例如,我要拷贝jdk源代码"D:\\file\\src",从中获取src
            String pathName = srcPath.getName();

            //在目标路径中创建要拷贝的目录,例如在"d:\\"创建"src"目录:
            String dPath = desPath+File.separator+pathName; //"d:\\src"
            File file = new File(dPath);
            file.mkdirs();

            //获取原文件夹中所有子文件(夹)
            File[] files = srcPath.listFiles();

            //遍历存放子文件的数组,一个个的拷贝到目标路径中,也就是dPath
            for(File file1:files){
                copyDir(file1,dPath); //递归调用
            }
        }
    }

    public static void main(String[] args){
        //String file = "D:\\tools\\aa.txt";
        //String file = "D:\\tools\\Navicat.rar";
        //copyFile(file,"d:\\abc");

        String file = "D:\\file\\src";
        copyDir(file,"d:\\");
    }
}

这里文件或文件夹拷贝告一段落了,反观之前的FileOutputStream这个低级流在实现写的时候,有一些瑕疵,模型如下:

package com.Jevin.io;

import java.io.*;

public class ByteStreamTest {

    public static void main(String[] args) {
        writeFile3();
    }


    /**
     * 在FileOutputStream上接一个高级流PrintStream输出
     */
    public static void writeFile3(){
        FileOutputStream fout = null;
        PrintStream ps = null;

        try {
            fout = new FileOutputStream("d:\\dd.txt",true);
            ps = new PrintStream(fout);

            for(int i=0;i<1000;i++){
                String str = i+"在FileOutputStream上接一个高级流PrintStream输出";

                //为了方便操作,ps.println(str)/ps.close()暂时不需要处理异常;
                ps.println(str);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally{
            if(ps != null){
                ps.close();
            }
        }
    }

}

================================================================================================

以上讲的都是字节流,从这里我们开始讲讲字符流的使用。

首先是使用字符流去读取文件中的数据,模型如下:

以下是代码演示:

package com.Jevin.io;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class CharacterStreamTest {

    public static void main(String[] args){
        //readFile1();
        readFile2();
    }

    /**
     * 用FileReader读取文件的内容,一个一个字符的读取
     */
    public static void readFile1(){
        FileReader fr = null;

        try {
            fr = new FileReader("d:\\aa.txt");
            int i = 0;
            //读取一个字符,当做int返回,直到文件末尾没有字符时返回-1;
            while((i=fr.read()) != -1){
                //char -> int -> char
                System.out.print((char)i);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(fr != null){
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 用FileReader读取文件的内容,一次读取多个字符的数据
     */
    public static void readFile2(){
        FileReader fr = null;

        try {
            fr = new FileReader("d:\\aa.txt");
            int i = 0;
            char[] c = new char[1024];
            //读取多个字符,保存到数组中,i是读取到的字符的数量
            while((i=fr.read(c)) != -1){
                //char[] -> String
                String str = new String(c,0,i);
                System.out.print(str);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(fr != null){
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

但是这样用低级流去读取文件是字符数组,然后还要手动转换为字符串,这样在读取大文件时效率不高,这时我没需要在低级流上接一个高级流,利用高级流的缓存一行一行的读取数据,效率大大提高,一下模型演示:

 下面是代码演示:

package com.Jevin.io;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class CharacterStreamTest {

    public static void main(String[] args) {
        readFile3();
    }

    /**
     * 用FileReader和BufferReader读取文件中的内容
     */
    public static void readFile3() {
        FileReader fr = null;
        BufferedReader br = null;

        try {
            fr = new FileReader("d:\\aa.txt");
            br = new BufferedReader(fr);

            String str = null;
            while ((str = br.readLine()) != null) {
                System.out.println(str);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

      这里简单的字节流和字符流就介绍到这里,接下来介绍一个有意思的流:RandomAccessFile,它可以从文件的任意位置读,也可以从文件的任意位置写。写个功能有什么用呢?换言之:可以将一个大文件切割成多个小文件分别读写

      模型如下所示:

代码如下所示:

package com.Jevin.io.demo;

import java.io.File;

/**
 * 文件拷贝包工头
 */
public class FileCopyContractor {

    private File srcFile; //源文件
    private String desFile; //目标文件
    private String tempFile; //拷贝过程中的临时文件
    private int splitCount; //文件切分的份数

    public FileCopyContractor(){}

    public FileCopyContractor(File srcFile, String desPath, int splitCount) {
        super();
        this.srcFile = srcFile;
        this.splitCount = splitCount;
        //组织目标文件:
        String fileName = srcFile.getName();
        this.desFile = desPath + File.separator + fileName;
        this.tempFile = desFile + ".td";
    }

    public FileCopyContractor(String srcFile, String desPath, int splitCount) {
        this(new File(srcFile),desPath,splitCount);
    }

    /**
     * 包工头开始工作:
     */
    public void start(){

        //获取原文件的大小:
        long fileSize = srcFile.length();
        System.out.println("文件的大小是:"+fileSize);

        //根据切分的份数和源文件的大小,计算每个工人的平均工作量
        long perWorkerSize = fileSize/this.splitCount;

        //计算第一个工人的开始位置和结束位置:
        long startPost = 0L;
        long endPost = perWorkerSize;

        //包工头创建多个工人:
        for(int i=0;i<this.splitCount;i++){
            //创建工人对象:
            FileCopyWorker fileCopyWorker = new FileCopyWorker("工人-"+i,srcFile,tempFile,startPost,endPost);

            //工人开始工作:
            fileCopyWorker.work();

            //包工头计算下一个工人的开始位置和结束位置:
            startPost = endPost;
            endPost = startPost + perWorkerSize;

            //如果是最后一个工人,则做到最后;
            if(i == this.splitCount-2){
                endPost = fileSize;
            }
        }

        //所有工人完成工作之后,把临时文件名称改成目标文件名称:
        File file1 = new File(this.tempFile);
        File file2 = new File(this.desFile);

        if(file1.renameTo(file2)){
            System.out.println(this.srcFile + "拷贝到"+this.desFile+"完成");
        }else{
            System.out.println("重命名文件失败");
        }
    }
}
package com.Jevin.io.demo;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * 文件拷贝工人
 */
public class FileCopyWorker {
    private String name; //工人名称
    private File srcFile; //源文件
    private String desFile; //目标文件
    private long startPost; //开始位置
    private long endPost; //结束位置
    private long copyedPost; //已经拷贝的位置

    public FileCopyWorker(String name, File srcFile, String desFile, long startPost, long endPost) {
        super();
        this.name = name;
        this.srcFile = srcFile;
        this.desFile = desFile;
        this.startPost = startPost;
        this.endPost = endPost;
        this.copyedPost = this.startPost; //初始化拷贝位置即为初始位置

        System.out.println(name+"[开始位置是:"+this.startPost+",结束位置是:"+this.endPost+"]");
    }

    /**
     * 工人开始工作
     */
    public void work(){
        RandomAccessFile rin = null; //读数据流
        RandomAccessFile rout = null; //写数据流

        try {
            rin = new RandomAccessFile(this.srcFile,"r");
            rout = new RandomAccessFile(this.desFile,"rw");

            //定位读写的位置:
            rin.seek(this.startPost); //开始读的位置
            rout.seek(this.startPost); //开始写的位置

            byte[] b = new byte[1024*1024];
            int i = 0;
            //当已经拷贝的位置小于结束位置,并且未拷贝到文件结尾,就一直循环拷贝下去:
            while((this.copyedPost < this.endPost) && (i=rin.read(b)) != -1){
                if((this.copyedPost + i) > this.endPost){
                    i = (int) (this.endPost - this.copyedPost);
                }
                rout.write(b,0,i);
                this.copyedPost += i;

                System.out.println(name+"正在工作,已经拷贝的位置是:"+this.copyedPost+",结束位置是:"+this.endPost);
            }
            System.out.println(name+"结束工作,已经拷贝的位置是:"+this.copyedPost+",结束位置是:"+this.endPost);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(rin != null){
                    rin.close();
                }
                if(rout != null){
                    rout.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
package com.Jevin.io.demo;

public class MainTest {
    public static void main(String[] args){
        String file = "D:\\tools\\Navicat.rar";
        FileCopyContractor fileCopyContractor = new FileCopyContractor(file,"d:\\",15);
        fileCopyContractor.start();
    }
}

“流”暂时就到这里吧,又补充的再继续吧!

猜你喜欢

转载自blog.csdn.net/boy_chen93/article/details/83502214