目录结构:
Java用File来访问文件、目录,以及对它们的删除、创建等。
接下来列出File类中常用的方法:
1. 访问文件名相关的方法
Sring getName():返回此File对象所表示的文件名或路径名(如果是路径则返回最后一级子路径)
String getPath():返回此File对象所对应的路径名
File getAbsoluteFile():返回此File对象所对应的绝对路径名称
String getParent():返回此File对象所对应的目录(最后一级子目录)的父目录名。
boolean renameTo(File newName):重命名此File对象所对应的的文件或是目录,如果重命名成功,则返回true,否则返回false。
2.文件检查相关的方法
boolean exists():判断File对象所对应的文件或目录是否存在。
boolean canWrite():判断File对象所对应的文件或目录是否可写。
boolean canRead():判断File对象所对应的文件或目录是否可读。
boolean isFile():判断File对象所对应的是否是文件。
boolean isDirectory():判断FIle对象所对应的是否是目录。
boolean isAbsolute():判断File所对应的文件或目录是否是绝对路径。该方法消除了不同平台的差异,可以直接判断FIle对象是否为绝对路径。在UNIX/Linux/BSD 等系统,如果路径名开头是一条斜线(/),则表明该File对象所对应一个绝对路径。在Window系统上,如果路径开头盘符,则说明它是一个绝对路径。
3.获取常规文件信息
boolean lastModified():返回文件的最后修改时间。
boolean length():返回文件内容的长度。
4.获取文件的常规信息
boolean createNewFile():当此File对象所对应的文件不存在时,该方法将新建一个该File对象所对应的新文件。如果创建成功则返回true,否则返回false。
boolean delete():删除File对象所对应的文件或是目录。
static File createTempFile(String prefix,String suffix) 在默认的临时文件目录中创建一个临时的空文件,使用给定前缀、系统生成的随机数和给定后缀做文件名。这是一个静态方法,可以直接通过File类来调用。Prefix参数必须至少是3字节长。建议前缀使用一个短的,有意义的字符串。suffix 可以为null,这种情况下默认使用后缀“.temp”。
static File createTempFile(String prefix,String suffix,File directory) 在directory指定的目录中创建一个临时的空文件,使用给定前缀、系统生成的随机数和给定后缀作为文件名。这是一个静态方法,可以直接通过File类来调用。
void deleteOnExit():注册一个删除勾子,指定当Java虚拟机退出时,删除File对象所对应的文件和目录。
5.目录操作相关的方法
boolean mkdir():试图创建一个File对象所对应的目录,如果创建成功,则返回true;否则返回false,调用方法时,File对象必须对应一个路径。
String[] list() 列出File对象的所有子文件名和路径名。
File[] listFiles() 列出File对象的所有子文件和路径。
static File[] listRoots() 列出系统所有的根目录。
下面使用使用递归打印某个目录下及其子目录下的所有的文件名:
public class TestDirPrint { //打印指定目录中的内容,要求子目录中的内容也要打印出来 public static void dirPrint(File f){ //1.若f关联的是普通文件,则直接打印文件名即可 if(f.isFile()){ System.out.println(f.getName()); } //2.若f关联的是目录文件,则打印目录名的同时使用[]括起来 if(f.isDirectory()){ System.out.println("[" + f.getName() + "]"); //3.获取该目录中的所有内容,分别进行打印 File[] ff = f.listFiles(); for(File ft : ff){ dirPrint(ft); } } } }
2. I/O流体系
2.1 流的基本介绍
首先介绍流的分类:
按照流的方向来分,可以分为字节流和字符流。
输入流:只能读取数据。
输出流:只能向其中写入数据。
输入流和输出流都是站在程序的角度进行考虑的。
按照流处理的数据单元不同,可以分为字节流和字符流。
字节流和字符流的用法几乎一致,区别是它们操作的数据单元不同。字节流操作的数据单元是一个字节,字符流操作的数据单元是2个字节。
按照流的角色,可以分为节点流和处理流。
节点流是可以直接向特定的IO设备进行读/写操作的流,这种流也被称为低级流。处理流则用于对一个已存在的流,通过封装后的流来实现数据读/写功能,处理流被称为装饰流或高级流。
java的输入/输出流提供了近40个类,下面按照流的功能进行分类:
| 分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
| 抽象基类 | InputStream | OutputStream | Reader | Writer |
| 访问文件 | FileInputStream | FileOutputStream | FileReader | FileWriter |
| 访问数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
| 访问管道 | PipedInptStream | PipedOutoutStream | PipedReader | PipedWriter |
| 访问字符串 | StringReader | StringWriter | ||
| 缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
| 转化流 | InputStreamReader | OutputStreamWriter | ||
| 对象流 | ObjectInputStream | ObjectOutputStream | ||
| 抽象基类 | FilterInputStream | FilterOutputStream | FilterReader | FilterWriter |
| 打印流 | PrintStream | |||
| 推回输入流 | PushbackInputStream | PushbackReader | ||
| 特殊流 | DataInputStream | DataOutputStream |
我们已经知道字节流的数据单元是一个字节,字符流的数据单元是两个字节。通常情况下,如果访问的是文本内容,那么应该使用字符流,如果访问的是二进制内容,那么应该使用字节流。
使用字节流访问文本内容,如果一次访问不完,那么很有可能出现乱码的情况。
例如有GBK格式编码的文本文件test.txt,内容如下:
“do not give up.不要放弃。”
这段文本中“do not give up.”一共占据15个字节。“不要放弃。”一共占了10个字节。
如果使用如下的代码来访问:
String path="C:\\Users\\dell\\Desktop\\test.txt"; FileInputStream fis=new FileInputStream(new File(path)); byte[] bytes=new byte[1024];//一次读取1024个字节 int offset=0; String result=""; while((offset=fis.read(bytes,0,bytes.length))!=-1){ result+=new String(bytes,0,offset); } System.out.println(result);
由于上面的文本没有1024个字节,所以可以一次性读完,并不会出现乱码情况。
而如果改为一次读取3个字节,那么就会出现乱码。我们甚至还可以推断出,那些字符会出现乱码,由于读取数据的单位为3个字节,所以前面的“do not give up.”会分为5次读完。后面的汉字“不要放弃。”每个汉字占两个字节,为了方便理解,我们把这10个字节用一下这些字符来表示“12 34 56 78 9A”,第一次读取了三个字节123,12可以被正常解析为“不”,后面有一个字节不能被正常解析。第二此又读取三个字节456,45不能被正常解析,6也不能被正常解析。第三次又读取三个字节789,78可以被正常解析,9不能。最后读取最后一个字节A,A也不能被正常解析。所以最终汉字中只有“不”、“弃”可以被正常解析。
2.2 访问文件
在前面介绍过访问文件主要涉及到FileInputStreaam、FileOutputStream、FileReader、FileWriter,如果是二进制文件,那么使用字节流。如果是文本文件,那么使用字符流。
接下使用FileInputStream、FileOutputStream实现对文件的复制:
public class TestFileCopy { public static void main(String[] args) { try{ //1.建立FileInputStream类的对象与源文件建立关联 FileInputStream fis = new FileInputStream("D:/java09/day16/javaseday16-IO流常用的类-06.wmv"); //2.建立FileOutputStream类的对象与目标文件建立关联 FileOutputStream fos = new FileOutputStream("c:/javaseday16-IO流常用的类-06.wmv"); //3.不断地读取源文件中的内容并写入到目标文件中 /* 可以实现文件的拷贝,但是文件比较大时效率很低 int res = 0; while((res = fis.read()) != -1){ fos.write(res); } */ //第二种方案,根据源文件的大小准备对应的缓冲区(数组),可能导致内存溢出 //第三种方案,无论文件的大小是多少,每次都准备一个1024整数倍的数组 byte[] data = new byte[1024 * 8]; int res = 0; while((res = fis.read(data)) != -1){ fos.write(data, 0, res); } System.out.println("拷贝文件结束!"); //4.关闭文件输入流对象 fis.close(); //5.关闭文件输出流对象 fos.close(); }catch(Exception e){ e.printStackTrace(); } } }