java程序设计--孙鑫java无难事Lesson9《IO操作》

来源:互联网 发布:全国十大淘宝村集群 编辑:程序博客网 时间:2024/06/01 10:22
java程序设计--孙鑫java无难事Lesson9《IO操作》
本节要点:
1.Java I/O流及操作
2.Java I/O库的设计原则,
3.字符集的编码,
4.RandomAccessFile类,
5.对象的序列化
详细内容:
1.File类操作
(1)一个File类的对象,表示了磁盘上的文件或目录。
(2)File类提供了与平台无关的方法来对磁盘上的文件或目录进行操作。
File类测试代码如下:
[java] view plaincopyprint?
  1. import java.io.*;  
  2. class FileTest  
  3. {  
  4.     public static void main(String[] args)  throws Exception  
  5.     {     
  6.         /* 
  7.         //创建文件 
  8.         File  file=new File("1.txt");//相对路径 
  9.         file.createNewFile(); 
  10.         */  
  11.   
  12.         /* 
  13.         //创建目录 
  14.         File  file2=new File("1"); 
  15.         file2.mkdir(); 
  16.         */  
  17.   
  18.         /* 
  19.         //绝对路径创建文件 
  20.         File file3=new File("F:\\java\\JavaLesson\\Lesson9\\2.txt"); 
  21.         file3.createNewFile(); 
  22.         */  
  23.   
  24.         /* 
  25.         //平台无关性创建文件 
  26.         File fileDir=new File( File.separator);//  一个分隔符代表根目录 
  27.         String  strFile="java"+File.separator+"JavaLesson"+File.separator+"Lesson9"+File.separator+"3.txt"; 
  28.         File file4=new File(fileDir,strFile); 
  29.        file4.createNewFile();//创建 
  30.        // file4.delete();//删除 
  31.        Thread.sleep(3000);//暂停加强演示效果 
  32.          file4.deleteOnExit(); 
  33.          */  
  34.   
  35.          /* 
  36.          //创建临时文件 
  37.          for(int i=0;i<5;i++) 
  38.         { 
  39.              File f=File.createTempFile("Temp",".tmp"); 
  40.              Thread.sleep(3000);//暂停加强演示效果 
  41.              f.deleteOnExit(); 
  42.          } 
  43.         */  
  44.   
  45.          //列举文件   
  46.         File fileDir=new File( File.separator);//  一个分隔符代表根目录  
  47.         String  strFile="java"+File.separator+"JavaLesson"+File.separator+"Lesson9";  
  48.         File file5=new File(fileDir,strFile);  
  49.         //运用匿名内部类 筛选文件   
  50.         String[] strFileName=file5.list(new FilenameFilter()  
  51.         {  
  52.              public boolean accept(File dir, String name)  
  53.             {  
  54.                 return name.indexOf(".java")!=-1;  
  55.             }  
  56.         } );  
  57.         for(int i=0;i<strFileName.length;i++)  
  58.         {  
  59.             System.out.println(strFileName[i]);  
  60.         }  
  61.     }  
  62. }  
2.流式I/O
流(Stream)是字节的源或目的。
两种基本的流是:输入流(Input Stream)和输出流(Output Stream)。可从中读出一系列字节的对象称为输入流。而能向其中写入一系列字节的对象称为输出流。
(1)流的分类
节点流:从特定的地方读写的流类,例如:磁盘或一块内存区域。
过滤流:使用节点流作为输入或输出。过滤流是使用一个已经存在的输入流或输出流连接创建的。
(2)InputStream和OutputStream类  操作字节流
InputStream和OutputStream类层次如下图所示:


(3)基本的流类

FileInputStream和FileOutputStream节点流,

用于从文件中读取或往文件中写入字节流。如果在构造FileOutputStream时,文件已经存在,则覆盖这个文件。

BufferedInputStream和BufferedOutputStream过滤流,

需要使用已经存在的节点流来构造,提供带缓冲的读写,提高了读写的效率。

DataInputStream和DataOutputStream过滤流,

需要使用已经存在的节点流来构造,提供了读写Java中的基本数据类型的功能。PipedInputStream和PipedOutputStream管道流,

用于线程间的通信。一个线程的PipedInputStream对象从另一个线程的PipedOutputStream对象读取输入。要使管道流有用,必须同时构造管道输入流和管道输出流。

