《Java编程思想第四版》笔记---18章(2) I/O 非流式部分

非流式部分

File类

      在Java语言的java.io包中,由File类提供了描述文件和目录的操作与管理方法。但File类不是InputStream、OutputStream或Reader、Writer的子类,因为它不负责数据的输入输出,而专门用来管理磁盘文件与目录。

作用:File类主要用于命名文件、查询文件属性和处理文件目录。

public  class   File   extends Object

implements Serializable,Comparable{}


File类共提供了三个不同的构造函数,以不同的参数形式灵活地接收文件和目录名信息。

构造函数:

1)File (String   pathname)

例:File  f1=new File("FileTest1.txt"); //创建文件对象f1,f1所指的文件是在当前目录下创建的FileTest1.txt

2)File (String  parent  ,  String child)

例:File f2=new  File(“D:\\dir1","FileTest2.txt") ;//  注意:D:\\dir1目录事先必须存在,否则异常

3)File (File    parent  , String child)

例:

File  f4=new File("\\dir3");

File  f5=new File(f4,"FileTest5.txt");  //在如果 \\dir3目录不存在使用f4.mkdir()先创建


一个对应于某磁盘文件或目录的File对象一经创建, 就可以通过调用它的方法来获得文件或目录的属性。

  
  
  1. public static void main(String[] args){
  2. String fileName = "D:" + File.separator + "Files";
  3. File file = new File(fileName);
  4. if (file.exists() && file.isDirectory()) // 判断路径指向的文件/文件夹是否存在、是否目录
  5. {
  6. System.out.println("file是一个文件夹\n");
  7. File[] files = file.listFiles(); // 获取目录下的所有文件/文件夹(仅该层路径下)
  8. System.out.print("路径下有文件:");
  9. for (File f : files){
  10. System.out.print(f + "\t");
  11. }
  12. System.out.println();
  13. System.out.println("files[0]的文件名:" + files[0].getName()); // 获取文件名、文件夹名
  14. System.out.println("files[0]的文件路径:" + files[0].getPath()); // 获取文件、文件夹路径
  15. System.out.println("files[0]的绝对路径:" + files[0].getAbsolutePath()); // 获取文件、文件夹绝对路径
  16. System.out.println("files[0]的父文件夹名:" + files[0].getParent()); // 获取文件父目录路径
  17. System.out.println(files[0].exists() ? "files[0]的存在" : "files[0]的不存在"); // 判断文件、文件夹是否存在
  18. System.out.println(files[0].canWrite() ? "files[0]的可写" : "files[0]的不可写"); // 判断文件是否可写
  19. System.out.println(files[0].canRead() ? "files[0]的可读" : "files[0]的不可读"); // 判断文件是否可读
  20. System.out.println(files[0].canExecute() ? "file[0]可执行" : "file[0]不可执行"); // 判断文件是否可执行
  21. System.out.println(files[0].isDirectory() ? "files[0]的是目录" : "files[0]的不是目录"); // 判断文件、文件夹是不是目录
  22. System.out.println(files[0].isFile() ? "files[0]的是文件" : "files[0]的不是文件"); // 判断拿文件、文件夹是不是标准文件
  23. System.out.println(files[0].isAbsolute() ? "files[0]的路径名是绝对路径" : "files[0]的路径名不是绝对路径"); // 判断路径名是不是绝对路径
  24. System.out.println("files[0]的最后修改时间:" + files[0].lastModified()); // 获取文件、文件夹上一次修改时间
  25. System.out.println("files[0]的大小:" + files[0].length() + " Bytes"); // 获取文件的字节数,如果是一个文件夹则这个值为0
  26. System.out.println("files[0]的路径转换为URI:" + files[0].toURI()); // 获取文件路径URI后的路径名
  27. if (files[0].exists())
  28. files[0].delete(); // 删除指定的文件、文件夹
  29. if (files[1].exists())
  30. files[1].deleteOnExit(); // 当虚拟机终止时删除指定的文件、文件夹
  31. }
  32. }

