一.基本文件操作
获取及判断文件属性
代码示例如下:
import java.io.IOException; public class test { public static void main(String[] args) throws IOException { File file = new File("./test.txt"); System.out.println(file.getParent()); System.out.println(file.getName()); System.out.println(file.getPath()); System.out.println(file.getAbsolutePath()); System.out.println(file.getCanonicalPath()); //创建文件前 System.out.println(file.exists()); System.out.println(file.isDirectory()); System.out.println(file.isFile()); System.out.println("---------------"); //创建文件后 file.createNewFile(); System.out.println(file.exists()); System.out.println(file.isDirectory()); System.out.println(file.isFile()); //删除文件 System.out.println("--------------"); file.delete(); System.out.println(file.exists()); } }
getParent():获取上级目录,若无指定则返回null
getName():获取当前文件名
getPath():获取以工作目录为基准的相对路径
getAbsolutePath():获取以盘头为起始点的绝对路径
getCanonicalPath():同上,但是会进行一些精简
exists():判断文件是否存在
isDirectory():判断文件是否是目录
isFile():判断文件是否是文件
delete():删除文件
上述代码的运行结果如下:
创建及修改文件
import java.io.File; import java.io.IOException; public class test { public static void main(String[] args) throws IOException { File file = new File("./test.txt"); file.createNewFile(); //退出时删除 file.deleteOnExit(); System.out.println(file.exists()); } }
deleteOnExit():退出时删除
createNewFile():创建对应文件
public class test { public static void main(String[] args) throws IOException { File file = new File("./test"); //创建单级目录 file.mkdir(); //创建多级目录 File file1 = new File("test1/a/11"); file1.mkdirs(); } }
上述代码运行结果如下:
mkdir():根据路径创建单级目录
mkdirs():根据路径创建多级目录
public class test { public static void main(String[] args) throws IOException { File file1 = new File("test"); File file2 = new File("test1"); //重命名 file1.renameTo(file2); } }
renameTo():将一个文件的名字赋值给另一个文件
二.文件读写
读文件
字节流
我们事先准备一个test.txt文件,里面包含内容"Hello".
public class test { public static void main(String[] args) throws IOException { File file = new File("text1.txt"); file.createNewFile(); //打开文件 InputStream inputStream = new FileInputStream("text1.txt"); //读文件 while(true){ int b = inputStream.read(); if(b == -1){ break; } System.out.println(b); } //关闭文件 inputStream.close(); } }
实际上,read()有很多个版本,具体如下:
上述代码中使用的是第一个版本,一次读取一个字节,并将这个字节的内容作为返回值返回,如果读取到文件结束符(EOF),则返回-1.
第二个版本要求一个"输出型参数"---一个字节数组.read()会从文件里把内容全部读入该字节数组中,若溢出则截断.
第三个版本与第二个版本相似,只不过允许通过参数控制数据的传入起点和终点(也即允许传入的数据长度).
上述代码的运行结果如下:
可见读取的是"Hello"每个字符对应的ASCII码值.
这样可读性无疑是很低的,我们可以将其转为字符串的形式输出,代码示例如下:
public class test { public static void main(String[] args) throws IOException { File file = new File("text1.txt"); file.createNewFile(); //打开文件 InputStream inputStream = new FileInputStream("text1.txt"); //读文件 byte[] b = new byte[1024]; int len = inputStream.read(b); String s = new String(b,0,len,"utf8"); System.out.println(s); //关闭文件 inputStream.close(); } }
我们可以通过读出来的字节数组,反向构造出其原本的字符串,这样就能得到"Hello"了,但这样无疑很麻烦.因此,对于这种非二进制的数组,我们可以使用字符流.
字符流
字符流对应着Reader和FileReader两个关键字.
public class test { public static void main(String[] args) throws IOException { File file = new File("text1.txt"); file.createNewFile(); //打开文件 Reader reader = new FileReader("text1.txt"); char[] buffer = new char[1024]; int len = reader.read(buffer); for (int i = 0; i < len; i++) { System.out.print(buffer[i]); } reader.close(); } }
这样输出出来的直接就是"Hello",而不是ASCII码值.
其他要点
1.InputStream和Reader两个都是抽象类,没办法直接实例化.因此我们需要借助他们的子类FileInputStream和FileReader来实例化.
2.我们创建的文件都在硬盘上,直接操作的话比较困难.因此我们尝试在内存上创建一个媒介,间接的操作硬盘上的文件.我们将InputStream和Reader这种媒介成为句柄(Handler).
3.上述代码的写法实际上是不严谨的,因为一旦程序在运行途中抛出了异常,代码末尾的close()就无法执行.因此我们应该把close()放在finally下.保证在文件描述符表上的资源得以释放.
4.关于文件描述符表:文件描述符表可以简单理解成PCB中的一个数组/顺序表.数组中的每个元素都对应着当前进程打开的文件.这个数组的下标,就称为"文件描述符".每当我们打开一个文件时,就会在文件描述符表中占据一个位置;每次关闭文件,都会释放一个位置.然而文件描述表的长度是存在上限的,如果在进程中一直打开文件而不释放,这就会导致进程在后续打开文件的时候抛出异常.
5.实际上,我们有一套更实用的方法从文件中读取内容,代码示例如下:
public class test { public static void main(String[] args) throws IOException { File file = new File("text1.txt"); file.createNewFile(); InputStream inputStream = new FileInputStream("text1.txt"); Scanner scanner = new Scanner(inputStream); String s = scanner.next(); System.out.println(s); } }
我们可以将InputStream作为Scanner构造函数的参数,这样我们就可以使用Scanner灵活读取文件内部的内容.
写文件
字节流
对于字节流的输入方式,我们有OutputStream和FileOutputStream这一套组合.
public class test { public static void main(String[] args) throws IOException { File file = new File("text1.txt"); file.createNewFile(); try(OutputStream outputStream = new FileOutputStream("text1.txt")){ outputStream.write('h'); outputStream.write('e'); outputStream.write('l'); outputStream.write('l'); outputStream.write('o'); }catch(IOException e){ e.printStackTrace(); } } }
字符流
对于字符流的输入方式,我们有Writer和FileWriter这一套组合.
public class test { public static void main(String[] args) throws IOException { File file = new File("text1.txt"); file.createNewFile(); try(Writer writer = new FileWriter("text1.txt")){ writer.write("hello"); }catch(IOException e){ e.printStackTrace(); } } }
字节流封装
与读取文件内容部分一样,我们可以将字节流封装,其可以灵活的向文件内写内容.
public class test { public static void main(String[] args) throws IOException { File file = new File("text.txt"); file.createNewFile(); try(OutputStream outputStream = new FileOutputStream("text.txt")){ PrintWriter printWriter = new PrintWriter(outputStream); printWriter.println("hello"); printWriter.flush(); }catch (IOException e){ e.printStackTrace(); } } }
此处封装过后,就可以如常规输出一样,向文件里输入内容.代码中flush()的作用在于清空输入缓冲区的内容,使println()输出的内容能成功到文件中.
其他要点
上述代码中我们把OutputStream等输入输出流放在try()中,其目的是在代码结束后可以自动调用close()方法释放文件描述符表,防止忘记.这要求这个类要实现Closeable接口.
到此这篇关于Java文件管理操作的知识点整理的文章就介绍到这了,更多相关Java文件管理内容请搜索好代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持好代码网!