天天看点

IO流--基础流FileInputStream和FileOutputStream的使用

                                基础流的简单操作

    之前学到的File我们只能操作文件夹和文件,却不能操作里面的内容。今天通过学习IO流之后,我们就可以操作文件里面的内容了。在Java中,处理字节流的两个基础的类是InputStream和OutputStream,而用于处理字符流的两个基础的类是Reader和Writer。所以其他的流类都是以这4个类为基础。首先就说一下InputStream和OutputStream。

FileInoutStream和FileOutputStream分别是InputStream和OutputStream的直接子类,我们可以叫它们为基础流或者低级流,基本流中构造中参数是介质。

1. InputStream的方法

        read():读入一个字节并返回,包装为int,返回-1表示已读不到

        close():关闭资源

首先从读文件的内容开始,例如我们先在D盘建立一个文件a.txt在里面写上abcde,那么我们怎么把这些内容读出来呢?看下面的代码。

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.InputStream;

publicclass Test {

publicstaticvoid main(String[] args) {

InputStream is = null;

try {// 输入流文件必须存在

is = new FileInputStream("d:\\a.txt");

int i = is.read();//读第一个字节

System.out.println(i);//输出对应的内容,是int类型的如果想输出原来的内容

//把类型转换一下就可以了

System.out.println((char)i);

//我们把两个异常合并到一起

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

}finally{

try {//关闭资源,同样需要抛出异常

is.close();

}

执行结果:97

a

另外的方法:

read(byte[] b) 一次读入尽可能多的字节去填满字节数组b,返回实际读到的字节数,-1表示已读不到。

read(byte[] b, int off, int len) 一次读入尽可能多的字节去填满字节数组b从off开始的len个空间。

如果我们想把abcde全部都读出来应该怎么办呢?这时我们可以借助循环,因为在read()方法中-1表示读不到了,所以我们可以这么做

int i = 0;

while((i=is.read())!=-1){//如果不是-1代表下面还有字节

System.out.print((char)i);

执行结果:abcde

读的操作我们已经做到了,接下来就是往文件里面写内容。这时我们就需要使用OutpetStream这个流类。OutputStream类提供的方法:

write():写一个字节到流中

write(byte[] b):将字节数组中的数据写入流中

write(byte[] b, int off, int len):将字节数组中从off开始的length个字节写入到流中

flush():将缓冲中的字节立即发送到流中,同时清空缓冲

close():关闭输出流

写的操作和读区别不大,看一下代码:

import java.io.FileOutputStream;

import java.io.OutputStream;

OutputStream os = null;

try {// 输出流:自己会新建一个文件

// true表示追加 false表示覆盖 默认是false

os = new FileOutputStream("d:\\b.txt",true);

os.write(97);//

//下面的这两个我们只需要写一个就行了

//os.flush();

os.close();

执行结果根据我们执行的次数而定,因为我们加了true,如果执行一次结果就是a,两次就是aa,以此类推。

如果我们想把a.txt的内容复制到b.txt中应该怎么做呢?思路就是每当读一个a.txt中的字节,就往b.txt里面写。代码也非常简单。

package day11;

import java.io.File;

while((i = is.read())!=-1){

char ch = (char)i;

os = new FileOutputStream(new File("d:\\b.txt"),true);

os.write(ch);

结果当然就是b.txt里面也是abcde

上面我们实现了文件内容的复制,下面我们来完成压缩文件复制的操作,有了上面的代码我们会有一些思路。在下面的代码中为了更清晰的体现代码,我们将抛出异常都交给函数来完成,不再自己处理,但是不建议这样,现在只是为了让代码清晰,看下面代码:

publicclass TestCopyFile {

publicstaticvoid main(String[] args) throws IOException {

//调用下面的方法,左面是以存在的压缩包,右面是复制生成的压缩包

copyFile("d:\\day02.rar","d:\\test.rar");

//定义一个方法

publicstaticvoid copyFile(String file1,String file2) throws IOException{

FileInputStream fis = new FileInputStream(new File(file1));

FileOutputStream fos = new FileOutputStream(new File(file2));

int b = 0;

// 读源文件,将读入的每个字节依次写入目标文件

while((b=fis.read())!=-1){

fos.write(b);

// 流操作的最后一定要关闭

fis.close();

fos.close();

执行结果:在D盘有一个test.rar的压缩包,当然我们可以根据自己电脑来决定复制什么文件,如果文件很大的话,我们可以清楚的看到test.rar的大小会逐渐增大,这是因为我们是按字节来复制的,很显然这种复制方法是非常慢的,怎么提高复制的速度呢?一起看下吧!

下面是改进的方法,改动的地方不是很大

intb = 0;

//定义一个8K的数组

byte[] arrByte = newbyte[8*1024];

// 读源文件,将读入的每个字节依次写入目标文件,按每8K来复制

while((b=fis.read(arrByte))!=-1){

fos.write(arrByte);

执行结果:如果文件很大的话,我们可以看到和上面的区别,就是复制速度变快了。

但是我们会发现一个问题,那就是复制之后的test.rar变大了一点,这是因为我们是按每8k来复制的,当day02.rar末尾的地方不够8k时,仍然会按照8k来复制,这样最后的8k里面就会自动填入数据,所以变大了,怎样解决这个问题呢?也很容易,我们只需要将上面的