运行结果为:

    
    
  1. file是一个文件夹
  2. 路径下有文件:D:\Files\buffered.txt D:\Files\example.txt D:\Files\Inner D:\Files\serializable.txt D:\Files\stream.txt D:\Files\test.txt
  3. files[0]的文件名:buffered.txt
  4. files[0]的文件路径:D:\Files\buffered.txt
  5. files[0]的绝对路径:D:\Files\buffered.txt
  6. files[0]的父文件夹名:D:\Files
  7. files[0]的存在
  8. files[0]的可写
  9. files[0]的可读
  10. file[0]可执行
  11. files[0]的不是目录
  12. files[0]的是文件
  13. files[0]的路径名是绝对路径
  14. files[0]的最后修改时间:1440313521120
  15. files[0]的大小:21 Bytes
  16. files[0]的路径转换为URIfile:/D:/Files/buffered.txt

示例代码应该是比较全面地演示了File的用法,其中有两点值得注意:

1、程序代码的第三行,写"D:/Files"和"D:\\Files"都是可以的,但像示例代码这么写应该是一种更好的做法,因为这么写使得代码  的跨平台型、健壮性更好。"File.separator"会根据不同的操作系统取不同操作系统下的分隔符。其实File还有另一个分隔符 pathSeparator,表示":",不过因为Java主要用在Windows和Linux下,Linux下没有盘符的问题,所以一般直接打":"就 好了

2、程序代码的第34、第36行,注意一下,删除的如果是一个文件夹的话,文件夹下还有文件/文件夹,是无法删除成功的

最后,再次重申,File是IO流的基础。
来源: http://www.cnblogs.com/szlbm/p/5513117.html 

RandomAccessFile 类

      RandomAccessFile类可以说是Java语言中功能最为丰富的文件访 问类,它提供了众多的文件访问方法。RandomAccessFile类支持"随机访问"方式,可以跳转到文件的任意位置处读写数据。要访问一个文件的时 候,不想把文件从头读到尾,而是希望像访问一个数据库一样地访问一个文本文件,使用RandomAccessFile类是最佳选择。

RandomAccessFile对象类中有个位置指示器,指向当前读写处的位置,当读写n个字节后,文件指示器将指向这n个字节后的下一个字节处。刚打开文件时,文件指示器指向文件的开头处,可以移动文件指示器到新的位置,随后的读写将从新的位置开始。

RandomAccessFile类在文件随机(相对于顺序)读取时有很大的优势,但该类仅限于操作文件,不能访问其他得IO设备,如网络、内存映像等。

 

RandomAccessFile类为用户提供了两种构造方法:

1、RandomAccessFile(File file, String mode)

2、RandomAccessFile(String name, String mode)

其实第二种构造方法也是new一个File出来再调用第一种构造方法,建议使用第 一种构造方法,因为第一篇文章就说了File是IO的基础,有一个File不仅仅可以通过RandomAccessFile对文件进行操作,也可以通过 File对象对文件进行操作。至于mode,Java给开发者提供了四种mode:

模    式 作    用
r 表示以只读方式打开,调用结果对象的任何write方法都将导致抛出IOException
rw 打开以便读取和写入,如果该文件尚不存在,则尝试创建该文件
rws 打开以便读取和写入,相对于"rw",还要求对文件内容或元数据的每个更新都同步写入到底层存储设备
rwd 打开以便读取和写入,相对于"rw",还要求对文件内容的每个更新都同步写入到底层存储设备

注意第二点"rw"模式,对rw模式的解释意味着Java并不强求指定的路径下一定存在某个文件,假如文件不存在,会自动创建

 

RandomAccessFile中有如下一些常用方法:

方    法 作    用
void close() 重要,关闭此随机访问文件流并释放与该流关联的所有系统资源
FileChannel getChannel() 返回与此文件关联的唯一FileChannel对象,NIO用到
long getFilePointer() 返回此文件中的当前偏移量
long length() 返回此文件的长度
int read() 从此文件中读取一个数据字节
int read(byte[] b) 将最多b.length个数据字节从此文件读入byte数组,返回读入的总字节数,如果由于已经达到文件末尾而不再有数据,则返回-1。在至少一个输入字节可用前,此方法一直阻塞
int read(byte[] b, int off, int len) 将最多len个数据字节从此文件的指定初始偏移量off读入byte数组
boolean readBoolean() 从此文件读取一个boolean,其余readByte()、readChar()、readDouble()等类似
String readLine() 从此文件读取文本的下一行
void seek(long pos) 重要,设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作
int skipBytes(int n) 重要,尝试跳过输入的n个字节以丢弃跳过的字节,返回跳过的字节数
void write(byte[] b) 将b.length个字节从指定byte数组写入到此文件中
void write(byte[] b, int off, int len) 将len个字节从指定byte数组写入到此文件,并从偏移量off处开始
void write(int b) 向此文件写入指定的字节
void writeBoolean(boolean v) 按单字节值将boolean写入该文件,其余writeByte(int v)、writeBytes(String s)、writeChar(int v)等都类似

 

