一、File类
File类是java.io下代表与平台无关的文件和目录。也就是说,如果希望在程序中操作文件和目录,都可以通过File类来完成,是java.io包中唯一代表磁盘文件本身的对象。
不管是文件还是目录,都是通过File类来操作,File能新建,删除,重命名文件和目录,File不能访问文件内容本身。
在操作文件之前必须创建一个指向文件的链接或者实例化一个一个文件对象,也可以指定一个不存在的文件从而创建它。使用File类可以可以获取文件本身的一些信息,例如文件所在目录,文件长度,文件读写权限等。
1)构造方法
- File(File parent,String child):根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
- File(String pathname):通过将给定路径名字符串转换成抽象路径名来创建一个新 File 实例。如果给定字符串是空字符串,则结果是空的抽象路径名。
- File(String parent,String child):根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
2)常用方法
表1 File类的常用方法
方法名称 | 说明 |
---|---|
boolean canRead() | 测试应用程序是否能从指定的文件中进行读取 |
boolean canWrite() | 测试应用程序是否能写当前文件 |
boolean delete() | 删除当前对象指定的文件 . |
boolean exists() | 测试当前 File 是否存在 |
String getAbsolutePath() | 返回由该对象表示的文件的绝对路径名 |
String getName() | 返回表示当前对象的文件名 |
String getParent() | 返回当前 File 对象路径名的父路径名,如果此名没有父路径则为 null |
boolean isAbsolute() | 测试当前 File 对象表示的文件是否为一个绝对路径名 |
boolean isDirectory() | 测试当前 File 对象表示的文件是否为一个路径 |
boolean isFile() | 测试当前 File 对象表示的文件是否为一个“普通”文件 |
long lastModified() | 返回当前 File 对象表示的文件最后修改的时间 |
long length() | 返回当前 File 对象表示的文件长度 |
String[] list() | 返回当前 File 对象指定的路径文件列表 |
String[] list(FilenameFilter) | 返回当前 File 对象指定的目录中满足指定过滤器的文件列表 |
boolean mkdir() | 创建一个目录,它的路径名由当前 File 对象指定 |
boolean mkdirs() | 创建一个目录,它的路径名由当前 File 对象指定 |
boolean renameTo(File) |
将当前 File 对象指定的文件更名为给定参数 File 指定的路径名 |
注意:假设在 Windows 操作系统中有一文件 D:javaspacehello.java
,在 Java 中使用的时候,其路径的写法应该为 D:/javaspace/hello.java
或者 D:\javaspace\hello.java
。
3)获取文件属性
@Test public void test(){ /*1.获取文件属性*/ /*假如有一个文件位于E:UalIdeaTestIOTest,名字叫now.txt*/ String path= "E:\UalIdea\Test\IOTest";//指定文件所在目录 File file= new File(path,"now.txt");//建立file变量 System.out.println("now.txt文件信息如下:"); System.out.println("==============================="); System.out.println("文件长度: "+file.length()+"字节"); System.out.println("是不是文件:"+(file.isFile()?"是文件":"不是文件")); System.out.println("是不是目录:"+(file.isDirectory()?"是目录":"不是目录")); System.out.println("是否可读:"+(file.canRead()?"可读":"不可读")); System.out.println("是否可写:"+(file.canWrite()?"可写":"不可写")); System.out.println("是否隐藏:"+(file.isHidden()?"隐藏":"未隐藏")); System.out.println("最后修改日期:"+ DateFormat.getDateInstance(DateFormat.FULL).format(new Date(file.lastModified()))); System.out.println("文件名称:"+file.getName()); System.out.println("文件路径:"+file.getPath()); System.out.println("绝对路径:"+file.getAbsolutePath()); }
输出:
4)创建和删除文件
File 类不仅可以获取已知文件的属性信息,还可以在指定路径创建文件,以及删除一个文件。创建文件需要调用 createNewFile() 方法,删除文件需要调用 delete() 方法。无论是创建还是删除文件通常都先调用 exists() 方法判断文件是否存在。
@Test public void test1(){ /*编写一个文件,判断E盘根目录是否存在IOTest目录,如果存在则先删除再创建*/ String path="E:\IOTest\";//指定目录位置 File f=new File(path); if(f.exists()){ f.delete(); } f.mkdir();//结束 String path1="E:\IOTest\b.txt"; File file= new File(path1); //File file = new File(path,"b.txt");//或用这种方式 if(file.exists()){ file.delete(); System.out.println("删除后创建"); } try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } }
5)遍历目录
通过遍历目录可以在指定的目录中查找文件,或者显示所有的文件列表。File 类的 list() 方法提供了遍历目录功能,该方法有如下两种重载形式。
1. String[] list()
该方法表示返回由 File 对象表示目录中所有文件和子目录名称组成的字符串数组,如果调用的 File 对象不是目录,则返回 null。
提示:list() 方法返回的数组中仅包含文件名称,而不包含路径。但不保证所得数组中的相同字符串将以特定顺序出现,特别是不保证它们按字母顺序出现。
2. String[] list(FilenameFilter filter)
该方法的作用与 list() 方法相同,不同的是返回数组中仅包含符合 filter 过滤器的文件和目录,如果 filter 为 null,则接受所有名称。
@Test public void test2(){ /*假设要遍历C盘根目录下的所有文件和目录,并显示文件或目录名称、类型及大小。使用 list() 方法的实现代码如下:*/ File file = new File("C:\"); System.out.println("文件名称 文件类型 文件大小"); System.out.println("================================================================="); String[] fileList=file.list(); for(int i=0;i<fileList.length;i++){ //遍历返回的字符数组 System.out.print(fileList[i]+" "); System.out.print((new File("C:\",fileList[i])).isFile()?"文件"+"" +" ":"文件夹"+" "); System.out.println((new File("C:\",fileList[i])).length()+"字节"); } }
6)文件过滤器
File类的list()方法可以接收一个FilenameFilter参数,通过该参数可以只列出符合条件的文件。FilenameFilter接口里包含了一个accept(File dir,String name)方法,该方法将依次对指定File的所有子目录或文件进行迭代,如果该方法返回true,则list()方法会列出该子目录或文件。
二、理解java的IO流
1)流的分类:
1.输入流与输出流
按流的方向来分,可分为输入流与输出流(相对于java代码所运行的内存来说)。
输入流:只能从中读取数据,而不能向其中写入数据。(主要由InputStream和Reader作为基类)
输出流:只能向其中写入数据,而不能读取数据。(主要由OutputStream和Writer作为基类)
2.字节流与字符流
两者用法几乎一样,区别在于字节流与字符流操作的数据单元不同-----------字节流操作的数据单元是8位的字节,字符流操作的单元是16位的字符。
字节流主要由InputStream与OutputStream作为基类
字符流主要由Reader与Writer作为基类。
3.节点流与处理流
按流的角色来分,可分为节点流与处理流。
可以从/向一个特定的IO设备(如磁盘,网络)读/写数据的流,称为节点流,节点流也被称为低级流。
处理流则用于对一个已存在的流进行连接或封装,通过封装后的流来实现数据读/写功能,处理流也被称为高级流。
使用处理流的好处是:只要使用相同的处理流,程序就可以采用完全相同的输入/输出代码来访问不同的数据源了,随着处理流包装的节点流的变换,程序所访问的数据源也相应的变换。(使用了装饰器模式)
2)流的概念模型
3)输入输出流
数据流的处理只能按照数据序列的顺序来进行,即前一个数据处理完之后才能处理后一个数据。数据流以输入流的形式被程序获取,再以输出流的形式将数据输出到其他设备。
1. InputStream
所有输入流类都是 InputStream 抽象类(字节输入流)和 Reader 抽象类(字符输入流)的子类。其中 InputStream 类是字节输入流的抽象类,是所有字节输入流的父类
InputStream 类中所有方法遇到错误时都会引发 IOException 异常。如下是该类中包含的常用方法。
- int read():从输入流读入一个 8 字节的数据,将它转换成一个 0~255 的整数,返回一个整数,如果遇到输入流的结尾返回 -1。
- int read(byte[] b):从输入流读取若干字节的数据保存到参数 b 指定的字芳数组中,返回的字芾数表示读取的字节数,如果遇到输入流的结尾返回 -1。
- int read(byte[] b,int off,int len):从输入流读取若干字节的数据保存到参数 b 指定的字节数组中,其中 off 是指在数组中开始保存数据位置的起始下标,len 是指读取字节的位数。返回的是实际读取的字节数,如果遇到输入流的结尾则返回 -1。
- void close():关闭数据流,当完成对数据流的操作之后需要关闭数据流。
- int available():返回可以从数据源读取的数据流的位数。
- skip(long n):从输入流跳过参数 n 指定的字节数目。
- boolean markSupported():判断输入流是否可以重复读取,如果可以就返回 true。
- void mark(int readLimit):如果输入流可以被重复读取,从流的当前位置开始设置标记,readLimit 指定可以设置标记的字节数。
- void reset():使输入流重新定位到刚才被标记的位置,这样可以重新读取标记过的数据。
上述最后 3 个方法一般会结合在一起使用,首先使用 markSupported() 判断,如果可以重复读取,则使用 mark(int readLimit) 方法进行标记,标记完成之后可以使用 read() 方法读取标记范围内的字节数,最后使用 reset() 方法使输入流重新定位到标记的位置,继而完成重复读取操作。
2.Reader
Java 中的字符是 Unicode 编码,即双字节的,而 InputerStream 是用来处理单字节的,在处理字符文本时不是很方便。这时可以使用 Java 的文本输入流 Reader 类,该类是字符输入流的抽象类,即所有字输入流的实现都是它的子类。
Reader类的方法与 InputerSteam 类的方法类似
3. OutputStream
OutputStream 类是所有字节输出流的超类,用于以二进制的形式将数据写入目标设备,该类是抽象类,不能被实例化。OutputStream 类提供了一系列跟数据输出有关的方法,如下所示。
- int write (b):将指定字节的数据写入到输出流。
- int write (byte[] b):将指定字节数组的内容写入输出流。
- int write (byte[] b,int off,int len):将指定字节数组从 off 位置开始的 len 字芳的内容写入输出流。
- close():关闭数据流,当完成对数据流的操作之后需要关闭数据流。
- flush():刷新输出流,强行将缓冲区的内容写入输出流。
4.Writer
4)处理流的用法
我们使用处理流的典型思路是:使用处理流来包装节点流,程序通过处理流来执行输入输出,让节点流与底层IO设备,文件交互。
识别处理流:只要流的构造器参数不是一个节点,而是已经存在的流,那么这种流就一定是处理流。
@Test public void test(){ PrintStream ps=null; /*使用PrintStream包装FileOutputStream,执行输出*/ try { FileOutputStream fo = new FileOutputStream("E:\IOTest\b.txt"); ps = new PrintStream(fo); ps.println("生活");//向文件中打印,每次执行会覆盖 ps.println(new PrintStreamTest()); } catch (FileNotFoundException e) { e.printStackTrace(); }finally { ps.close();//关闭资源时,只用关闭上层处理流,节点流会自动关闭 } }
由于PrintStream功能非常强大,通常我们需要输出文本文件时,都应该将输出流包装成PrintStream。
5)输入输出流体系
6)转换流
InputStreamReader 将字节输入流转换成字符输入流
OutputStreamWriter将字节输出流转换成字符输出流