• 黑马程序员第二阶段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/
  • 相关阅读:
    『转载』优秀ASP.NET程序员的修炼之路
    [转]给年轻工程师的十大忠告
    [转]谈谈技术原则,技术学习方法,代码阅读及其它
    【转贴】你必须知道的20个故事
    谈谈建站心得(转载)[精华]
    HTTP和SOAP完全就是两个不同的协议
    数据集的理解IDataset
    学习在 ArcEngine 中使用 Geoprocessing
    程序执行过程
    How to Run a Geoprocessing Tool
  • 原文地址:https://www.cnblogs.com/runwind/p/4454748.html
Copyright © 2020-2023  润新知