ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

JavaEE(4)文件操作和IO

JavaEE(4)文件操作和IO 目录一、操作系统层面到底什么是文件1.1 目录文件夹的树形结构1.2 两种路径绝对路径 vs 相对路径1.3 文件分类文本文件 二进制文件二、Java File类操作文件元信息不读写内容2.1 构造方法2.2 常用API梳理2.3 getPath / getAbsolutePath / getCanonicalPath 区别三、IO流真正读写文件内容3.1 字节输入流 FileInputStream读文件3.2 字节输出流 FileOutputStream写文件3.3 PrintWriter方便的打印输出四、实战小项目案例1文件复制案例2递归扫描目录查找文件名包含关键词的文件可选删除五、小贴士六、知识回顾一、操作系统层面到底什么是文件硬盘是持久化存储设备操作系统将硬盘上的数据抽象为文件。一个文件包含两部分信息文件内容真正保存业务数据文本、图片、视频二进制数据文件元信息文件名、大小、修改时间、权限等不属于文件内容本身。1.1 目录文件夹的树形结构磁盘上文件成千上万操作系统采用树形结构组织文件。目录文件夹本质上是一种特殊文件保存子文件、子目录的元信息。Windows此电脑 → C盘 → Program Files反斜杠\作为路径分隔符Linux/作为根目录正斜杠/分隔路径经典思想万物皆文件把硬件IO设备也抽象成文件来访问。1.2 两种路径绝对路径 vs 相对路径绝对路径从根节点出发完整路径唯一定位一个文件。Windows示例C:\Program Files\test.txt相对路径从当前工作目录出发去找文件。..代表父目录.代表当前目录。注意Windows依靠后缀名识别文件类型.exe、.txtLinux不依赖后缀文件还具备读、写、执行权限操作系统依靠权限做数据安全保护。1.3 文件分类文本文件 二进制文件文本文件内容经过字符集编码UTF‑8/GBK如txt、java源代码。二进制文件没有字符编码直接原始二进制存储图片、exe、压缩包都属于二进制。快捷方式/软链接不是真实文件只是对原文件的引用。二、Java File类操作文件元信息不读写内容java.io.File专门描述文件或者目录的抽象对象。⚠️ 重要new File对象磁盘上不一定真的有这个文件File类只能操作元信息创建、删除、获取路径、判断类型不能读写文件里面的数据。2.1 构造方法// 直接传入路径绝对路径 / 相对路径Filefile1newFile(hello.txt);// 父路径字符串 子文件名Filefile2newFile(./dir,hello.txt);// File对象作为父目录 子文件名FileparentnewFile(./dir);Filefile3newFile(parent,hello.txt);2.2 常用API梳理方法作用getParent()获取父目录路径getName()获取文件名不含路径getPath()创建File时传入的原始路径getAbsolutePath()获取完整绝对路径getCanonicalPath()解析..等符号后的规范化绝对路径exists()判断文件/目录是否真实存在isFile()是否普通文件isDirectory()是否目录createNewFile()创建空文件已存在返回falsedelete()立刻删除文件/空目录deleteOnExit()JVM退出的时候才删除临时文件mkdir()创建单层目录父目录不存在创建失败mkdirs()创建多级目录不存在的父目录一并创建list()获取目录下所有子项名字String数组listFiles()获取目录下所有子项File对象数组renameTo(File dest)文件重命名/剪切粘贴易错提醒mkdir()只能创建一层文件夹多级目录请一定用mkdirs()2.3 getPath / getAbsolutePath / getCanonicalPath 区别举个例子相对路径..\\hello‑world.txtgetPath()原样输出..\hello‑world.txtgetAbsolutePath()拼接上项目工作目录D:\code\demo\..\hello‑world.txtgetCanonicalPath()把..解析抵消掉得到干净路径D:\code\hello‑world.txt。三、IO流真正读写文件内容流的比喻把数据比作水池里面的水。输入流InputStream读从文件流向程序接水输出流OutputStream写从程序流向文件往水池灌水InputStream、OutputStream是抽象类操作文件使用实现类FileInputStream、FileOutputStream。3.1 字节输入流 FileInputStream读文件核心方法int read()读1个字节读到文件末尾返回**‑1**int read(byte[] buf)批量读取到字节数组buf返回读到字节数量末尾返回‑1close()关闭文件资源释放句柄最佳实践使用try‑with‑resources自动调用close避免资源泄露Java7及以上支持资源会自动关闭不需要写finally手动关闭流。示例批量读取性能优于单字节读取importjava.io.FileInputStream;importjava.io.IOException;importjava.io.InputStream;publicclassReadDemo{publicstaticvoidmain(String[]args)throwsIOException{// try()括号中声明流代码结束自动closetry(InputStreamisnewFileInputStream(hello.txt)){byte[]bufnewbyte[1024];// 缓冲区intlen;while((lenis.read(buf))!-1){// buf[0 ~ len‑1] 是本次读到的有效字节for(inti0;ilen;i){System.out.print((char)buf[i]);}}}}}注意字节流拿到原始字节如果直接强转charUTF‑8中文占3字节直接单字节转换会乱码。处理中文文本推荐配合Scanner或者转换流。Scanner包装字节流读取文本try(InputStreamisnewFileInputStream(hello.txt);ScannerscannernewScanner(is,UTF‑8)){while(scanner.hasNextLine()){Stringlinescanner.nextLine();System.out.println(line);}}3.2 字节输出流 FileOutputStream写文件核心APIwrite(int b)写入一个字节write(byte[] b)写入整个字节数组write(byte[] b,int off,int len)数组从off开始写len长度字节flush()刷新缓冲区数据先放在内存缓冲区调用flush才真正刷入磁盘close也会自动flush。close()关闭流FileOutputStream默认会清空原有文件内容从头覆盖写入。简单写文件示例importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.OutputStream;publicclassWriteDemo{publicstaticvoidmain(String[]args)throwsIOException{try(OutputStreamosnewFileOutputStream(output.txt)){Stringcontent你好JavaIO;byte[]datacontent.getBytes(UTF‑8);os.write(data);os.flush();// 强制刷盘}}}3.3 PrintWriter方便的打印输出如果想直接使用print / println / printf可借助转换流OutputStreamWriter将字节流转为字符流再套上PrintWritertry(OutputStreamosnewFileOutputStream(out.txt);OutputStreamWriterwriternewOutputStreamWriter(os,UTF‑8);PrintWriterprintWriternewPrintWriter(writer)){printWriter.println(第一行文本);printWriter.printf(数字%d\n,100);printWriter.flush();}四、实战小项目案例1文件复制读取源文件写入目标文件对二进制数据通用文本、图片都支持。importjava.io.*;importjava.util.Scanner;publicclassFileCopy{publicstaticvoidmain(String[]args)throwsIOException{ScannerscnewScanner(System.in);System.out.print(输入源文件路径);StringsrcPathsc.next();FilesrcnewFile(srcPath);if(!src.exists()||!src.isFile()){System.out.println(源文件错误);return;}System.out.print(输入目标路径);StringdestPathsc.next();FiledestnewFile(destPath);if(dest.exists()){System.out.print(目标已存在是否覆盖 y/n);Stringopsc.next();if(!y.equalsIgnoreCase(op)){return;}}try(InputStreaminnewFileInputStream(src);OutputStreamoutnewFileOutputStream(dest)){byte[]bufnewbyte[1024];intlen;while((lenin.read(buf))!-1){out.write(buf,0,len);}out.flush();}System.out.println(复制完成);}}案例2递归扫描目录查找文件名包含关键词的文件可选删除文件系统是树形使用深度优先递归遍历目录importjava.io.File;importjava.io.IOException;importjava.util.ArrayList;importjava.util.List;importjava.util.Scanner;publicclassScanFileDemo{publicstaticvoidmain(String[]args)throwsIOException{ScannerscnewScanner(System.in);System.out.print(输入扫描根目录);StringrootPathsc.next();FilerootnewFile(rootPath);if(!root.exists()||!root.isDirectory()){System.out.println(目录无效);return;}System.out.print(输入要匹配文件名关键字);Stringkeywordsc.next();ListFileresultnewArrayList();scanDir(root,keyword,result);System.out.println(找到result.size()个匹配文件);for(Filef:result){System.out.println(f.getCanonicalPath());System.out.print(是否删除(y/n));Stringopsc.next();if(y.equalsIgnoreCase(op)){f.delete();System.out.println(已删除);}}}privatestaticvoidscanDir(Filedir,Stringkeyword,ListFileres){File[]subsdir.listFiles();if(subsnull)return;for(Filef:subs){if(f.isDirectory()){scanDir(f,keyword,res);}else{if(f.getName().contains(keyword)){res.add(f);}}}}}五、小贴士File对象创建不等于磁盘存在必须调用createNewFile/mkdir/mkdirs判断存在必须调用exists()。创建多级目录不要用mkdir()要用mkdirs()。IO流一定要关闭优先try‑with‑resources自动关闭杜绝文件句柄泄露。写输出流切记flush()缓冲区没刷盘会出现数据丢失。中文读写务必指定编码UTF‑8否则系统默认编码不一致产生乱码。read()返回‑1代表读取结束不要把读到的字节直接当成char处理中文。delete()删除文件不走回收站删除前一定要确认业务逻辑。六、知识回顾操作系统层文件内容元信息→目录树结构→绝对/相对路径→文本/二进制文件File类只操作元信息创建对象≠真实存在熟悉路径获取、创建删除、遍历目录IO流InputStream读OutputStream写字节流通用所有文件try‑with‑resources管理资源flush刷缓冲区实战文件复制、递归遍历目录搜索文件写IO代码的时候记住File管文件本身流管文件里面的数据把两件事分开就不容易混淆。
返回列表