一、File类的有什么作用
java.io.File 用于表示文件(目录),也就是说程序员可以通过File类在程序中操作硬盘上的文件和目录.
File类只用于表示文件(目录)的信息(名称 大小等),不能对文件内容进行访问(访问用RandomAccessFile)
二、 java.io.File 基本 API
File 代表文件系统中对文件/目录的管理操作(增删改查, CRUD)
常用API方法:
File(String) 指定文件名的构造器
long length() 文件的长度
long lastModified() 最后一次修改的时间(是个long)
String getName() 返回由此抽象路径名表示的文件或目录的名称。
String getPath() 将此抽象路径名转换为一个路径名字符串
boolean exists() 检查是否存在
boolean dir.isFile() 检查是否是文件
boolean dir.isDirectory() 检查是否是目录/文件夹
boolean mkdir() 创建一个目录
boolean mkdirs() 创建一系列目录(demo/sub/sub同时创建3个文件夹)
boolean delete() 删除此抽象路径名表示的文件或目录
(如果此路径名表示一个目录,则该目录必须为空才能删除。 )
boolean createNewFile() throw IOException 当且仅当不存在具有此抽象路径名指定名
称的文件时,不可分地创建一个新的空文件
File[] listFile() 返回一个抽象路径名数组,这些路径名表示此
抽象路径名表示的目录中的文件
例子:
1 import java.io.File; 2 import java.io.IOException; 3 /** 4 * 文件系统的管理 :pwd,ls 5 * 6 */ 7 public class FSDemo { 8 9 public static void main(String[] args) throws IOException { 10 /*注意:Java程序的当前目录:是JAVA程序的启动文件夹,在 11 * ECLIPSE开发的项目中,启动文件夹是项目文件夹,就是当前目录*/ 12 File dir = new File(".");//当前目录 13 14 //getCanonicalPath():返回的规范的路径名,不包括: . .. 15 String path = dir.getCanonicalPath(); 16 System.out.println(path); 17 18 //getAbsolutePath(): 返回绝对路径,可能包含 :. .. 19 path = dir.getAbsolutePath(); 20 System.out.println(path); 21 //以上代码相当于:Linux的pwd命令 22 23 //File demo = new File("demo");//相对路径 24 File demo = new File(dir,"demo");//dir是父目录,这里的dir就是.(当前目录) 25 26 //new File()只是在内存中创建对象,不代表在硬盘上创建文件夹 27 //或文件,可以使用方法exists()检查文件/文件甲是否存在 28 29 System.out.println(demo.exists());//false 30 //检查当前目录下有没有demo文件对象 31 if(!demo.exists()){ 32 demo.mkdir();//创建文件夹 33 //demo.mkdirs();创建系列文件夹,如:demo/sub/sub 34 } 35 File file = new File(demo,"demo.txt"); 36 if(!file.exists()){ 37 file.createNewFile();//创建文件, 38 } 39 System.out.println(file.isDirectory());//false 40 System.out.println(file.isFile());//true 41 System.out.println(demo.isDirectory());//true 42 System.out.println(demo.isFile());//false 43 44 System.out.println(file.canRead());//true 该文件是否可读 45 System.out.println(file.isHidden());//false 该文件或目录是否为隐藏 46 System.out.println(file.lastModified());//1334837570000(返回long的毫秒数) 47 System.out.println(file.length());//0 48 49 file.delete();//删除文件 50 demo.delete();//只能删除空文件夹 51 } 52 }
例子2
1 import java.io.File; 2 import java.util.Arrays; 3 import java.util.Comparator; 4 5 public class ListFileDemo { 6 public static void main(String[] args) { 7 //以下代码相当于linux的ls命令 8 File dir = new File("/etc");//在linux操作系统下 9 File[] files = dir.listFiles(); 10 for(File file: files){ 11 System.out.println(file); 12 } 13 } 14 15 }
三 回调模式和FileFilter
FileFilter 类是对操作文件的过滤,相当于Linux命令:ls|grep p
API 方法 :File[] listFile(FileFilter)
例
1 import java.io.File; 2 import java.io.FileFilter; 3 4 public class ListFilesDemo2 { 5 public static void main(String[] args) { 6 //ls /etc |grep p 7 File dir = new File("/etc"); 8 /*dir.listFiles(filter)重载的列目录方法,参数是过滤条件 9 根据过滤条件过滤列目录的结果 10 FileFilter 接口,声明了过滤方法accapt(file) 如果这个方法返回 11 true,表示这个文件被接受,保留作为方法的结果 12 */ 13 14 File[] files = dir.listFiles(new FileFilter(){ 15 public boolean accept(File file){ //此方法的调用属于回调模式(不用自己去调用) 16 return file.isFile() && 17 file.getName().matches(".+p.+");//此处代表文件名中有p,可用正则表达式 18 } 19 }); 20 for(File file:files){ 21 if(file.isDirectory()){//根据是文件夹还是文件作出有差别的打印 22 System.out.println("["+file.getName()+"]"); 23 }else{ 24 System.out.println(file.getName()); 25 } 26 } 27 } 28 }
四 RandomAccessFile
RandomAccessFile类有什么用?
RandomAccessFile类是Java提供的功能丰富的文件内容访问类,它提供了多种方法访问文件
内容,既可以读取文件内容,也可以向文件输出数据,RandomAccessFile支持"随即访问"方式,可以访问文件的任意位置
1)Java 文件模型,文件是byte by byte 是数据集合
data : 41 42 00 00 00 ff d6 d0 ……
index: 0 1 2 3 4 5 6 7 ……
porinter: ^
注意:data中为16进制数
16进制:41 对应 0100 0001 是一个字节
1024*1024*1024*1024
k M G T
5M Byte = 5 * 1024 * 1024个Byte组成的序列
2) 打开文件,有两种模式"rw"(读写),"r"(读)
RandomAccessFile raf = new RandomAccessFile(file,"rw");
打开文件时候默认文件指针在开头 pointer = 0
3)写入方法:raf.write(int)将整整的" 低八位"写入到文件中,
指针自动移动到下一个位置,准备再次写入
* 文件名的扩展名要明确指定,没有默认扩展名现象!
4)读取文件
int b = raf.read() 从文件中读取一个byte(8位)填充到int 的低8位,高24位为0,返回值
范围整数:0-255,如果返回-1表示读取到了文件末尾!每次读取后自动移动文件指针,准备下次读取
5) 文件读写完成以后一定要关闭文件
Sun官方说明,如果不关闭,可能遇到一些意想不到的错误,根据具体操作平台不同会有不同
在使用过程中,切记文件读写完后要关闭文件.
例子
1 import java.io.FileNotFoundException; 2 import java.io.IOException; 3 import java.io.RandomAccessFile; 4 /** 5 * 随机读写文件 6 * data: 41 42 ff ff ff fe 7 * index: 0 1 2 3 4 5 6 8 * pointer: ^ 9 */ 10 public class RAFDemo { 11 public static void main(String[] args) throws IOException { 12 String file = "raf.dat"; 13 RandomAccessFile raf = new RandomAccessFile(file,"rw"); 14 System.out.println(raf.length());//0 15 System.out.println(raf.getFilePointer());//0 16 raf.write(0xffffff41);//底八位是41,前面的f没用,向文件写入41 17 System.out.println(raf.getFilePointer());//1 18 raf.write(66);//向文件写入42(十六进制) 19 System.out.println(raf.getFilePointer());//2 20 //如何将 -2 写入到文件! 21 int i = -2;//Oxfffffffe 22 //raf.write(i);//写入的是fe(高24位舍弃),不是-2 23 //>>>:无符号移位运算(向右移动数位,低位溢出,高位补0) 24 //>> 有符号移位运算,向右移动数位,低位溢出,高位正数补0,负数补1,保证符号不变 25 //i = 11111111 11111111 11111111 11111110 26 raf.write(i>>>24);//00000000 00000000 00000000 11111111 27 raf.write(i>>>16);//00000000 00000000 11111111 11111111 28 raf.write(i>>>8); //00000000 11111111 11111111 11111110 29 raf.write(i); //11111111 11111111 11111111 11111110 30 31 System.out.println(raf.getFilePointer());//6 32 String str = "中国"; 33 byte[] buf = str.getBytes("GBK");//将"中国"转为GBK编码 34 raf.write(buf); 35 36 //读取文件内容 37 System.out.println("读取文件内容"); 38 raf.seek(0);//使pointer回到0 39 int b = raf.read();//读41,同时poiner+1 40 System.out.println(Integer.toHexString(b));//用16进制打印出来41 41 b = raf.read();//读42,同时poiner+1 42 System.out.println(Integer.toHexString(b));//用16进制打印出来42 43 44 System.out.println("重新读取文件内容"); 45 raf.seek(0);//使pointer回到0 46 while((b= raf.read()) != -1){ 47 ;//读一个,同时poiner+1 48 System.out.println(Integer.toHexString(b));//用16进制打印出来 49 } 50 raf.close();//关闭文件 51 } 52 }
五 序列化与基本类型序列化
1) 什么叫序列化?
将类型int转换为4byte,或者将其他数据类型(如long -> 8byte)的过程,即将数据转换
为 n 个 byte 序列叫做序列化(数据 -> n byte)
2)什么是反序列化?
将n byte 转换为一个数据的过程(n byte -> 数据)
如:[7f, ff, ff, ff] -> 0x7fffffff
3)RandomAccessFile 提供基本数据类型的读写方法,可以将基本类型数据序列化到文件或者将文件内容反序列化为数据
例子:
1 import java.io.IOException; 2 import java.io.RandomAccessFile; 3 /** 4 * 文件的最基本的操作 就是每次读/写 一个byte数据 5 * 6 * 序列华 : 数据(int long double)需要拆分为 byte序列写入到文件 7 * 反序列化: 将byte重新拼接为数据 8 * 9 * image 在内存中是对象,写到文件中,需要进行序列化,有标准:jpg 10 */ 11 public class DataIODemo { 12 13 public static void main(String[] args) throws IOException{ 14 // TODO Auto-generated method stub 15 16 //如何写出基本类型,读取基本类型 17 String file = "data.dat"; 18 RandomAccessFile raf = new RandomAccessFile(file,"rw"); 19 20 raf.writeInt(-2);//将int -2 拆分为4个byrte写到文件中 21 raf.writeLong(-2L); 22 raf.writeDouble(-2.0); 23 raf.writeBoolean(true); 24 25 raf.seek(0); 26 int i = raf.readInt();//pointer 4 27 long l = raf.readLong();//pointer 8 28 double d = raf.readDouble();//pointer 12 29 boolean b = raf.readBoolean();//pointer 16 30 raf.seek(12); 31 double x = raf.readDouble(); 32 System.out.println(i+","+l+","+d+","+b+","+x); 33 34 raf.close(); 35 IOUtils.print(file); 36 37 } 38 39 }
序列化和反序列化的原理如下
1 import java.io.IOException; 2 import java.io.RandomAccessFile; 3 4 public class RAFDataIODemo { 5 public static void main(String[] args)throws IOException{ 6 String file = "raf.dat"; 7 IOUtils.print(file);//41 42 ff ff ff fe d6 d0 b9 fa 8 RandomAccessFile raf = new RandomAccessFile(file,"r"); 9 //如何读取int数据,使用readInt() 10 //原理 11 raf.seek(2); 12 int d1 = raf.read();// 00 00 00 ff 13 int d2 = raf.read();// 00 00 00 ff 14 int d3 = raf.read();// 00 00 00 ff 15 int d4 = raf.read();// 00 00 00 fe 16 //(d1<<24) : ff 00 00 00 17 //(d2<<16) : 00 ff 00 00 18 //(d3<< 8) : 00 00 ff 00 19 //(d4 ) : 00 00 00 fe 20 // i : ff ff ff fe 21 int i = (d1<<24) + (d2<<16) + (d3<<8) + d4; 22 System.out.println(i); 23 //使用readInt() 24 raf.seek(2);//pointer重回2 25 i = raf.readInt(); 26 System.out.println(i); 27 28 29 //读取中文 30 raf.seek(6); 31 byte[] buf = new byte[4];//4个byte的缓冲区 32 //raf.read(byte[])从raf尽可能多的读取byte数据填充到buf中 33 //返回读取的个数,返回值介于0~缓冲区大小之间,如果返回-1,表 34 //示读取到了文件尾部! 35 int n = raf.read(buf); 36 //String(byte[] byte,int start,int size,编码方式) 37 String str = new String(buf, 0, n,"GBK"); 38 System.out.println(str);//中国 39 raf.close(); 40 } 41 }