深入解析I/O编程之文件访问类
转载请表明出处:http://blog.csdn.net/u012637501(嵌入式_小J的天空)
开始学习字节流类之前,我们来先看下与文件有关的类-File类。File类是IO包中唯一代表磁盘文件本身的对象,File类定义了一些与平台无关的方法来操作文件,通过调用File类提供的各种方法,我们能够创建、删除文件、重命名文件以及判断文件的读写权限及其是否存在,设置和查询文件的最近修改时间等。在Java中,目录也被当作File使用,只是多了一些目录特有的功能---可以用list方法列出目标中的文件名。
一、File类
(1)功能
File类是IO包中唯一代表磁盘文件本身的对象,File类定义了一些与平台无关的方法来操作文件。但File类不能访问文件的内容,即不能够从文件中读取数据或向文件里写数据,它只能对文件本身的属性进行操作。
(2)构造方法
>File(String pathname) :创建一个File对象,其内容为字符串路径所对应的文件;
>File(URI uri) :创建一个File对象,其内容为URI所包含的文件;
举例:File f=new File("C:\\test.txt");创建一个File类实例f,该实例的内容直接对应C盘目录下test.txt文件,File类的所有方法则都是针对于该文件。
(3)常用方法
boolean createNewFile():当文件不存在时,新建一个空的文件(文件名为pathname(包含路径));
boolean delete():删除该抽象路径名所表示的文件或者目录;
boolean exists():判定该抽象路径名所表示的文件或者目录是否存在;
String getAbsolutePath():以字符串的形式返回该文件的绝对路径;
String getCanonicalPath():以字符串的形式返回该文件的相对路径;
String getName():获取该文件/目录的文件(目录)名;
long lastModified():返回该文件最后依次修改时间;
long length() :返回该文件的长度(大小);
String[] list():以字符串数组的形式返回该目录下的所有文件名(目录);
boolean setReadable(boolean readable):设置文件的可读权限;
boolean setWritable(boolean writable):设置文件的可写权限;
boolean isDirectory() :判定是否为目录;
boolean isFile():判断是否为文件;
boolean canRead() :判定该文件或目录是否可读;
boolean canWrite() :判定该文件或目录是否可写;
注意:上述方法操作的是由File对象的路径所表示的磁盘文件或目录。
二、RandomAccessFile类
1.功能
RandomAccessFile类是Java语言中最为丰富的文件访问类,其提供了大量的访问文件的方法。RandomAccessFile类支持"随机访问"方式,即使用该类实现跳转到文件的任意位置处读写数据。另外,RandomAccessFile对象类有个位置指示器,指向当前读写处的位置,当读写n个字节后,文件指示器将指向这n个字节后的下一个字节处。需要注意的是,该类仅限于操作文件,不能访问其他的IO设备(如网络、内存映像)。
2.构造方法
RandomAccessFile(File file, String mode)
RandomAccessFile(String name, String mode)
举例:
new RandomAccessFile(f,"rw"); //以读写方式实例化一个RandomAccessFile对象
new RandomAccessFile(f,"r"); //以只读方式实例化一个RandomAccessFile对象
当以读写的方式打开一个文件(引用变量f对应的文件)时,如果该文件不存在,程序将自动创建。
3.常用方法
void close():关闭该随机存取文件流并释放与该文件流有关的系统资源;
long getFilePointer():返回位置指示器指向文件当前读写处的位置;
long length():返回该文件的长度;
int read():从该文件读取一个字节的数据;
int read(byte[] b) :从该文件读取最多b.length()个字节数据到字节数组(byte[]);
int read(byte[] b, int off, int len):从该文件的off位置读取len个字节数据到字节数组(byte[]);
byte readByte():从该文件读取一字节数据;
char readXxx():从该文件读取一个字符/double型/float型数据;
String readLine():读取文件的下一行数据;
void seek(long pos):设置位置指示器偏移位置(相对于文件开头);
int skipBytes(int n):跳过n个字节;
void write(byte[] b) :将指定字节数组中的b.length个字节数据写入到该文件中;
void write(byte[] b, int off, int len) :将从指定字节数组的off位置后面的len个字节数据写入到该文件中
void write(int b) :写一个字节数据到该文件中;
4.源码实战
1.使用RandomAccessFile创建并读取一个文本文件
(1)Employee.java
功能:设计一个类用于封装员工信息,一个员工的信息就是文件中的一条记录,为了准确定位每条记录在文件中的具体位置,我们使每条记录在文件中的大小相同,即每个员工的姓名字段在文件中的长度是一样的。
package test;
<span style="font-size:18px;">/*自定义类:用于封装员工的信息*/ public class Employee { String name; int age; final static int len=8; //名字的长度 public Employee(String name,int age) //构造方法 { if(name.length()>=len) { name=name.substring(0, len); //如何名字长度大于8个字符则只取前8个 } else { while(name.length()<len) name=name+"\u0000"; } this.age=age; this.name=name; } }</span>
源码分析:为了使name中满足8个字符条件,我们可以这样处理:少于8个字符则补空格(即+"\u0000"),多于8个则去掉后面多余的部分。另外,由于年龄是整型数据不管这个数有多大,只要它不超过整型数据的范围,在内存中都是占4个字节大小。
String.substring(int beginIndex,int endIndex)方法用于取出一个字符串中的部分子字符串,需要注意的是字符串中的第一个字符对应的是原字符串中的脚标为beginIndex处的字符,但最后的字符对应的是原字符串中的脚本为endIndex-1处的字符,而非endIndex处的字符。
(2)RandomAccessFileTest.java
功能:实现使用RandomAccessFile类创建并操作文本文件,向该文件写入数据然后再从文件中读取指定位置的数据打印。
<span style="font-size:18px;">package test; import java.io.RandomAccessFile; public class RandomAccessFileTest { public static void main(String[] args) throws Exception { Employee e1 = new Employee("zhangsan", 30); //实例并初始化3个Employee对象 Employee e2 = new Employee("lisi", 26); Employee e3 = new Employee("wangwu", 25); /*1.打开文件写入数据后关闭*/ RandomAccessFile ra = new RandomAccessFile("C:\\employee.txt", "rw"); //实例化并打开一个RandomAccessFile代表的文件 ra.write(e1.name.getBytes()); //将第一个员工信息写入到RandomAccessFile代表的文件中 ra.writeInt(e1.age); ra.write(e2.name.getBytes()); ra.writeInt(e2.age); ra.write(e3.name.getBytes()); ra.writeInt(e3.age); ra.close(); /*2.再次打开文件读取文件后关闭*/ RandomAccessFile raf = new RandomAccessFile("C:\\employee.txt", "r"); int len=8; raf.skipBytes(len+4); //跳过第一个员工信息,其中姓名8个字节、年龄4字节 //获取第二个员工信息 System.out.println("第二个员工信息:"); String str=""; for(int i=0;i<len;i++) str = str +(char)raf.readByte(); //读取一个字节的信息到str中,此时位置指示器指向第9个字节位置(假如从0开始) System.out.println("name:"+str); System.out.println("age:"+raf.readInt()); //获取第一个员工信息(读取完数据后位置指示器位置指向第二个员工信息的开始位置) System.out.println("第一个员工信息:"); raf.seek(0); str=""; for(int i=0;i<len;i++) str = str +(char)raf.readByte(); System.out.println("name:"+str); System.out.println("age:"+raf.readInt()); //获取第三个员工信息 System.out.println("第三个员工信息:"); raf.skipBytes(len+4); str=""; for(int i=0;i<len;i++) str = str +(char)raf.readByte(); System.out.println("name:"+str); System.out.println("age:"+raf.readInt()); raf.close(); //关闭文件,释放引用变量资源及其所占用的系统资源 } }</span>
效果演示: