JAVA IO流——使用FileInputStream和FileOutputStream复制文件注意事项

不积跬步无以至千里,不积小流无以成江海

在之前的博客文章里面记录了学习FileInputStream的使用,因此写点实际小例子,比如使用流来复制出一个新的文件,也在本次l练手学习过程中发现一些需要注意的地方。

目标文件file.txt,里面有78个字符,三组26个字母

目标就是复制出一个新文件newFile.txt到同一目录下

测试代码

import java.io.*;

public class FileInpuStreamTest {
    private static final String FILE_PATH = "F:\\javashop\\IOTest\\src\\file.txt";
    private static final String FILE_DIRECTORY = "F:\\javashop\\IOTest\\src\\";

    public static void main(String[] args) {
        File file = new File(FILE_PATH);
        File newFile = new File(FILE_DIRECTORY+"newFile.txt");
        try {
            FileInputStream fis = new FileInputStream(file);
            FileOutputStream fos = new FileOutputStream(newFile);
            byte[] bytes = new byte[26];    //定义一个26字节长的数组
            int length = 0;
            System.out.println("=====生成文件开始=====");
            long startTime = System.currentTimeMillis();
            while ((length = fis.read(bytes, 0, bytes.length)) != -1) {
                //一次写入一个数组
                fos.write(bytes);
                fos.flush();
            }
            System.out.println("耗时:"+String.valueOf(System.currentTimeMillis()-startTime)+"ms.");
            System.out.println("=====生成文件结束=====");
            fis.close();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行结果后,完美在目标路径下发现newFile.txt的身影。但是,代码中定义了一个缓冲数组byte[] bytes = new byte[26];,测试文件里面有78个字符,按照代码来说,循环三次就可以写完了。那么假如定义不是26?不是目标文件字节可以整除的缓冲区大小呢?怀着这样的心情,我定义了一个100的缓冲区大小,并且修改了代码如下:
修改后的测试代码

import java.io.*;

public class FileInpuStreamTest {
    private static final String FILE_PATH = "F:\\javashop\\IOTest\\src\\file.txt";
    private static final String FILE_DIRECTORY = "F:\\javashop\\IOTest\\src\\";

    public static void main(String[] args) {
        File file = new File(FILE_PATH);
        File newFile = new File(FILE_DIRECTORY+"newFile.txt");
        try {
            FileInputStream fis = new FileInputStream(file);
            FileOutputStream fos = new FileOutputStream(newFile);
            byte[] bytes = new byte[100];    //定义一个100字节长的数组
            int length = 0;
            System.out.println("=====生成文件开始=====");
            long startTime = System.currentTimeMillis();
            while ((length = fis.read(bytes, 0, bytes.length)) != -1) {
                //一次写入一个数组
                fos.write(bytes);
                fos.flush();
            }
            System.out.println("耗时:"+String.valueOf(System.currentTimeMillis()-startTime)+"ms.");
            System.out.println("=====生成文件结束=====");
            fis.close();
            fos.close();
            FileInputStream fis1 = new FileInputStream(newFile);
            System.out.println(newFile.getName()+"长度:"+fis1.available());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

删除原来生成的文件,重新运行后,newFile.txt乖乖地出现了。好像是没什么问题,但是为什么输出长度是100???我使用神器IDEA打开看了一下,光标左右动了一下,发现了不对。

打开文件管理器看一下file.txt和newFile.txt大小

看得出来上面生成的文件实际比源文件字节大小多了22个字节。简单的数学就是100-78=22。
所以按照上面的代码生成的文件实际是有问题的,看上去好像是正确的,实际大小内容已经有了细微的差异。

关键在于这行代码fos.write(bytes);虽然一个write很简单的帮我们将缓冲区的内容一次写入,但是实际在最后一次循环写入中有可能将多余的内容也写入到新文件中,因此应该换其另一个写入的重载方法
public void write(byte[] b,int off,int len)throws IOException

修改代码如下,则运行生成的文件和源文件大小一致

import java.io.*;

public class FileInpuStreamTest {
    private static final String FILE_PATH = "F:\\javashop\\IOTest\\src\\file.txt";
    private static final String FILE_DIRECTORY = "F:\\javashop\\IOTest\\src\\";

    public static void main(String[] args) {
        File file = new File(FILE_PATH);
        File newFile = new File(FILE_DIRECTORY + "newFile.txt");
        try {
            FileInputStream fis = new FileInputStream(file);
            FileOutputStream fos = new FileOutputStream(newFile);
            byte[] bytes = new byte[100];    //定义一个100字节长的数组
            int length = 0;
            System.out.println("=====生成文件开始=====");
            long startTime = System.currentTimeMillis();
            while ((length = fis.read(bytes, 0, bytes.length)) != -1) {
                //最后一个参数length,保证最后一个循环写入正确的数据内容长度
                fos.write(bytes, 0, length);
                fos.flush();
            }
            System.out.println("耗时:" + String.valueOf(System.currentTimeMillis() - startTime) + "ms.");
            System.out.println("=====生成文件结束=====");
            fis.close();
            fos.close();
            FileInputStream fis1 = new FileInputStream(newFile);
            System.out.println(newFile.getName() + "长度:" + fis1.available());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

不积跬步无以至千里,不积小流无以成江海

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值