前三种流类,测试代码如下:
[java] view plaincopyprint?
  1. import java.io.* ;  
  2. class StreamTest  
  3. {  
  4.     public static void main(String[] args) throws Exception  
  5.     {     
  6.         /* 
  7.         int data; 
  8.         while( (data=System.in.read()) !=-1) 
  9.         { 
  10.            System.out.write(data); 
  11.         } 
  12.         */  
  13.         /* 
  14.         //BufferedOutputStream写入 
  15.         FileOutputStream fileout=new  FileOutputStream(new File("StreamTest1.txt")); 
  16.         BufferedOutputStream bo=new BufferedOutputStream(fileout); 
  17.         fileout.write("Java FileOutputStream Test".getBytes()); 
  18.         bo.write("Java BufferedOutputStream Test".getBytes()); 
  19.         bo.flush();//需要刷新缓冲区  不关闭输出流 
  20.         bo.close();//关闭同样可以刷新  但是将关闭输出流 
  21.         //BufferedInputStream读取 
  22.         FileInputStream  filein=new FileInputStream(new File("StreamTest1.txt")); 
  23.         BufferedInputStream bi=new BufferedInputStream(filein); 
  24.         byte[] b=new byte[100]; 
  25.         int len=bi.read(b); 
  26.         String str=new String(b,0,len); 
  27.         System.out.println(str); 
  28.         */  
  29.   
  30.         /* 
  31.         //DataOutputStream和DataInputStream测试 
  32.         //DataOutputStream写入 
  33.         FileOutputStream fileout=new  FileOutputStream(new File("StreamTest2.txt")); 
  34.         DataOutputStream dos=new DataOutputStream(fileout); 
  35.         byte bt=3; 
  36.         int i=4; 
  37.         boolean bool=false; 
  38.         char ch='a'; 
  39.         float f=1.3f; 
  40.         dos.writeByte(bt); 
  41.         dos.writeInt(i); 
  42.         dos.writeBoolean(bool); 
  43.         dos.writeChar(ch); 
  44.         dos.writeFloat(f); 
  45.         dos.close(); 
  46.         //DataInputStream读取 
  47.         FileInputStream  filein=new FileInputStream(new File("StreamTest2.txt")); 
  48.         DataInputStream dis=new DataInputStream(filein); 
  49.         System.out.println(dis.readByte()); 
  50.         System.out.println(dis.readInt()); 
  51.         System.out.println(dis.readBoolean()); 
  52.         System.out.println(dis.readChar()); 
  53.         System.out.println(dis.readFloat()); 
  54.         */  
  55.   
  56.   
  57.         /* 
  58.         //OutputStreamWriter写入 
  59.         FileOutputStream fileout=new  FileOutputStream(new File("StreamTest3.txt")); 
  60.         OutputStreamWriter osw=new  OutputStreamWriter(fileout); 
  61.         BufferedWriter    bw= new BufferedWriter(osw); 
  62.         bw.write("java BufferedWriter Test"); 
  63.         bw.close(); 
  64.         //InputStreamReader读取数据 
  65.         FileInputStream  filein=new FileInputStream(new File("StreamTest3.txt")); 
  66.         InputStreamReader fsr=new InputStreamReader(filein); 
  67.         BufferedReader   br=new BufferedReader(fsr); 
  68.         String strline=br.readLine(); 
  69.         System.out.println(strline); 
  70.         */  
  71.         //从标准输入设备读写   
  72.         InputStreamReader fsr=new InputStreamReader(System.in);  
  73.         BufferedReader   br=new BufferedReader(fsr);  
  74.         String strline=new String();  
  75.         while((strline=br.readLine())!=null)  
  76.         {  
  77.                System.out.println(strline);  
  78.         }  
  79.         br.close();  
  80.     }  
  81. }  
