学习了文件操作 IO流相关知识,我们来写一个小demo;仿制Windos系统CMD,MacOS系统的终端做一个命令行窗口,当然,仅有文件目录操作相关功能—— 增删改查 拷贝等。
当我们要做一个项目的时候,就得先想想这个项目要有什么功能,再将这些功能列出来,放在一个类里面自定义实现这些功能;先确定好主干,在添加枝叶!下面为这个工具的UML图 功能实现示意图
创建所需的类,再进行完善
- 演示:
ICmd和ICommand接口
// 接口内的方法 前面默认修饰符 public abstract
public interface ICommand {
/**
* 列出当前目录的所有名字 名字+size
* @return
*/
boolean list();
/**
* 在当前目录下创建一个目录
* @param path
* @return
*/
boolean mkdir(String path);
/**
* 将src的文件拷贝一份到des处
* @param src
* @param des
* @return
*/
boolean copy(String src, String des);
/**
* 删除文件/目录
* @param path
* @return
*/
boolean remove(String path);
/**
* 切换当前目录到子目录
* @param path
* @return
*/
boolean cd_to_child(String path);
/**
* 切换到上一层目录
* @return
*/
boolean cd_to_parent();
/**
* 判断路径文件/目录是否存在
* @param path
* @return
*/
boolean isExists(String path);
}
public interface ICmd {
String LS = "ls";
String MKDIR = "mkdir";
String COPY = "copy";
String RM = "rm";
String CD = "cd";
String CDP = "cd..";
/**
* "ls:列出当前目录所有内容; mkdir:创建一个目录;" + "copy:拷贝; rm:删除; cd:进入一个目录; cd..:进入上一层目录
*/
String[] COMMANDS = new String[]{LS,MKDIR,COPY,RM,CD,CDP};
}
FileManager
public class FileManager {
private static FileManager manager;
private FileManager(){
}
public static FileManager getInstance(){
if (manager == null){
synchronized (FileManager.class){
if (manager == null){
manager = new FileManager();
}
}
}
return manager;
}
/**
* 创建目录
* @param path
* @return
*/
public boolean mkdir(String path){
File file = new File(path);
if (file.exists()){
return false;
}
// desktop/file/image/1.jpg
// mkdir 要求路径中的目录都存在
// mkdirs 如果路径中的目录不存在 也会自动创建 一直创建到头
return file.mkdir();
}
/**
* 删除文件目录
* @param path
* @return
*/
public boolean remove(String path){
File file = new File(path);
if (!file.exists()){
return false;
}
return file.delete();
}
public boolean isExists(String path){
File file = new File(path);
if(file.exists()){
return true;
} else {
return false;
}
}
/**
* 列出文件信息
* @param path
* @return
*/
public File[] list(String path){
File file = new File(path);
if (!file.exists()){
return null;
}
return file.listFiles(new FilenameFilter() {
@Override
public boolean accept(File file, String s) {
if (s.startsWith(".")){
return false;
}
return true;
}
});
}
/**
* 拷贝文件
*/
public boolean copy(String src,String des){
File srcFile = new File(src);
File desFile = new File(des);
//判断文件是否存在
if (!srcFile.exists() || desFile.exists()){
return false;
}
//判断是不是文件
if (srcFile.isFile()){
//直接copy文件
copyFile(src, des);
}else{
//是目录
//创建当前的目录
desFile.mkdir();
//需要将源目录的所有内容copy到des目录
for (File file: srcFile.listFiles()){
copy(file.getAbsolutePath(),des+"/"+file.getName());
}
}
return true;
}
private void copyFile(String src, String des){
FileInputStream fis = null;
BufferedInputStream bis = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
try {
//创建输入流
fis = new FileInputStream(src);
bis = new BufferedInputStream(fis);
//创建输出流
fos = new FileOutputStream(des);
bos = new BufferedOutputStream(fos);
//创建buffer
byte[] buffer = new byte[1024];
int len = 0;
while ((len = bis.read(buffer)) != -1){
bos.write(buffer);
}
bos.flush();
}catch (Exception e){
e.printStackTrace();
}finally {
try {
bis.close();
fis.close();
bos.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
CommandTool
- 接受用户指令 和 处理指令
public class CommandTool implements ICommand{
// 默认启动起来操作的目录
public static final String DESKTOP_PATH = "/Users/lijin";
// 记录当前操作的路径
private StringBuilder currentPath;
public CommandTool() {
currentPath = new StringBuilder(DESKTOP_PATH);
}
// 启动命令行工具
public void start() throws PXDException.CommandNotExistException {
// 创建读取指令类的对象
CommandOperation commandOperation = new CommandOperation();
// 启动界面
System.out.println("欢迎使用命令行工具!");
while(true) {
// 显示目录提示
showParent();
// 输入指令进行读取
try {
commandOperation.readCommand(this);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
private void showParent(){
// 获取最后一个/的索引值 index
int start = currentPath.lastIndexOf("/");
// 获取最后的内容
String parent = currentPath.substring(start);
// 输出提示内容
System.out.print(parent+"$ ");
}
@Override
public boolean list() {
File[] files = FileManager.getInstance().list(currentPath.toString());
for (File file: files){
// 获取文件名
String name = file.getName();
// 获取文件长度 字节
long size = file.length();
long kb = size / 1024;
long by = size % 1024;
System.out.print(name);
for (int i = 0; i < 40 - name.length(); i++){
System.out.print(" ");
}
System.out.println(kb+"."+by+"kb");
}
return false;
}
@Override
public boolean mkdir(String path) {
// 拼接完整路径
String dirPath = currentPath.toString() + "/" + path;
FileManager.getInstance().mkdir(dirPath);
return false;
}
@Override
public boolean copy(String src, String des) {
// 拼接完整路径
String srcPath = currentPath.toString() + "/" + src;
String desPath = currentPath.toString() + "/" + des;
FileManager.getInstance().copy(srcPath, desPath);
return false;
}
@Override
public boolean remove(String path) {
String dirPath = currentPath.toString() + "/" + path;
FileManager.getInstance().remove(dirPath);
return false;
}
@Override
public boolean cd_to_child(String path) {
currentPath.append("/"+path);
System.out.println("进入子目录:"+ currentPath.toString());
return false;
}
@Override
public boolean cd_to_parent() {
int start = currentPath.toString().lastIndexOf("/");
int end = currentPath.length();
currentPath.delete(start, end);
return false;
}
@Override
public boolean isExists(String path) {
String dirPath = currentPath.toString() + "/" + path;
if (FileManager.getInstance().isExists(dirPath)){
return false;
}
return true;
}
}
CommandOperation
public class CommandOperation {
// 回调对象
private ICommand listener;
// 获取输入对象
// next() 以空格作为结束符
// nextLine() 读取一行数据 以/n做回结尾
private Scanner mScanner;
// 保存所有指令
private List<String> commands;
public CommandOperation() {
mScanner = new Scanner(System.in);
// 将普通的 Array类型 转换成 List
commands = Arrays.asList(ICmd.COMMANDS);
}
// 接受用户输入的指令 并进行实现
public void readCommand(ICommand listener) throws PXDException.CommandNotExistException, PXDException.CommandArgumentErrorException { // 多态 子类向父类转
this.listener = listener;
// 接收指令
String command = mScanner.nextLine();
// 解析指令
parseCommand(command);
}
// 以下为 readCommand 方法实现的 内部协作方法
/**
* 解析指令的方法
*/
public void parseCommand(String command) throws PXDException.CommandNotExistException, PXDException.CommandArgumentErrorException {
// 将指令以空格为分割符 分开
String[] componts = command.split(" ");
// 获取第指令的类型 -> 首个内容
String cmd = componts[0];
// 判断指令是否存在
if (!commands.contains(cmd)){
// 指令不存在 抛出异常
throw new PXDException.CommandNotExistException("指令不存在");
}
// 判断是哪种操作
switch (cmd){
case ICmd.CD:
// cd filename
if (componts.length != 2){
throw new PXDException.CommandArgumentErrorException("cd 参数不正确");
}
if (listener.isExists(componts[1])){
listener.mkdir(componts[1]);
}
listener.cd_to_child(componts[1]);
break;
case ICmd.CDP:
// cd..
if (componts.length != 1){
throw new PXDException.CommandArgumentErrorException("cd.. 不需要参数");
}
listener.cd_to_parent();
break;
case ICmd.MKDIR:
// mkdir file
if (componts.length != 2){
throw new PXDException.CommandArgumentErrorException("mkdir 不需要参数");
}
listener.mkdir(componts[1]);
break;
case ICmd.RM:
// rm file
if (componts.length != 2){
throw new PXDException.CommandArgumentErrorException("rm 不需要参数");
}
listener.remove(componts[1]);
break;
case ICmd.LS:
if (componts.length != 1){
throw new PXDException.CommandArgumentErrorException("ls 不需要参数");
}
listener.list();
break;
case ICmd.COPY:
// copy file1 file2
if (componts.length != 3){
throw new PXDException.CommandArgumentErrorException("copy 参数错误");
}
listener.copy(componts[1],componts[2]);
break;
}
}
}
自定义异常
public class PXDException {
/**
* 指令不存在
*/
static class CommandNotExistException extends Exception{
public CommandNotExistException(String s) {
super(s);
}
}
static class CommandArgumentErrorException extends Exception{
public CommandArgumentErrorException(String s) {
super(s);
}
}
}