第4关:复制文件

任务描述

本关任务:复制文本文件,复制图片文件。

相关知识

上一关中最后,我们遇到了一个问题:hello.txt文件只有五个字符,而用来存储字符的数组有1024个字符,直接使用FileReaderread()方法读取然后输出就会有1019个空字符,如何来解决这个问题呢?

很容易想到的方法就是,我们定义一个长度为5的字符数组就可以了,这样确实可以暂时解决问题,可是我们往往不知道读取的文件有多大,如果文件中不止5个字符,而是有几万个字符我们又应该怎么办呢?

这就需要我们深入的了解IO流的常用函数了。

read()方法

我们来看read方法的详细解释:

方法参数说明方法描述
int read(char[] cbuf)字符数组将字符流中的数据读入到字符数组中,如果读取到文件末尾则返回-1,否则返回读取到的长度

理解了read方法,之前的问题就好解决了。

代码:

 
  1. String file = "D://hello.txt";
  2. FileReader fr = new FileReader(file);
  3. char[] cbuf = new char[1024];
  4. int len = fr.read(cbuf);//将数据读入到cbuf中并返回读取到的数据长度
  5. StringBuilder builder = new StringBuilder();
  6. builder.append(cbuf,0,len); //将cbuf 0 到len长度的数据添加到builder
  7. System.out.println(builder.toString());

运行这段代码,我们会发现输出是正确的,没有再打印出多余的空格。

可能我们又会有疑问了,如果文本文件大于1K,这段代码肯定就行不通了,怎么办呢?

很简单,加个循环就可以啦:

 
  1. String file = "D://hello.txt";
  2. FileReader fr = new FileReader(file);
  3. char[] cbuf = new char[1024];
  4. int len = 0; // 每次读取的长度
  5. StringBuilder builder = new StringBuilder();
  6. while ((len = fr.read(cbuf)) != -1) {
  7. builder.append(cbuf,0,len);
  8. }
  9. System.out.println(builder.toString());

这样修改之后我们就可以读取任意的文件,并将其内容输出到控制台了。

write()方法

write()方法有两种常用的重载方法:

方法参数说明方法描述
void write(String str)字符串将字符串写入到字符流中
void write(char[] cbuf,int off,int len)字符数组,偏移量(从什么位置开始),写入的长度将字符数组按照偏移量写入到字符流中写入的长度和偏移量与len有关

理解了这两种方法,我们现在如果要复制一个文本文件就很方便了,现在我们就来将D盘下hello.txt文件复制到E盘下,并重命名为abc.txt

 
  1. FileReader fr = new FileReader("D://hello.txt"); //定义FileReader读取文件
  2. int len = 0; //每次读取的字符数量
  3. char[] cbuf = new char[1024]; //每次读取数据的缓冲区
  4. FileWriter fw = new FileWriter("E://abc.txt"); //定义FileWriter写文件
  5. while((len = fr.read(cbuf)) != -1){
  6. fw.write(cbuf,0,len);
  7. }
  8. fw.close(); //释放资源 刷新缓冲区
  9. fr.close();

这段代码就是一个边读边写的过程,运行之后我们发现E盘下已经有了abc.txt文件并且内容和hello.txt一致。

使用字节流读写文件

到目前为止我们一直操作的都是文本文件,不过我们计算机中存储的文件可不止有文本文件,还有很多其他类型的,比如图片,视频,等等。

如果要对非文本类型的文件进行操作,应该怎么做呢?这个时候字符流还能不能派上用场呢?

答案是否定的,字符流只适用于操作字符类型的文件,不能操作非字符类型的。

所以这个时候应该用什么来操作呢?

相信你已经想到了:字节流。

是的我们需要使用字节流来操作非字符类文件。

接下来,我们使用字节流来复制一个图片文件,代码:

 
  1. FileInputStream fs = new FileInputStream("D://user.jpg"); //定义文件输入流读取文件信息
  2. FileOutputStream fos = new FileOutputStream("E://new.jpg");//定义文件输出流写文件
  3. int len = 0; //每次读取数据的长度
  4. byte[] bys = new byte[1024]; //数据缓冲区
  5. while( (len = fs.read(bys)) != -1){
  6. fos.write(bys, 0, len);
  7. }
  8. //释放资源 刷新缓冲区
  9. fs.close();
  10. fos.close();

运行即可看到E盘下生成了一个名为new.jpg的文件,且内容和user.jpg一致 可以发现上述代码和之前的字符流很像,确实原理都是类似的。

可能学到这,你会有很多疑问:

  1. 字节流既然可以用来读取非字符构成的文件,那可以读取字符类型的文件吗? 答案是可以的,字节流可以操作所有类型的文件,因为计算机中的数据都是以字节的方式存储的;

  2. 既然字节流可以用来操作所有的文件,那还要字符流干啥咧? 因为字符流操作字符类型的数据和文件要比字节流快很多。

扩展

使用BufferedReader读取字符文件的速度要比我们之前使用的字节流和FileReader快很多,示例代码:

 
  1. BufferedReader bf = new BufferedReader(new FileReader("D://hello.txt"));
  2. BufferedWriter writer = new BufferedWriter(new FileWriter("D://abc.txt"));
  3. String str = "";
  4. while( (str = bf.readLine()) != null){
  5. writer.write(str);
  6. }
  7. bf.close();
  8. writer.close();

编程要求

请仔细阅读右侧代码,根据方法内的提示,在Begin - End区域内进行代码补充,具体任务如下:

  • 复制src/step4/input/目录下的input.txt文件到src/step4/output/目录下,新文件命名为output.txt

  • 复制src/step4/input/目录下的input.jpg文件到src/step4/output/目录下,新文件命名为output.jpg

  • package step4;
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    
    public class Task {
    	
    	public void task() throws IOException{
    		/********* Begin *********/
    		//复制文本,字符流更快
            FileReader fr = new FileReader("src/step4/input/input.txt");//创建文件并将其实例化
            int len = 0;
    		char[] cbuf = new char[1024];
     
    		FileWriter fw = new FileWriter("src/step4/output/output.txt");//创建文件将其实例化
    		while((len = fr.read(cbuf)) != -1){//读入从左往右依次判断
    			fw.write(cbuf, 0, len);//读出从右往左,读入需要的数据
    		}
     
    		fr.close();//关闭输入流
    		fw.close();//关闭写入流
    		//复制图片字节流,更广泛
    		FileInputStream fs = new FileInputStream("src/step4/input/input.jpg");//同样将其创实例
    		FileOutputStream fos = new FileOutputStream("src/step4/output/output.jpg");//创建实例
     
    		int len1 = 0;
    		byte[] b = new byte[1024];
     
    		while((len1 = fs.read(b)) != -1){//从左到右
    			fos.write(b, 0, len1);//从右到左
    		}
     
    		fs.close();
    		fos.close();
    		
    		/********* End *********/		
    	}
    }

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值