隨筆-159  評論-114  文章-7  trackbacks-0
          需求,java程序與外屆交流數據。

          實際上是OS與JVM內存交互數據。

          那么針對程序,有輸出流,也有輸入流。

          java.io包下,File類,它表示文件系統上的一個文件或者目錄。

          方法,總體來說是對磁盤文件的磁盤操作,不能看內容,主要是為了獲得文件和文件屬性。

          File dir = new File("d:\");
          File f = new File(dir,"11.txt");// -->創建文件對象,只是一個對象,沒有反映到磁盤上。
          f.createNewFile();//-->創建文件
          f.mkdir();//創建目錄

          delete();調用完馬上就刪除了
          deleteOnExit();程序退出時,可以作為臨時文件。

          new File("d:\\....\\11.txt");
          File.separator


          file.list() 所有文件名 String[]
          file.listFiles() File[]數組

          注意如何實現 dir *.java的效果呢,需要一個過濾器

          public File[] listFiles(FilenameFilter filter)

          public File[] listFiles(FileFilter filter)


          FilenameFilter需要實現

          boolean accept(File dir, String name)

          返回true,表示要包含在結果中的

          new FilenameFilter(){
                public boolean acccept(File dir,String name)
                {
                     if(name.indexOf(".java") == -1) return false;
                     else return true;
                }
          }


          ===================================

          File類不能讀取文件內容。

          所以真正讀取文件內容,需要在虛擬機中的對象和DS數據源之間建立一個數據輸入輸出流。

          按照以JVM為方向,數據流向分為輸入流,輸出流。

          按照傳輸數據單元:又有字節流和字符流。8位為一字節。

          按功能又叫做節點流,比如專門以文件為數據源與程序建立的數據流,通道,就是FileInputStream。

          給節點流,添加輔助功能的流,也就是構造方法的參數為其他流的流,一定是過濾流。(裝飾模式應用)



          所有字節輸入流的父類,都是InputStream。比如有子類,FileInputStream,還有javax.sound.sampled.AudioInputStream

          它有一個read()方法,一次讀入一個字節,由于是跨出JVM的操作,因此極其消耗資源。

          所以一般用read(byte[] b),給一個字節數組,方法返回,字節數據會讀滿,返回值為實際,讀入的字節數,用于處理,最后一次時,可能并沒有裝滿,要保證文件一個字節都不差,必須爭取取出相應個數的字節內容。返回-1,表示沒有可以讀的了。

          read(byte[] b, int off, int len),從數組off起始位置讀入,len試圖讀入的個數。可控的。

          read(b)  <==> read(b,0,b.length);

          OutputStream

          write(int b) -> 寫一個字節 

          由于輸入、輸出流是跨出虛擬機邊界的資源,虛擬機很難回收,這時對于資源的占用,是一種極大的浪費。

          就好像,你能讓你媽幫你收拾屋子,洗衣服,但是你打開水龍口,打完水不管水龍頭,試一試。

          或者你在麥當勞吃完飯,盤子放那,有服務生來幫你收走,但你試試把盤子拿到大街上,放在外面,服務生是不能回收的。

          雖然Java幫你回收不使用的對象,但對于關閉輸入輸出流的工作,程序員是要自己負責!因為跨出虛擬機邊界,虛擬機不管。

          ============================

          節點流,FileInputStream,當然也是字節流。有Stream,只是記憶方便。

          構造器參數,文件名,文件對象File

          FileInputStream fi = new FileInputStream("1.txt");
          byte b[] = new byte[100];
          int length;
          while((length = (fi.read(b))!=-1){
                String s = new String(b);
                System.out.println(s);
          }
          fi.close();

          FileOutputSteam(File file,boolean append)//第二個選項,為true,表示要追加文件內容。

          構造器一個FileOutputStream對象時,磁盤會同時生成一個文件(如果已存在同名文件,會先刪除)

          FileOutputSteam fo = new FileOutputStream("1.txt",true);
          String s = new String("hi my girl");
          byte[] b = s.getBytes();
          while(fo.write(b)!= -1){};
          fo.close();


          為了能夠輕松的將簡單數據類型的數據,直接輸出到流中,需要對已存在字節輸出流添加功能。

          所以這種流叫做過濾流,例如java.io.DataOutputStream。它的構造函數參數為OutputStream對象。

          FileOutputStream file = new FileOutputStream("DST1.txt");
          DataOutputStream out = new DataOutputStream(file);

          out.writeUTF(str);

          注意使用這個過濾流,輸出和輸入的順序要一致。

          輸出:

          _byte_ _short_ _ _ _int

          輸入:
          不能夠
          _ _short_ byte_ _ _ _

          這樣讀,會將byte和short的前一個字節一起讀為short類型,顯然是錯誤的。

          =================================

          給輸入輸出流添加緩沖功能的過濾流,叫做BufferedOutputStream out = new BufferedOutputStream(other outputstream);

          虛擬機中拿出一個塊區域當作緩沖區,把數據先寫入緩沖區,如果緩沖區滿了,再一次性將內容寫到磁盤。

          大大的減少了虛擬機快越邊界的操作,效率大幅度提高。是犧牲空間換時間的典型做法。

          任何帶緩沖的流,都會有一個flush()的方法,可以不管緩沖區滿不滿,都情空緩沖區。

          還有直接調用.close,也會自動調用.flush()方法。



          對于過濾流,只關閉最外層的流,即可。

          ===============================

          管道,節點流

          PipedOutputStream / PipedInputStream

          pos.connect(pis);

          用于給兩個線程交換數據。

          import java.io.*;
          public class PipedStreamTest
          {
              
          public static void main(String[] args)
              
          {
                  PipedOutputStream pos
          =new PipedOutputStream();
                  PipedInputStream pis
          =new PipedInputStream();
                  
          try
                  
          {
                      pos.connect(pis);
                      
          new Producer(pos).start();
                      
          new Consumer(pis).start();
                  }

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

                  
              }

          }


          class Producer extends Thread
          {
              
          private PipedOutputStream pos;
              
          public Producer(PipedOutputStream pos)
              
          {
                  
          this.pos=pos;
              }

              
          public void run()
              
          {
                  
          try
                  
          {
                      pos.write(
          "Hello,welcome you!".getBytes());
                      pos.close();
                  }

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

              }

          }


          class Consumer extends Thread
          {
              
          private PipedInputStream pis;
              
          public Consumer(PipedInputStream pis)
              
          {
                  
          this.pis=pis;
              }

              
          public void run()
              
          {
                  
          try
                  
          {
                      
          byte[] buf=new byte[100];
                      
          int len=pis.read(buf);
                      System.out.println(
          new String(buf,0,len));
                      pis.close();
                  }

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

              }

          }



          練習實現,文件拷貝功能,條件一個字節都能看,比如PDF,備份文件可以看,電影圖片都可以正常讀取。

          import java.io.*;
          public class TestFileCopy{
              
          public static void main(String[] args){
                  BufferedInputStream in
          =null;
                  BufferedOutputStream out
          =null;
                  
          try{
                      in
          =new BufferedInputStream(new FileInputStream(args[0]));
                      out
          =new BufferedOutputStream(new FileOutputStream(args[1]));
                      
          byte[] b=new byte[1024];
                      
          int len;
                      
          while((len=in.read(b))!=-1){
                          out.write(b,
          0,len);
                      }

                      out.flush();
                  }

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

                  
          finally{
                      
          if (in!=null){
                          
          try{
                              in.close();
                          }

                          
          catch(Exception e){}
                      }

                      
          if (out!=null){
                          
          try{
                              out.close();
                          }

                          
          catch(Exception e){}
                      }

                  }

                  
              }

          }

          注意,out.write(b,0,len);保證了最后一次,b沒有裝滿時,可以只寫裝入的數據。

          ==============================

          字符流

          java.io.Reader
          java.io.Writer

          單位為字符,一次一個字符,主要對于純文本。

          read(char[] cbuf)

          基本方法,參數為字符數組,而不是字節數組。一個字符2字節。

          FileReader,字符文件輸入流。

          那么一個字符有什么存在意義呢,

          'A'影射編碼成為整數65,而反過來,整數解碼成為'A'。如果編解碼不統一就會出現亂碼。

          ASCii,包括數字和字符,一個字節,256個字符

          這是最早的編碼,所以以后的任何編碼都兼容ASCii,所以英文總沒有問題。

          ISO-8859-1,一個字節 1B

          GB2312,國標,2B,65535,‘喆’就不這個字符集中,只有常用漢字。

          GBK,2B。包含所有漢字。

          UNICODE 2B

          UTF-8,不一定占用幾個字節。

          解決亂碼問題的宗旨,就是保證編碼解碼方式一致。

          ---------------------------

          java.io.InputStreamReader

          InputStreamReader(InputStream in)

          這是一個字符流,而構造函數參數是一個字節流。

          通常稱之為從字節六到字符流的橋轉換。

          InputStreamReader(InputStream in, String charsetName)

          第二個參數就是編碼方式參數,指對字節流按照什么解碼方式將文件讀入。

          OutputStreamWriter(OutputStream out, String charsetName)

          輸出是指按什么編碼方式輸出字節流。

          import java.io.*;

          public class TestReaderWriter{

              
          static void write() throws Exception
              
          {
                  FileOutputStream fos 
          = new FileOutputStream("test.dat");
                  OutputStreamWriter osw 
          = new OutputStreamWriter(fos,"UTF-8");
                  BufferedWriter out 
          = new BufferedWriter(osw);
                  
                  out.write(
          "慢慢爐火純青了!");
                  out.newLine();
                  out.write(
          "學完C++,Java確實很簡單,但很棒!");
                  out.flush();
              }


              
          static void read() throws Exception
              
          {
                  FileInputStream fis 
          = new FileInputStream("test.dat");
                  InputStreamReader isr 
          = new InputStreamReader(fis,"UTF-8");
                  BufferedReader in 
          = new BufferedReader(isr);
                  
                  String line;
                  
          while((line = in.readLine())!=null)
                  
          {
                      System.out.println(line);
                  }

              }


              
          public static void main(String[] args) throws Exception
              
          {
                  write();
                  read();    
                  System.out.println(System.getProperty(
          "file.encoding"));
              }


          }

          PrintWriter,也是一個帶緩沖的字符輸出流,可以直接由一個OutputStream或者Writer構造,但功能更強大,也就是方法更多。

          PrintWriter(OutputStream out, boolean autoFlush)

          PrintWriter(Writer out, boolean autoFlush)


          println(String x)

          PrintStream,也是同理,帶緩沖的字節輸出流,功能比BufferedOutputStream更強。

          ==========================================

          java.io.ObjectOutputStream 過濾流

          輸出一個對象,是對DataOutputStream的增強。

          writeObject(Object obj)

          對象序列化,對象需要實現Serializable接口,這個接口是一個標記接口。

          由于對象有價值的東西就是屬性,所以只關系對象的屬性文件,如果某個屬性沒有序列化的意義,那么就用transient修飾,表示不持久化該屬性。

          恢復時,為默認屬性。

          要求屬性也是Serializable的。

          用命令serialver判斷一個類是否可以序列化。

          =====================================

          早期持久化,就是通過文件存儲信息,通過定義特定分割符分開信息。

          StringTokenizer st = new StringTokenizer(s,"t");
          while(st.hasMoreTokens()){
             System.out.println();
          }

          ======================================

          void open{
             BufferedReader in = null;
             try{
                FileInputStream fis = new FileInputStream("data");
                InputStreamReader ir = new InputStreamReader(fis);
                in = new BufferedReader(ir);
             }catch(Exception e)
             {
                
             }
             finally{
                if(in!=null)
                   try{
                         in.close();
                   }catch(Exception){}
             }
          }



          posted on 2005-12-25 00:08 北國狼人的BloG 閱讀(430) 評論(0)  編輯  收藏 所屬分類: 達內學習總結
          主站蜘蛛池模板: 桃园市| 中方县| 东乡| 黔东| 福清市| 江陵县| 八宿县| 格尔木市| 阿图什市| 雷山县| 永福县| 南乐县| 万安县| 定兴县| 盈江县| 洛宁县| 铁岭县| 寻甸| 莲花县| 镇雄县| 龙岩市| 腾冲县| 龙游县| 卓尼县| 锡林郭勒盟| 焉耆| 岱山县| 大厂| 古交市| 舞阳县| 得荣县| 盐山县| 白城市| 福鼎市| 姜堰市| 都昌县| 锡林郭勒盟| 胶州市| 霍邱县| 黄山市| 朝阳区|