run_wind

导航

黑马程序员--第二阶段Java高级IO--第18天

 

IO/输入输出

大多数应用程序都需要与外部设备进行数据交换,最常见的外部设备包含磁盘文件系统和网络,IO就是指应用程序对这些设备的数据输入与输出的操作,在程序中,键盘被当作一种特殊的输入文件,显示器被当作输出文件使用。Java语言定义了许多类专门负责各种方式的输入输出,这些类都被放在java.io包中。

File

File类是IO包中惟一代表磁盘文件本身信息的类,注意不是代表文件中的内容,而是代表文件的信息,如文件名、修改时间、可读等信息内容。File类定义了一些与平台无关的方法来操纵文件,通过调用File类提花的各种方法,我们能够创建、删除文件,重命名文件,判断文件的读写权限及文件是否存在,设置和查询文件的最近修改时间。

Java中,目录也被当作File使用,只是多了一些目录特有的功能——可以用list方法列出目录中所有子目录和文件名。在Unix下的路径分隔符为(/),Dos下的路径分隔符为(\),Java可以正确处理UnixDos的路径分隔符,即使我们在Windows环境下使用(/)作为路径分隔符,Java仍然能够正确处理。

下面的例子演示了File类用法,判断某个文件是否存在,存在则删除,不存在则创建:

import java.io.File;

import java.text.SimpleDateFormat;

import java.util.Date;

class TestFile {

 

       public static void main(String[] args) {

              File f = new File("D:\\text1\\text2\\text.txt");//这里的目录结构必须已经存在

              //此处可尝试:texttext1\\text2text.txt

              //如果用new File("aa","1.txt"),则aa1.txt文件的parent目录,但是aa目录必须已经存在

              if(f.exists()) {   //判断文件或目录是否存在

                     f.delete();  //删除文件或目录

              } else {

                     try{

                            f.createNewFile();  //创建文件

                     //     f.mkdirs();   //创建目录

                     } catch(Exception e) {e.printStackTrace();}

              }

              System.out.println(f.exists()? "文件或目录已存在" : "文件或目录不存在");

              System.out.println("指定的路径名为:" + f);

              System.out.println("指定的文件名或目录名为:" + f.getName());

              System.out.println("指定的文件路径为:" + f.getPath());

              System.out.println("指定的文件绝对路径为:" + f.getAbsolutePath());

              System.out.println("指定的父目录为:" + f.getParent());

              System.out.println(f.isAbsolute()? "是绝对路径" : "不是绝对路径");

              System.out.println(f.isDirectory()? "这是一个目录" : "这不是一个目录");

              System.out.println(f.isFile()? "这是一个文件" : "这不是一个文件");

              System.out.println(f.isHidden()? "这是一个隐藏文件" : "这不是一个隐藏文件");

              System.out.println(f.canExecute()? "这是可执行文件" : "这不是一个可执行文件");

              System.out.println(f.canRead()? "这是可读文件" : "这不是一个可读文件");

              System.out.println(f.canWrite()? "这是可写文件" : "这不是一个可写文件");  

             

              if(f.exists()){

                     SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");

                     Date d = new Date(f.lastModified());//lastModified为返回文件的最后修改时间,值为long

                     String lastModified =sdf.format(d);

                     System.out.println("文件最后一次修改时间为:" + lastModified);

              }           

       }    

}

注意:delete方法删除由File对象的路径所表示的磁盘文件或目录。如果删除的对象是目录,该目录中的内容必须为空。

上面代码只是对文件本身的属性进行操作,而不能访问文件的内容,即不能够从文件中读取数据或往文件里写数据。

RandomAccessFile

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

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

         RandomAccessFile类提供了众多的文件访问方法

         RandomAccessFile类支持“随机访问”方式

         RandomAccessFile类在随机读写等长记录格式的文件时有很大的优势

         RandomAccessFile类仅限于操作文件,不能访问其他IO设备,如网络、内存映象等。

         两种构造方法:
    new RandomAccessFile(f,”rw”);//读写方式
    new RandomAccessFile(f,”r”);//只读方式

      注:当我们的程序以读写的方式打开一个文件时,如果这个文件不存在,程序会为你创建

编程实例:往文件中写入三名员工的信息,每个员工含有姓名和年龄两个字段,然后按照第二名、第一名、第三名的先后顺序读取出员工信息。

我们需要设计一个类来封装员工信息。一个员工信息就是文件中的一条记录,我们必须保证每条记录在文件中的大小相同,也就是每个员工的姓名字段在文件中的长度是一样的,我们才能够确定每条记录在文件中的具体位置。假设name中有8个字符,少于8个则补空格(”\u0000”),多于8个则去掉后面多余的部分。由于年龄是整数型,不管这个数有多大,只要它不超过整型数的范围,在内存中都是占4个字节大小。

