1.路径
相对路径:目录起点为当前工作位置 可以使用./代替
比如当前工作目录为C:/ 那么相对路径就可以写成./code/ 其完整意思为:C:/code
../表示返回上一级路径 比如当前目录在./code/tmp 使用../code就可以返回上一级code目录下
绝对路径:完整的路径地址
文件分类:
文本文件:存放的是文本-----字符串 每一个字符对应一个数字
二进制文件:存放的是二进制数据 没有任何限制
IO相关方法
public static void main(String[] args) throws IOException { //创建一个文件 File file = new File("./text.txt"); //创建一个文件夹 mkdir只能创建一级目录 File file1 = new File("./aaa"); file1.mkdir(); //mkdirs 可以创建多级目录 File file2 = new File("./aaa/bbb/ccc"); file2.mkdirs(); //如果已经有此文件了 则创建失败 System.out.println(file.createNewFile()); //文件是否存在 System.out.println(file.exists()); //是否是一个文件 System.out.println("是否是一个文件:"+file2.isFile()); //是否是一个文件夹 System.out.println(file.isDirectory()); //在本地IDEA的基础上的路径 ./aaa/bbb/ccc //得到文件的相对路径 System.out.println("file2相对路径:"+file2.getPath()); //D:\code\review\review\IOoperation\.\aaa\bbb\ccc //得到文件的绝对路径 System.out.println("file2绝对路径:"+file2.getAbsoluteFile()); System.out.println(file.getName()); //删除文件夹 --- 文件夹里的内容必须是空的才能使用delete方法删除 File file3 = new File("./aaa/bbb/ccc"); System.out.println(file3.delete()); }
- mkdir只能创建一级目录 mkdirs可以创建多级目录
- 当使用delete删除文件夹时,文件夹下必须没有任何内容才能被删除,否则删除失败
文件流:
字节流
操作二进制数据
InputSteam OutputStream / FileInputStream FileOutputStream
读文件:
//读文件 InputStream inputStream = new FileInputStream("./text.txt"); //字节字节 无参情况下 一次读一个字节 while(true){ //返回值为int 因为要用-1来表示文件被读完 int b = inputStream.read(); //当为-1时结束读 if(b == (char)-1){ break; } System.out.print(b); //得到字符ASCII码值 }
如果是无参的话,一次读一个字节,如果想一次多读,可以给定一个字节数组
read()方法返回的是int类型 当为-1时结束读操作
写文件:
//写操作 File outputFile = new File("./text2.txt"); outputFile.createNewFile(); OutputStream outputStream = new FileOutputStream(outputFile); //outputStream.write(97); //outputStream.write(98); //outputStream.write(99); //outputStream.write(100); //默认情况下 对于outputSteam来说,每重新打开一个文件时 会先清空里面的内容 如果不想清空 想追加在其后面 可以使用追加流 String res = "Hello Word"; //字符串可以直接转字节数组 int[] arr = {1,2,3}; outputStream.write(1 + '0'); //会写入答案会转成byte 想写入数组就需要+'0' }
需要注意的是,使用ouputStream时,每重新打开一次写的文件,都会先清空内容,如果想追加在内容后面写时,我们可以使用追加流对象,在下面字符流中会提到
字符流
操作文本文件
Reader Writer / FileReader FileWriter
写文件:
public static void main(String[] args) throws IOException { File file = new File("./text3.txt"); //不写./默认本地路径下 file.createNewFile(); //读操作 Reader reader = new FileReader(file); while(true){ int ch = reader.read(); //返回值也是int 当为-1时表示文件读完 if(ch == -1){ break; } System.out.print((char)ch); }
read的返回值也是int,当为-1时表示读完,读的是字符/字符数组/字符串
写操作
//写操作 File file1 = new File("./text4.txt"); file1.createNewFile(); Writer writer = new FileWriter(file1); String s = "你说你爱过的人都已经离去"; //这样的写操作 大多是将内容写入缓冲区中 执行完后 可能还在缓冲区中 并没有写入硬盘 //此时可以使用flush // close操作--->会触发缓冲区刷新 来刷新缓冲区中的内容到硬盘 writer.write(s); writer.flush();
写操作后,需要调用flush方法,为很有可能只是写入了缓冲区中,并还没有写入到硬盘上,故内容无法显示,使用flush可以将缓冲区中的内容刷新到硬盘上
追加写操作
public static void main(String[] args) throws IOException { File file = new File("./aaa/text.txt"); file.createNewFile(); //字符流 --- 文本文件 //1.追加写操作 ----- FileWriter 追加流对象 FileWriter fileWriter = new FileWriter(file,true); String src = " 我借来寄托"; fileWriter.write(src); fileWriter.flush(); //2.追加写操作 × //Writer writer = new FileWriter(file); //并没有实现追加功能 //writer.append(null); //writer.flush(); }
将构造方法时第二个参数boolean append设置为true,即可在原本内容后面进行追加写
拷贝文件
public static void main(String[] args) throws IOException { //复制文本文件到指定目录 //语法点:try with resources 此时不需要flush操作了 //此时这种写法虽然没有写close 但在try语句块执行完后 会自动执行close //条件:放在try语句块中的对象必须要实现Closeable接口 ---- 提供的方法就是close try( Reader reader = new FileReader("./text.txt"); Writer writer = new FileWriter("C:/Users/depth/Desktop/text.txt")){ while(true){ int ch = reader.read(); if(ch == -1){ break; } //换转换成字符 writer.write(ch); } }catch (Exception e){ e.printStackTrace(); } }
注意这里的语法点:try with resources
当将流对象放在try代码块中,这样当try中的代码块执行完后,会自动执行close方法,而close方法中就会刷新缓冲区,这样就可以不用调用flush方法了
注意,前提条件:try代码块中的对象必须实现Closeable接口,其接口提供的方法就是close
删除指定文件夹
public class deleteFile { private static Scanner sc = new Scanner(System.in); //循环扫描文件 / 文件夹 public static void scanDir(File root, String fileName){ File[] fileLists = root.listFiles(); if(root == null){ return; } for(File file : fileLists){ if(file.isFile()){ continue; }else if(file.isDirectory()){ File[] files = file.listFiles(); for(File f : files){ if(f.getName().contains(fileName)){ System.out.println("是否确定删除此文件夹:"+f.getAbsolutePath()); System.out.println("Y:删除 其他:取消"); String option = sc.next(); if(option.equals("Y")){ deleteFolder(f); System.out.println("删除完成"); }else{ System.out.println("取消删除"); } } } scanDir(file,fileName); } } } //循环遍历删除文件夹及子内容 public static void deleteFolder(File file){ File[] files = file.listFiles(); for(File f : files){ if(f.isFile()){ f.delete(); }else{ deleteFolder(f); } } //只有文件夹为空时 才可以使用delete方法删除文件夹对象 file.delete(); } public static void main(String[] args) { //指定删除文件 / 文件夹 while(true){ System.out.println("请输入删除文件的路径"); String dir = sc.next(); File file = new File(dir); if(!file.isDirectory()){ System.out.println("此路径否目录 请重新输入"); } System.out.println("请输入需要删除的文件名"); String fileName = sc.next(); scanDir(file,fileName); } } }
值得注意的是删除文件夹操作:循环遍历删除,如果有子文件夹,先把子文件夹下的文件全部删除后,再删除子文件夹,因为delete方法删除文件夹只能删除空的文件夹
close:
每一个pcb(程序控制块)下都有一个文件操作描述符,当我们进行IO操作时,就会在里面申请位置,将相关信息放到里面
是否需要必须执行close操作?
如果是执行一个程序,里面的文件操作对象自始至终地都要使用,那么此时不执行close方法
也没什么,因为随着程序的关闭,pcb随之销毁,文件操作描述符也会随之销毁
但不怕一万 就怕万一
如果我们一直都不执行close方法,有小伙也会说,咱不是还有GC垃圾回收,但可能回收的不及时,当文件操作描述符被沾满后(是个数组,不会自动扩容,有长度上限),此时打开文件就失败了
那怎么样才能保证能执行到close方法呢?----- try with resources
将能执行close方法的对象放到try代码块中,虽然这里没有显示的执行close方法,但会自动执行的,注意放进去的对象必须得实现Closeable接口才会被自动释放