[java] view plaincopyprint?
  1. 管道流测试代码如下:  
  2. import java.io.* ;  
  3. class PipedStreamTest  
  4. {  
  5.     public static void main(String[] args)  
  6.     {       
  7.           PipedOutputStream pos=new PipedOutputStream();  
  8.           PipedInputStream pis=new PipedInputStream();  
  9.           try  
  10.           {  
  11.             pis.connect(pos);//连接管道  
  12.             new Producer(pos).start();  
  13.             new Consumer(pis).start();  
  14.           }  
  15.            catch (Exception e)  
  16.            {  
  17.                e.printStackTrace();  
  18.            }  
  19.     }  
  20. }  
  21. //生产者线程   
  22. class Producer  extends Thread  
  23. {  
  24.     private PipedOutputStream pos;  
  25.     Producer (PipedOutputStream pos)  
  26.     {  
  27.         this.pos=pos;  
  28.       
  29.     }  
  30.     public void run()  
  31.     {  
  32.            try  
  33.            {  
  34.               pos.write("Hello,Welcome you!".getBytes());  
  35.               pos.close();  
  36.            }  
  37.            catch (Exception e)  
  38.            {  
  39.                e.printStackTrace();  
  40.            }  
  41.     }  
  42. }  
  43. //消费者线程   
  44. class Consumer  extends Thread  
  45. {  
  46.     private PipedInputStream pis;  
  47.     Consumer(PipedInputStream pis)  
  48.     {  
  49.        this.pis=pis;  
  50.     }  
  51.     public void run()  
  52.     {  
  53.         try  
  54.         {     
  55.             byte[] bt=new byte[100];  
  56.             int len=pis.read(bt,0,bt.length);  
  57.             System.out.write(bt,0,len);  
  58.         }  
  59.         catch (Exception e)  
  60.          {  
  61.            e.printStackTrace();  
  62.          }  
  63.     }  
  64. }  
(4)Java I/O库的设计原则
Java的I/O库提供了一个称做链接的机制,可以将一个流与另一个流首尾相接,形成一个流管道的链接。这种机制实际上是一种被称为Decorator(装饰)设计模式的应用。
通过流的链接,可以动态的增加流的功能,而这种功能的增加是通过组合一些流的基本功能而动态获取的。

我们要获取一个I/O对象,往往需要产生多个I/O对象,这也是Java I/O库不太容易掌握的原因,但在I/O库中Decorator模式的运用,给我们提供了实现上的灵活性。I/O流的链接如下图所示:


(5)Reader和Writer 操作字符流
Java程序语言使用Unicode来表示字符串和字符。
Reader和Writer这两个抽象类主要用来读写字符流。

Reader和Writer类层次如下图所示:


(6)RandomAccessFile
RandomAccessFile类同时实现了DataInput和DataOutput接口,提供了对文件随机存取的功能,利用这个类可以在文件的任何位置读取或写入数据。
RandomAccessFile类提供了一个文件指针,用来标志要进行读写操作的下一数据的位置。
RandomAccessFile测试代码如下:
[java] view plaincopyprint?
  1. import java.io.*;  
  2. class RandomAccessFileTest  
  3. {  
  4.     public static void main(String[] args) throws Exception  
  5.     {     
  6.         Student  stu1=new Student(1,"ZhangSan",98.5);  
  7.         Student  stu2=new Student(2,"liSi",97.5);  
  8.         Student  stu3=new Student(3,"WangWu",88.5);  
  9.   
  10.         RandomAccessFile  raf=new RandomAccessFile("Student.txt","rw");  
  11.         //写入   
  12.         stu1.write(raf);  
  13.         stu2.write(raf);  
  14.         stu3.write(raf);  
  15.         //读取   
  16.         raf.seek(0);//移动文件指针 否则  EOFException  
  17.         Student stu=new Student();  
  18.         for(long i=0;i<raf.length();i=raf.getFilePointer())  
  19.         {  
  20.               stu.read(raf);  
  21.               System.out.println(stu);  
  22.         }  
  23.         raf.close();  
  24.     }  
  25. }  
  26. class Student  
  27. {  
  28.     int num;  
  29.     String name;  
  30.     Double score;  
  31.     Student( )  
  32.     {  
  33.     }  
  34.     Student(int num,String name,double score)  
  35.     {  
  36.        this.num=num;  
  37.        this.name=name;  
  38.        this.score=score;  
  39.     }  
  40.     public  void write(RandomAccessFile raf) throws Exception  
  41.     {  
  42.          raf.writeInt(num);  
  43.          raf.writeUTF(name);  
  44.          raf.writeDouble(score);  
  45.     }  
  46.     public void read(RandomAccessFile raf) throws Exception  
  47.     {  
  48.          num=raf.readInt();  
  49.          name=raf.readUTF();  
  50.          score=raf.readDouble();  
  51.     }  
  52.     public String toString()  
  53.     {  
  54.        return "num:"+num+" "+"name:"+name+" "+"score:"+score;  
  55.     }  
  56. }  
3.字符集的编码
字符编码部分内容较为复杂,在此不做深究,列出一个测试代码如下:

[java] view plaincopyprint?
  1. import java.util.*;  
  2. import java.nio.charset.*;  
  3. class CharsetTest  
  4. {  
  5.     public static void main(String[] args)  throws Exception  
  6.     {     
  7.         /* 
  8.         //列举当前可用字符集 
  9.         Map map=Charset.availableCharsets(); 
  10.         Set names=map.keySet(); 
  11.         Iterator iter=names.iterator(); 
  12.         while(iter.hasNext()) 
  13.         { 
  14.             System.out.println(iter.next()); 
  15.         } 
  16.         */  
  17.          Properties pps=System.getProperties();  
  18.          //pps.list(System.out);   
  19.   
  20.          //编码与解码的问题   
  21.          pps.put("file.encoding","ISO-8859-1");  
  22.          byte[] buf=new byte[100];  
  23.          int data;  
  24.          int i=0;  
  25.         while((data=System.in.read())!='q')  
  26.          {  
  27.                  buf[i]=(byte)data;  
  28.                  i++;  
  29.          }  
  30.          String strbuf=new String(buf,0,i);  
  31.          System.out.println(strbuf);  
  32.          //重新解码   
  33.          String strGBK=new String(strbuf.getBytes("ISO-8859-1"),"GBK");  
  34.          System.out.println(strGBK);  
  35.     }  
  36. }  
4.对象序列化
将对象转换为字节流保存起来,并在日后还原这个对象,这种机制叫做对象序列化
将一个对象保存到永久存储设备上称为
持续性
一个对象要想能够实现序列化,必须实现Serializable接口或Externalizable接口。

(1)当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量。

(2)如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存。

(3)如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化。对象序列化测试代码如下:
[java] view plaincopyprint?
  1. import java.io.*;  
  2. class ObjectSerializeTest  
  3. {  
  4.     public static void main(String[] args) throws Exception  
  5.     {     
  6.         Employee e1=new Employee("ZhangSan",25,3500.50);  
  7.         Employee e2=new Employee("LiSi",26,3200.80);  
  8.         Employee e3=new Employee("WangWu",35,4500.50);  
  9.           
  10.           
  11.         //写入对象   
  12.         FileOutputStream fos=new FileOutputStream("Employee.txt");  
  13.         ObjectOutputStream oos=new ObjectOutputStream(fos);  
  14.         oos.writeObject(e1);  
  15.         oos.writeObject(e2);  
  16.         oos.writeObject(e3);  
  17.         oos.close();  
  18.         //读取对象   
  19.         FileInputStream  fis=new FileInputStream("Employee.txt");  
  20.         ObjectInputStream ois=new ObjectInputStream(fis);  
  21.         Employee e;//不会调用构造方法   
  22.         for(int i=0;i<3;i++)  
  23.         {  
  24.            e=(Employee)ois.readObject();  
  25.            System.out.println(e);  
  26.         }  
  27.         ois.close();  
  28.     }  
  29. }  
  30. //类的序列化   
  31. class Employee  implements Serializable  
  32. {  
  33.     String name;  
  34.     int age;  
  35.     double salary;  
  36.     //将对象(一般为不可序列化对象)标记为transient将不参与序列化,否则产生NotSerializableException  
  37.     transient Thread th=new Thread();  
  38.     public Employee(String name ,int age,double salary)  
  39.     {  
  40.         this.name=name;  
  41.         this.age=age;  
  42.         this.salary=salary;  
  43.       
  44.     }  
  45.     public String toString()  
  46.     {  
  47.       return "name:"+name+" "+"age:"+age+" "+"salary:"+salary;  
  48.     }  
  49.     //自定义序列化方法  在类外可以被调用 特例   
  50.     private void writeObject(java.io.ObjectOutputStream out) throws IOException  
  51.     {  
  52.         out.writeInt(age);  
  53.         out.writeUTF(name);  
  54.         System.out.println("Write object!");  
  55.     }  
  56.   private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException  
  57.     {  
  58.          age=in.readInt();  
  59.          name=in.readUTF();  
  60.          System.out.println("read object!");  
  61.      }  
  62.        
  63. }