字符串对象有一个length方法用来返回字符串对象的字符个数。如:

“abc”.length( );//返回3

戴振良”.length( );//返回3

注意1:英文字符虽然占两个字节,但是他们的unicode码只占一个字节,而中文字符却占两个字符。byte只占一个字节,所以把一个英文字符转换为byte型时数据不会丢失,如:(byte)’a’,  而把一个中文字符转换为byte就会丢失数据,如:int b=‘戴’; //b=25140       int b=(byte)‘戴’;  //b=52

注意2     String a=null; a=a+"你好";  此时a="null你好";所以可以把a初始化为空字符串” ”

 

Employee.java

public class Employee

{

public String name = null;

public int age = 0;

public static final int LEN = 8;      

 

public Employee(String name, int age)

{

           if(name.length()>LEN)//字符串对象的length方法用于返回字符串对象的长度(字符个数)

           {

                    name=name.substring(0,LEN);

           }

           else

           {

                    while(name.length()<LEN)

                    {

                             name+="\u0000";

                    }

           }

           this.name=name;

           this.age=age;

}      

}

 

RandomFileTest.java

import java.io.*;

public class RandomFileTest

{

 

public static void main(String[] args) throws Exception  //在这里加了throws Exception后就不需要捕获异常了

{

           Employee e1=new Employee("张三",23);

           Employee e2=new Employee("lisi",256);

           Employee e3=new Employee("wangwu",25);

          

           RandomAccessFile ra=new RandomAccessFile("employee.txt","rw");

           //getBytes()方法用于把该字符串对象的所有字符转换为Byte数组,因为中文字符太多,要用两个字节来表示,而一个字节就能表示完所有的英文字符,当读取英文字符是,则读一个字符会转换成一个字节,而读一个中文字符的时候会转换成两个字节,           

//write(int b)向此文件写入指定的字节。

           //write(byte[] b)b.length 个字节从指定 byte 数组写入到此文件,并从当前文件指针开始。

           //writeInt方法:按四个字节将 int 写入该文件,先写高字节。

           //ra.write(e1.name.getBytes());      

           //writeChar(int v) 按双字节值将 char 写入该文件,先写高字节

           //writeChars(String s) 按字符序列将一个字符串写入该文件。

           ra.writeChars(e1.name);        //写进来的字符串以Unicode码表示,每个字符占两个字节

           ra.writeInt(e1.age);

           //ra.write(e2.name.getBytes());

           ra.writeChars(e2.name);       

           ra.writeInt(e2.age);

           //ra.write(e3.name.getBytes());

           ra.writeChars(e3.name);       

           ra.writeInt(e3.age);

           ra.close();//关闭文件

          

           //int len=0;

           //byte[] buf=new byte[Employee.LEN];

           String strName="";

           RandomAccessFile raf=new RandomAccessFile("employee.txt","r");

           //skipBytes(int n) //尝试跳过输入的 n 个字节以丢弃跳过的字节。

           raf.skipBytes(Employee.LEN*2+4);//跳过12个字节,从第13个字节开始读写操作

           //len=raf.read(buf);//将最多 buf.length 个数据字节从此文件读入 buf 数组。

           //buf参数是将数据读入的缓冲区,该方法返回的是读入缓冲区的总字节数(int型),如果由于已到达此文件的末尾而不再有数据,则返回 -1

           //strName=new String(buf,0,len);

           for(int i=0;i<Employee.LEN;i++)

           {       //readChar()从此文件读取一个字符。           

                    strName+=raf.readChar();

           }

           System.out.println(strName.trim()+":"+raf.readInt());

           strName="";

           //trim方法:删除字符串对象中字符串前面、后面的那些不可显示的字符

           //read()无参数方法:从此文件中读取一个数据字节。以整数形式返回此字节,范围在 0 255 (0x00-0x0ff)。如果尚无输入可用,将阻塞此方法。

          

           //seek(long pos) //设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。         

           raf.seek(0);//定位到文件中的第0个字节处

           //len=raf.read(buf);

           //strName=new String(buf,0,len);

           for(int i=0;i<Employee.LEN;i++)

           {

                    strName+=raf.readChar();

           }

           System.out.println(strName.trim()+":"+raf.readInt());//读取完这条语句,指示器已经指示到了第二条记录的开始处了

          

           strName="";

           raf.skipBytes(Employee.LEN*2+4);

           //len=raf.read(buf);

           //strName=new String(buf,0,len);

           for(int i=0;i<Employee.LEN;i++)

           {

                    strName+=raf.readChar();

           }

           System.out.println(strName.trim()+":"+raf.readInt());

          

           raf.close();

}      

}

                    详情请查看:http://edu.csdn.net/heima/

posted on 2012-04-25 11:11  run_wind  阅读(126)  评论(0编辑  收藏  举报