程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> java IO 實例分析,javaio實例分析

java IO 實例分析,javaio實例分析

編輯:JAVA綜合教程

java IO 實例分析,javaio實例分析


初學java,一直搞不懂java裡面的io關系,在網上找了很多大多都是給個結構圖草草描述也看的不是很懂。而且沒有結合到java7 的最新技術,所以自己來整理一下,有錯的話請指正,也希望大家提出寶貴意見。

首先看個圖:(如果你也是初學者,我相信你看了真個人都不好了,想想java設計者真是煞費苦心啊!)

這是java io 比較基本的一些處理流,除此之外我們還會提到一些比較深入的基於io的處理類,比如console類,SteamTokenzier,Externalizable接口,Serializable接口等等一些高級用法極其原理。

一、java io的開始:文件

1. 我們主要講的是流,流的本質也是對文件的處理,我們循序漸進一步一步從文件將到流去。

2. java 處理文件的類 File,java提供了十分詳細的文件處理方法,舉了其中幾個例子,其余的可以去

 

Java代碼  
  • package com.hxw.io;  
  • import java.io.*;  
  •    
  • public class FileExample{  
  •     public static void main(String[] args) {  
  •        
  •         createFile();  
  •     }  
  •    
  •   /** 
  •    * 文件處理示例 
  •    */  
  •   public static void createFile() {  
  •      File f=new File("E:/電腦桌面/jar/files/create.txt");  
  •         try{  
  •             f.createNewFile();  //當且僅當不存在具有此抽象路徑名指定名稱的文件時,不可分地創建一個新的空文件。  
  •             System.out.println("該分區大小"+f.getTotalSpace()/(1024*1024*1024)+"G"); //返回由此抽象路徑名表示的文件或目錄的大小。  
  •             f.mkdirs();  //創建此抽象路徑名指定的目錄,包括所有必需但不存在的父目錄。  
  • //            f.delete(); //  刪除此抽象路徑名表示的文件或目錄  
  •            System.out.println("文件名  "+f.getName());  //  返回由此抽象路徑名表示的文件或目錄的名稱。  
  •            System.out.println("文件父目錄字符串 "+f.getParent());// 返回此抽象路徑名父目錄的路徑名字符串;如果此路徑名沒有指定父目錄,則返回 null。  
  •             
  •         }catch (Exception e) {  
  •             e.printStackTrace();  
  •         }  
  •   }  
  • }  


  • 二、字節流:

    1.字節流有輸入和輸出流,我們首先看輸入流InputStream,我們首先解析一個例子(FileInputStream)。

     

    Java代碼  
  • package com.hxw.io;  
  • import java.io.File;  
  • import java.io.FileInputStream;  
  • import java.io.IOException;  
  • import java.io.InputStream;  
  • public class FileCount {  
  •    /** 
  •     * 我們寫一個檢測文件長度的小程序,別看這個程序挺長的,你忽略try catch塊後發現也就那麼幾行而已。 
  •     */  
  •    publicstatic void main(String[] args) {  
  •       //TODO 自動生成的方法存根  
  •              int count=0;  //統計文件字節長度  
  •       InputStreamstreamReader = null;   //文件輸入流  
  •       try{  
  •           streamReader=newFileInputStream(new File("D:/David/Java/java 高級進階/files/tiger.jpg"));  
  •           /*1.new File()裡面的文件地址也可以寫成D:\\David\\Java\\java 高級進階\\files\\tiger.jpg,前一個\是用來對後一個 
  •            * 進行轉換的,FileInputStream是有緩沖區的,所以用完之後必須關閉,否則可能導致內存占滿,數據丟失。 
  •           */  
  •           while(streamReader.read()!=-1) {  //讀取文件字節,並遞增指針到下一個字節  
  •              count++;  
  •           }  
  •           System.out.println("---長度是: "+count+" 字節");  
  •       }catch (final IOException e) {  
  •           //TODO 自動生成的 catch 塊  
  •           e.printStackTrace();  
  •       }finally{  
  •           try{  
  •              streamReader.close();  
  •           }catch (IOException e) {  
  •              //TODO 自動生成的 catch 塊  
  •              e.printStackTrace();  
  •           }  
  •       }  
  •    }  
  •    
  • }  


  • 我們一步一步來,首先,上面的程序存在問題是,每讀取一個自己我都要去用到FileInputStream,我輸出的結果是“---長度是: 64982 字節”,那麼進行了64982次操作!可能想象如果文件十分龐大,這樣的操作肯定會出大問題,所以引出了緩沖區的概念。可以將 streamReader.read()改成streamReader.read(byte[]b)此方法讀取的字節數目等於字節數組的長度,讀取的數據 被存儲在字節數組中,返回讀取的字節數,InputStream還有其他方法mark,reset,markSupported方法,例如:

     

    markSupported 判斷該輸入流能支持mark 和 reset 方法。

    mark用於標記當前位置;在讀取一定數量的數據(小於readlimit的數據)後使用reset可以回到mark標記的位置。

    FileInputStream不支持mark/reset操作;BufferedInputStream支持此操作;

    mark(readlimit)的含義是在當前位置作一個標記,制定可以重新讀取的最大字節數,也就是說你如果標記後讀取的字節數大於readlimit,你就再也回不到回來的位置了。

    通常InputStream的read()返回-1後,說明到達文件尾,不能再讀取。除非使用了mark/reset。

     

     

    2.FileOutputStream 循序漸進版, OutputStream是所有字節輸出流的父類,子類有 ByteArrayOutputStream,FileOutputStream,ObjectOutputStreanm,這些我們在後面都會一一說 到。先說FileOutputStream

    我以一個文件復制程序來說,順便演示一下緩存區的使用。(Java I/O默認是不緩沖流的,所謂“緩沖”就是先把從流中得到的一塊字節序列暫存在一個被稱為buffer的內部字節數組裡,然後你可以一下子取到這一整塊的 字節數據,沒有緩沖的流只能一個字節一個字節讀,效率孰高孰低一目了然。有兩個特殊的輸入流實現了緩沖功能,一個是我們常用的 BufferedInputStream.)

     

    Java代碼  
  • package com.hxw.io;  
  • import java.io.*;  
  •    
  • public class FileCopy {  
  •    
  •   public static void main(String[] args) {  
  •      // TODO自動生成的方法存根  
  •      byte[] buffer=new byte[512];   //一次取出的字節數大小,緩沖區大小  
  •      int numberRead=0;  
  •      FileInputStream input=null;  
  •      FileOutputStream out =null;  
  •      try {  
  •         input=new FileInputStream("D:/David/Java/java 高級進階/files/tiger.jpg");  
  •         out=new FileOutputStream("D:/David/Java/java 高級進階/files/tiger2.jpg"); //如果文件不存在會自動創建(目錄不存在會報錯) 
  •          
  •         while ((numberRead=input.read(buffer))!=-1) {  //numberRead的目的在於防止最後一次讀取的字節小於buffer長度,  
  •            out.write(buffer, 0, numberRead);       //否則會自動被填充0  
  •         }  
  •      } catch (final IOException e) {  
  •         // TODO自動生成的 catch 塊  
  •         e.printStackTrace();  
  •      }finally{  
  •         try {  
  •            input.close();  
  •            out.close();  
  •         } catch (IOException e) {  
  •            // TODO自動生成的 catch 塊  
  •            e.printStackTrace();  
  •         }  
  •          
  •      }  
  •   }  
  •    
  • }  
  •  

     

    3.讀寫對象:ObjectInputStream 和ObjectOutputStream ,該流允許讀取或寫入用戶自定義的類,但是要實現這種功能,被讀取和寫入的類必須實現Serializable接口,其實該接口並沒有什麼方法,可能相當 於一個標記而已,但是確實不可缺少的。實例代碼如下:

     

    Java代碼  
  • package com.hxw.io;  
  •    
  • import java.io.*;  
  •    
  • public class ObjetStream {  
  •    
  •    /** 
  •     * @param args 
  •     */  
  •    public static void main(String[] args) {  
  •       // TODO自動生成的方法存根  
  •       ObjectOutputStream objectwriter=null;  
  •       ObjectInputStream objectreader=null;  
  •        
  •       try {  
  •          objectwriter=new ObjectOutputStream(new FileOutputStream("D:/David/Java/java 高級進階/files/student.txt"));  
  •          objectwriter.writeObject(new Student("gg", 22));  
  •          objectwriter.writeObject(new Student("tt", 18));  
  •          objectwriter.writeObject(new Student("rr", 17));  
  •          objectreader=new ObjectInputStream(new FileInputStream("D:/David/Java/java 高級進階/files/student.txt"));  
  •          for (int i = 0; i < 3; i++) {  
  •             System.out.println(objectreader.readObject());  
  •          }  
  •       } catch (IOException | ClassNotFoundException e) {  
  •          // TODO自動生成的 catch 塊  
  •          e.printStackTrace();  
  •       }finally{  
  •          try {  
  •             objectreader.close();  
  •             objectwriter.close();  
  •          } catch (IOException e) {  
  •             // TODO自動生成的 catch 塊  
  •             e.printStackTrace();  
  •          }  
  •           
  •       }  
  •        
  •    }  
  •    
  • }  
  • class Student implements Serializable{  
  •    private String name;  
  •    private int age;  
  •     
  •    public Student(String name, int age) {  
  •       super();  
  •       this.name = name;  
  •       this.age = age;  
  •    }  
  •    
  •    @Override  
  •    public String toString() {  
  •       return "Student [name=" + name + ", age=" + age + "]";  
  •    }  
  •     
  •     
  • }  


  • 運行後系統輸出:

    Student [name=gg, age=22]

    Student [name=tt, age=18]

    Student [name=rr, age=17]

    4.有時沒有必要存儲整個對象的信息,而只是要存儲一個對象的成員數據,成員數據的類型假設都是Java的基本數據類型,這樣的需求不必 使用到與Object輸入、輸出相關的流對象,可以使用DataInputStream、DataOutputStream來寫入或讀出數據。下面是一個 例子:(DataInputStream的好處在於在從文件讀出數據時,不用費心地自行判斷讀入字符串時或讀入int類型時何時將停止,使用對應的readUTF()和readInt()方法就可以正確地讀入完整的類型數據。)

     

     

    Java代碼  
  • package com.hxw;  
  • public class Member {  
  •     private String name;  
  •     private int age;  
  •     public Member() {  
  •     }  
  •    public Member(String name, int age) {  
  •         this.name = name;  
  •         this.age = age;  
  •     }  
  •     public void setName(String name){  
  •         this.name = name;  
  •     }  
  •     public void setAge(int age) {  
  •         this.age = age;  
  •     }  
  •     public String getName() {  
  •         return name;  
  •     }  
  •     public int getAge() {  
  •         return age;  
  •     }  
  • }  


  • 打算將Member類實例的成員數據寫入文件中,並打算在讀入文件數據後,將這些數據還原為Member對象。下面的代碼簡單示范了如何實現這個需求。

     

     

    Java代碼  
  • package com.hxw;  
  • import java.io.*;  
  • public class DataStreamDemo  
  • {  
  •   public static void main(String[]args)  
  •   {  
  •      Member[] members = {newMember("Justin",90),  
  •                         newMember("momor",95),  
  •                         newMember("Bush",88)};  
  •         try  
  •      {  
  •         DataOutputStreamdataOutputStream = new DataOutputStream(new FileOutputStream(args[0]));  
  •    
  •         for(Member member:members)  
  •         {  
  •             //寫入UTF字符串  
  •            dataOutputStream.writeUTF(member.getName());  
  •            //寫入int數據  
  •            dataOutputStream.writeInt(member.getAge());  
  •         }  
  •    
  •         //所有數據至目的地  
  •         dataOutputStream.flush();  
  •         //關閉流  
  •         dataOutputStream.close();  
  •    
  •             DataInputStreamdataInputStream = new DataInputStream(new FileInputStream(args[0]));  
  •    
  •         //讀出數據並還原為對象  
  •         for(inti=0;i<members.length;i++)  
  •         {  
  •            //讀出UTF字符串  
  •            String name =dataInputStream.readUTF();  
  •            //讀出int數據  
  •            int score =dataInputStream.readInt();  
  •            members[i] = newMember(name,score);  
  •         }  
  •    
  •         //關閉流  
  •         dataInputStream.close();  
  •    
  •         //顯示還原後的數據  
  •         for(Member member : members)  
  •         {  
  •            System.out.printf("%s\t%d%n",member.getName(),member.getAge());  
  •         }  
  •      }  
  •      catch(IOException e)  
  •      {  
  •             e.printStackTrace();  
  •      }  
  •   }  
  • }  


  • 5.PushbackInputStream類繼承了FilterInputStream類是iputStream類的修飾者。提供可以 將數據插入到輸入流前端的能力(當然也可以做其他操作)。簡而言之PushbackInputStream類的作用就是能夠在讀取緩沖區的時候提前知道下 一個字節是什麼,其實質是讀取到下一個字符後回退的做法,這之間可以進行很多操作,這有點向你把讀取緩沖區的過程當成一個數組的遍歷,遍歷到某個字符的時候可以進行的操作,當然,如果要插入,能夠插入的最大字節數是與推回緩沖區的大小相關的,插入字符肯定不能大於緩沖區吧!下面是一個示例。

     

    Java代碼  
  • package com.hxw.io;  
  •    
  • import java.io.ByteArrayInputStream; //導入ByteArrayInputStream的包  
  • import java.io.IOException;  
  • import java.io.PushbackInputStream;  
  •    
  • /** 
  •  * 回退流操作 
  •  * */  
  • public class PushBackInputStreamDemo {  
  • public static void main(String[] args) throws IOException {  
  •     String str = "hello,rollenholt";  
  •     PushbackInputStream push = null; // 聲明回退流對象  
  •     ByteArrayInputStream bat = null; // 聲明字節數組流對象  
  •     bat = new ByteArrayInputStream(str.getBytes());  
  •     push = new PushbackInputStream(bat); // 創建回退流對象,將拆解的字節數組流傳入  
  •     int temp = 0;  
  •     while ((temp = push.read()) != -1) { // push.read()逐字節讀取存放在temp中,如果讀取完成返回-1  
  •        if (temp == ',') { // 判斷讀取的是否是逗號  
  •           push.unread(temp); //回到temp的位置  
  •           temp = push.read(); //接著讀取字節  
  •           System.out.print("(回退" + (char) temp + ") "); // 輸出回退的字符  
  •        } else {  
  •           System.out.print((char) temp); // 否則輸出字符  
  •        }  
  •     }  
  • }  
  • }  


  • 6.SequenceInputStream:有些情況下,當我們需要從多個輸入流中向程序讀入數據。此時,可以使用合並流,將多個輸入 流合並成一個SequenceInputStream流對象。SequenceInputStream會將與之相連接的流集組合成一個輸入流並從第一個輸 入流開始讀取,直到到達文件末尾,接著從第二個輸入流讀取,依次類推,直到到達包含的最後一個輸入流的文件末尾為止。 合並流的作用是將多個源合並合一個源。其可接收枚舉類所封閉的多個字節流對象。

     

    Java代碼  
  • package com.hxw.io;  
  •    
  • import java.io.*;  
  • import java.util.Enumeration;  
  • import java.util.Vector;  
  •    
  • public class SequenceInputStreamTest {  
  •   /** 
  •    * @param args 
  •    *            SequenceInputStream合並流,將與之相連接的流集組合成一個輸入流並從第一個輸入流開始讀取, 
  •    *            直到到達文件末尾,接著從第二個輸入流讀取,依次類推,直到到達包含的最後一個輸入流的文件末尾為止。 
  •    *            合並流的作用是將多個源合並合一個源。可接收枚舉類所封閉的多個字節流對象。 
  •    */  
  •   public static void main(String[] args) {  
  •      doSequence();  
  •   }  
  •    
  •   private static void doSequence() {  
  •      // 創建一個合並流的對象  
  •      SequenceInputStream sis = null;  
  •      // 創建輸出流。  
  •      BufferedOutputStream bos = null;  
  •      try {  
  •         // 構建流集合。  
  •         Vector<InputStream> vector = new Vector<InputStream>();  
  •         vector.addElement(new FileInputStream("D:\text1.txt"));  
  •         vector.addElement(new FileInputStream("D:\text2.txt"));  
  •         vector.addElement(new FileInputStream("D:\text3.txt"));  
  •         Enumeration<InputStream> e = vector.elements();  
  •    
  •         sis = new SequenceInputStream(e);  
  •    
  •         bos = new BufferedOutputStream(new FileOutputStream("D:\text4.txt"));  
  •         // 讀寫數據  
  •         byte[] buf = new byte[1024];  
  •         int len = 0;  
  •         while ((len = sis.read(buf)) != -1) {  
  •            bos.write(buf, 0, len);  
  •            bos.flush();  
  •         }  
  •      } catch (FileNotFoundException e1) {  
  •         e1.printStackTrace();  
  •      } catch (IOException e1) {  
  •         e1.printStackTrace();  
  •      } finally {  
  •         try {  
  •            if (sis != null)  
  •               sis.close();  
  •         } catch (IOException e) {  
  •            e.printStackTrace();  
  •         }  
  •         try {  
  •            if (bos != null)  
  •               bos.close();  
  •         } catch (IOException e) {  
  •            e.printStackTrace();  
  •         }  
  •      }  
  •   }  
  • }  


  • 7.PrintStream 說這個名字可能初學者不熟悉,如果說System.out.print()你肯定熟悉,System.out這個對象就是PrintStream,這個我們不做過多示例

    三、字符流(顧名思義,就是操作字符文件的流)

    1.java 使用Unicode存儲字符串,在寫入字符流時我們都可以指定寫入的字符串的編碼。前面介紹了不用拋異常的處理字節型數據的流 ByteArrayOutputStream,與之對應的操作字符類的類就是CharArrayReader,CharArrayWriter類,這裡也 會用到緩沖區,不過是字符緩沖區,一般講字符串放入到操作字符的io流一般方法是

    CharArrayReaderreader=mew CharArrayReader(str.toCharArray()); 一旦會去到CharArrayReader實例就可以使用CharArrayReader訪問字符串的各個元素以執行進一步讀取操作。不做例子

    2.我們用FileReader ,PrintWriter來做示范

     

    Java代碼  
  • package com.hxw.io;  
  •    
  • import java.io.FileNotFoundException;  
  • import java.io.FileReader;  
  • import java.io.IOException;  
  • import java.io.PrintWriter;  
  • import java.nio.CharBuffer;  
  •    
  • public class Print {  
  •    
  • /** 
  •  * @param args 
  •  */  
  • public static void main(String[] args) {  
  •     // TODO自動生成的方法存根  
  •     char[] buffer=new char[512];   //一次取出的字節數大小,緩沖區大小  
  •     int numberRead=0;  
  •     FileReader reader=null;        //讀取字符文件的流  
  •     PrintWriter writer=null;    //寫字符到控制台的流  
  •      
  •     try {  
  •        reader=new FileReader("D:/David/Java/java 高級進階/files/copy1.txt");  
  •        writer=new PrintWriter(System.out);  //PrintWriter可以輸出字符到文件,也可以輸出到控制台  
  •        while ((numberRead=reader.read(buffer))!=-1) {  
  •           writer.write(buffer, 0, numberRead);  
  •        }  
  •     } catch (IOException e) {  
  •        // TODO自動生成的 catch 塊  
  •        e.printStackTrace();  
  •     }finally{  
  •        try {  
  •           reader.close();  
  •        } catch (IOException e) {  
  •           // TODO自動生成的 catch 塊  
  •           e.printStackTrace();  
  •        }  
  •        writer.close();       //這個不用拋異常  
  •     }  
  •         
  • }  
  •    
  • }  


  • 3.相對我們前面的例子是直接用FileReader打開的文件,我們這次使用鏈接流,一般比較常用的都用鏈接流,所謂鏈接流就是就多次 對流的封裝,這樣能更好的操作個管理數據,(比如我們利用 DataInputStream(BufferedInputStream(FileInputStream))將字節流層層包裝後,我們可以讀取 readByte(),readChar()這樣更加具體的操作,注意,該流屬於字節流對字符進行操作,)字符流用CharArrayReader就可以 了。下面的示例我們將用到j2se 5中的一個可變參數進行一個小度擴展。使用BufferedWriter 和BufferedReader用文件級聯的方式進行寫入,即將多個文件寫入到同一文件中(自帶緩沖區的輸出輸出流BufferedReader和 BufferedWriter,該流最常用的屬readLine()方法了,讀取一行數據,並返回String)。

     

     

    Java代碼  
  • package com.hxw.io;  
  •    
  • import java.io.BufferedReader;  
  • import java.io.BufferedWriter;  
  • import java.io.FileReader;  
  • import java.io.FileWriter;  
  • import java.io.IOException;  
  • import java.util.Iterator;  
  •    
  • public class FileConcatenate {  
  •    
  •   /** 
  •    * 包裝類進行文件級聯操作 
  •    */  
  •   public static void main(String[] args) {  
  •      // TODO自動生成的方法存根  
  •      try {  
  •         concennateFile(args);  
  •      } catch (IOException e) {  
  •         // TODO自動生成的 catch 塊  
  •         e.printStackTrace();  
  •      }  
  •   }  
  •   public static voidconcennateFile(String...fileName) throws IOException{  
  •      String str;  
  •      //構建對該文件您的輸入流  
  •      BufferedWriter writer=new BufferedWriter(new FileWriter("D:/David/Java/java 高級進階/files/copy2.txt"));  
  •      for(String name: fileName){  
  •         BufferedReader reader=new BufferedReader(new FileReader(name));  
  •          
  •         while ((str=reader.readLine())!=null) {  
  •            writer.write(str);  
  •            writer.newLine();  
  •         }  
  •      }  
  •   }  
  •    
  • }  
  •    


  • 4.Console類,該類提供了用於讀取密碼的方法,可以禁止控制台回顯並返回char數組,對兩個特性對保證安全有作用,平時用的不多,了解就行。

    5.StreamTokenizer 類,這個類非常有用,它可以把輸入流解析為標記(token), StreamTokenizer 並非派生自InputStream或者OutputStream,而是歸類於io庫中,因為StreamTokenizer只處理InputStream 對象。

    首先給出我的文本文件內容:

    '水上漂'

    青青草

    "i love wyhss"

    {3211}

    23223 3523

    i love wyh ,。

    . ,

    下面是代碼:

     

    Java代碼  
  • package com.hxw.io;  
  • import java.io.BufferedReader;  
  • import java.io.FileReader;  
  • import java.io.IOException;  
  • import java.io.StreamTokenizer;  
  •    
  • /** 
  •  * 使用StreamTokenizer來統計文件中的字符數 
  •  * StreamTokenizer 類獲取輸入流並將其分析為“標記”,允許一次讀取一個標記。 
  •  * 分析過程由一個表和許多可以設置為各種狀態的標志控制。 
  •  * 該流的標記生成器可以識別標識符、數字、引用的字符串和各種注釋樣式。 
  •  * 
  •  *  默認情況下,StreamTokenizer認為下列內容是Token: 字母、數字、除C和C++注釋符號以外的其他符號。 
  •  *  如符號"/"不是Token,注釋後的內容也不是,而"\"是Token。單引號和雙引號以及其中的內容,只能算是一個Token。 
  •  *  統計文章字符數的程序,不是簡單的統計Token數就萬事大吉,因為字符數不等於Token。按照Token的規定, 
  •  *  引號中的內容就算是10頁也算一個Token。如果希望引號和引號中的內容都算作Token,應該調用下面的代碼: 
  •  *    st.ordinaryChar('\''); 
  •  * st.ordinaryChar('\"'); 
  •  */  
  • public class StreamTokenizerExample {  
  •    
  •     /** 
  •      * 統計字符數 
  •      * @param fileName 文件名 
  •      * @return    字符數 
  •      */  
  • public static void main(String[] args) {  
  •         String fileName = "D:/David/Java/java 高級進階/files/copy1.txt";  
  •         StreamTokenizerExample.statis(fileName);  
  •     }  
  •     public static long statis(String fileName) {  
  •    
  •         FileReader fileReader = null;  
  •         try {  
  •             fileReader = new FileReader(fileName);  
  •             //創建分析給定字符流的標記生成器  
  •             StreamTokenizer st = new StreamTokenizer(new BufferedReader(  
  •                     fileReader));  
  •    
  •             //ordinaryChar方法指定字符參數在此標記生成器中是“普通”字符。  
  •             //下面指定單引號、雙引號和注釋符號是普通字符  
  •             st.ordinaryChar('\'');  
  •             st.ordinaryChar('\"');  
  •             st.ordinaryChar('/');  
  •    
  •             String s;  
  •             int numberSum = 0;  
  •             int wordSum = 0;  
  •             int symbolSum = 0;  
  •             int total = 0;  
  •             //nextToken方法讀取下一個Token.  
  •             //TT_EOF指示已讀到流末尾的常量。  
  •             while (st.nextToken() !=StreamTokenizer.TT_EOF) {  
  •                 //在調用 nextToken 方法之後,ttype字段將包含剛讀取的標記的類型  
  •                 switch (st.ttype) {  
  •                 //TT_EOL指示已讀到行末尾的常量。  
  •                 case StreamTokenizer.TT_EOL:  
  •                     break;  
  •                 //TT_NUMBER指示已讀到一個數字標記的常量  
  •                 case StreamTokenizer.TT_NUMBER:  
  •                     //如果當前標記是一個數字,nval字段將包含該數字的值  
  •                     s = String.valueOf((st.nval));  
  •                     System.out.println("數字有:"+s);  
  •                     numberSum ++;  
  •                     break;  
  •                 //TT_WORD指示已讀到一個文字標記的常量  
  •                 case StreamTokenizer.TT_WORD:  
  •                     //如果當前標記是一個文字標記,sval字段包含一個給出該文字標記的字符的字符串  
  •                     s = st.sval;  
  •                     System.out.println("單詞有: "+s);  
  •                     wordSum ++;  
  •                     break;  
  •                 default:  
  •                     //如果以上3中類型都不是,則為英文的標點符號  
  •                     s = String.valueOf((char) st.ttype);  
  •                     System.out.println("標點有: "+s);  
  •                     symbolSum ++;  
  •                 }  
  •             }  
  •             System.out.println("數字有 " + numberSum+"個");  
  •             System.out.println("單詞有 " + wordSum+"個");  
  •             System.out.println("標點符號有: " + symbolSum+"個");  
  •             total = symbolSum + numberSum +wordSum;  
  •             System.out.println("Total = " + total);  
  •             return total;  
  •         } catch (Exception e) {  
  •             e.printStackTrace();  
  •             return -1;  
  •         } finally {  
  •             if (fileReader != null) {  
  •                 try {  
  •                     fileReader.close();  
  •                 } catch (IOException e1) {  
  •                 }  
  •             }  
  •         }  
  •     }  
  •    
  •      
  • }  


  • 運行結果為:

    標點有: '

    單詞有: 水上漂

    標點有: '

    單詞有: 青青草

    標點有: "

    單詞有: i

    單詞有: love

    單詞有: wyh

    單詞有: ss

    標點有: "

    標點有: {

    數字有:3211.0

    標點有: }

    數字有:23223.0

    數字有:35.23

    單詞有: i

    單詞有: love

    單詞有: wyh

    單詞有: ,。

    數字有:0.0

    標點有: ,

    數字有 4個

    單詞有 10個

    標點符號有: 7個

    Total= 21

     

    我們從其中可以看到很多東西:

    1.一個單獨的小數點“.”是被當做一個數字來對待的,數字的值為0.0;

    2.一串漢字只要中間沒有符號(空格回車 分號等等)都是被當做一個單詞的。中文的標點跟中文的漢字一樣處理

    3.如果不對引號化成普通字符,一個引號內的內容不論多少都被當做是一個標記。

    4.該類能夠識別英文標點

     

    6. java io裡面還有其他接口類似Serializable接口的子接口Externalizable接口,比Serializable復雜一些,這裡不再介紹。 還有關於java對象版本化的東西感興趣的可以百度。java nio的東西這裡沒有涉及,後續會結合到線程再發一篇文章專門解析這個東西。

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved