不积跬步无以至千里,不积小流无以成江海
在之前的博客文章里面记录了学习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();
}
}
}
不积跬步无以至千里,不积小流无以成江海