RandomAccessFile使用实例

先定义一个实体类:

    
    
  1. public class Employee{
  2. private String name;
  3. private int age;
  4. private final static int LEN = 8;
  5. public Employee(){}
  6. public Employee(String name, int age){
  7. if (name.length() > LEN){
  8. name = name.substring(0, 8);
  9. }else{
  10. while (name.length() < LEN){
  11. name = name + "\u0000";
  12. }
  13. }
  14. this.name = name;
  15. this.age = age;
  16. }
  17. public String getName(){
  18. return name;
  19. }
  20. public void setName(String name){
  21. this.name = name;
  22. }
  23. public int getAge(){
  24. return age;
  25. }
  26. public void setAge(int age){
  27. this.age = age;
  28. }
  29. }

第一部分,写文件,该文件在路径下并没有,所以Java会自动帮我们创建:

    
    
  1. Employee e1 = new Employee("zhangsan", 23);
  2. Employee e2 = new Employee("lisi", 24);
  3. Employee e3 = new Employee("wangwu", 25);
  4. RandomAccessFile raf0 = new RandomAccessFile("D:/employee.txt", "rw");
  5. raf0.writeBytes(e1.getName());
  6. raf0.writeInt(e1.getAge());
  7. raf0.writeBytes(e2.getName());
  8. raf0.writeInt(e2.getAge());
  9. raf0.writeBytes(e3.getName());
  10. raf0.writeInt(e3.getAge());
  11. raf0.close();

文件创建好了,D盘下也有该文件了,所以读取一下,这里使用了一些小技巧来演示seek方法和skipBytes方法:

    
    
  1. RandomAccessFile raf1 = new RandomAccessFile("D:/employee.txt", "r");
  2. int len = 8;
  3. raf1.skipBytes(12); // 跳过第一个员工的信息,其姓名8字节,年龄4字节
  4. System.out.println("第二个员工的信息:");
  5. String str = "";
  6. for (int i = 0; i < len; i++){
  7. str = str + (char)raf1.readByte();
  8. }
  9. System.out.println("name:" + str);
  10. System.out.println("age:" + raf1.readInt());
  11. System.out.println("第一个员工的信息:");
  12. raf1.seek(0);
  13. str = "";
  14. for (int i = 0; i < len; i++){
  15. str = str + (char)raf1.readByte();
  16. }
  17. System.out.println("name:" + str);
  18. System.out.println("age:" + raf1.readInt());
  19. System.out.println("第三个员工的信息:");
  20. raf1.skipBytes(12); // 跳过第二个员工的信息
  21. str = "";
  22. for (int i = 0; i < len; i++){
  23. str = str + (char)raf1.readByte();
  24. }
  25. System.out.println("name:" + str.trim());
  26. System.out.println("age:" + raf1.readInt());
  27. raf1.close();

看一下运行结果:

    
    
  1. 第二个员工的信息:
  2. namelisi
  3. age24
  4. 第一个员工信息:
  5. namezhangsan
  6. age23
  7. 第三个员工信息:
  8. namewangwu
  9. age25

可能有人奇怪,"zhangsan"加上一个int跳过12个字节可以理解,但是"lisi"、"wangwu"为什么加上int要跳过12个字节 呢?明明"lisi"只有4个字节,"wangwu"只有6个字节啊。这个就涉及到一个"字节对齐"的问题了,有兴趣的可以了解一下。另外,再说一 下,RandomAccessFile使用完一定要及时close()。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

繁星点点-

请我喝杯咖啡呗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值