A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

这个小问题是,今天我们小组的一个组员出现的;
之后陆续的在其它几个小组成员的代码上也出现了同样的问题;
所以我就提上一嘴吧.
组员代码如下
[AppleScript] 纯文本查看 复制代码
package com.heima.test;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
//文件过滤筛选拷贝:把指定目录下(不包含子目录)的所有图片,复制到另一个指定目录下(使用文件过滤器来过滤图片)
public class Lianxi2 {
	public static void main(String[] args) throws IOException {
		System.out.println("请输入指定复制源文件夹路径:");
		File file1 = getFile();
		System.out.println("请输入指定存放文件夹路径:");
		File file2 = getFile();
		//用一个集合来存放符合拷贝文件的绝对路径
		List<[color=#ff0000]String[/color]> list = new ArrayList<>();
		//寻找所有符合条件的文件并将路径存入集合
		seek(file1,list);
		//从集合读取文件路径,复制到新的文件夹路径
		copy(file2,list);	
	}
	private static void copy(File file2, List<[color=#ff0000]String[/color]> list) throws IOException {
[color=#000080]		File[] filelist = file2.listFiles();[/color]
[color=#ff0000]		if (filelist != null)[/color] {
[color=#ff0000]			for (String string : list) {
				BufferedInputStream bts = new BufferedInputStream(new FileInputStream(string));
				BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file2));
				int x;
				while((x = bts.read()) != -1) {
					bos.write(x);
					bts.close();
					bos.close();[/color]
				}
			}
		}
	}
	private static void seek(File file1, List<[color=#ff0000]String[/color]> list) {
		File[] filelist = file1.listFiles();
		if (filelist != null) {
			for (File file : filelist) {
				if (file.isFile() && file.getName().endsWith("jpg")) {
					list.add(file.getAbsolutePath());
				}else if (file.isDirectory()) {
					seek(file,list);
				}
			}
		}else{
			System.out.println("文件夹下为空,请检查后输入!");
		}
	}
	//测试样本路径file1		G:\图片\地图
	//测试接收路径file2		H:\新建文件夹
	private static File getFile() {
		Scanner sc = new Scanner(System.in);
		while(true) {	
			String line = sc.nextLine();
			File file = new File(line);
			if (!file.isDirectory()) {
				System.out.println("非文件夹路径,请重新输入:");
			}else{
				System.out.println("文件夹路径输入成功!");
				return file;
			}
		}
	}
}

红色部分为错误代码或者需要调整的部分,海军蓝标记的代码需要删除.
这段代码,创建了3个方法分别用于录入,迭代遍历和复制,思路很清晰,而且层次分明.
但就是由于对IO流的概念并没有理解透彻,照着Demo模板模仿下来,又希望添上一些自己的想法,结果demo运行没问题.
自己写的代码各种bug,而且在未能理解正确的概念之前,对着异常也半天难以找出错误.
下面我就来说这段代码的核心错误:
错误的理解:IO流操作的是File对象或者说路径;
正确的理解应该是:通过IO流实现内存与硬盘的交互时;IO流所操作的一定是文件!!!
可能会有人感到奇怪;所有IO流的构造方法里,不都是传File对象和路径的么?
的确在构造时传一个文件夹路径,或者说一个文件夹File对象;
在创建时,的确,编译器不会报错;
但是当在之后调用的write等方法时,一开始运行就会报错;
IO流在此时的目的只有一个就是对文件进行操作;
无论是传File对象还是传入一个路径,最终的目的,只是为了通过路径或者说File对象在机器的硬盘上
找到对应的文件,以便对其进行操作.
在输出路径上写个文件夹路径,难道说JVM会自动在那个文件夹中创建一个文件并拷贝过去么?
还是说,JVM会把文件内容直接写到文件夹上?这个JVM没有那么智能哈.
下面附上正确的代码;
[AppleScript] 纯文本查看 复制代码
package Test;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
//文件过滤筛选拷贝:把指定目录下(不包含子目录)的所有图片,复制到另一个指定目录下(使用文件过滤器来过滤图片)
public class Tr {
	public static void main(String[] args) throws IOException {
		System.out.println("请输入指定复制源文件夹路径:");
		File file1 = getFile();
		System.out.println("请输入指定存放文件夹路径:");
		File file2 = getFile();
		//用一个集合来存放符合拷贝文件的File对象
		List<File> list = new ArrayList<>();
		//寻找所有符合条件的文件并将File对象存入集合
		seek(file1,list);
		//从集合读取文件路径,复制到新的文件夹路径
		copy(file2,list);	
	}
	private static void copy(File file2, List<File> list) throws IOException {
//这里我们需要判断的不是file2是否为空,而是我们是否有需要拷贝的文件;即list是否为空
		if (!list.isEmpty()) {
//在外部创建变量;在内部创建对象,可以在拷贝完成之后一次性关流;
			BufferedOutputStream bos = null;
			BufferedInputStream bts = null; 
			for (File file : list) {
				int x;
//读取的是文件对象
				bts = new BufferedInputStream(new FileInputStream(file));
//写出的也是文件对象,但是通过得到目标文件夹的全路径名和被拷贝文件的文件名中间加上'\\'组成最终的拷贝路径
				bos = new BufferedOutputStream(new FileOutputStream(file2.getAbsolutePath()+"\\"+file.getName()));
				while((x = bts.read()) != -1) {
					bos.write(x);
				}
			}
			bts.close();
			bos.close();
		}
	}
	private static void seek(File file1, List<File> list) {
		File[] filelist = file1.listFiles();
		if (filelist != null) {
			for (File file : filelist) {
				if (file.isFile() && file.getName().endsWith("jpg")) {
					list.add(file);
				}else if (file.isDirectory()) {
					seek(file,list);
				}
			}
		}else{
			System.out.println("文件夹下为空,请检查后输入!");
		}
	}
	//测试样本路径file1		G:\图片\地图
	//测试接收路径file2		H:\新建文件夹
	@SuppressWarnings("resource")
	private static File getFile() {
		Scanner sc = new Scanner(System.in);
		while(true) {	
			String line = sc.nextLine();
			File file = new File(line);
			if (!file.isDirectory()) {
				System.out.println("非文件夹路径,请重新输入:");
			}else{
				System.out.println("文件夹路径输入成功!");
				return file;
			}
		}
	}
}

再次重复:正确的理解应该是,通过IO流实现内存与硬盘的交互时;IO流所操作的一定是文件!!!

评分

参与人数 2黑马币 +10 收起 理由
gaofengdage + 5 神马都是浮云
378657357 + 5

查看全部评分

7 个回复

倒序浏览
撒泼打滚求币
急求
回复 使用道具 举报
哈哈哈哈哈,学霸学霸学霸
回复 使用道具 举报
IO流最容易犯的小错误就是忘了关流,往往在我们写一个关流和不关流都没区别的时候会遗忘关流
回复 使用道具 举报
分析的很到位啊
回复 使用道具 举报
初英 发表于 2016-9-5 11:09
IO流最容易犯的小错误就是忘了关流,往往在我们写一个关流和不关流都没区别的时候会遗忘关流 ...

关流其实是小问题,容易查出来,我说的这个是理解上的错误,理解出错了,这次改了,在没有纠正错误观念之前还是会犯
回复 使用道具 举报
赢无翳 来自手机 中级黑马 2016-9-5 23:57:31
7#
先标记一下回去慢慢看
回复 使用道具 举报
对,,用心想想就知道,肯定是文件
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马