Java-IO 輸入輸出流詳解


一、文件的編碼

              開發時一定要注意項目默認的編碼!!!!!!!!
              文件操作的時候一定要記得關閉!!!!!!!!
       ASCII:美國標准信息交換碼,用一個字節的7位可以表示一個字符
       ISO8859-1:拉丁碼表,西歐標准字符集,用一個字節的8位表示
       GB2312:中文編碼表,用兩個字節來表示中文編碼
       GBK:中文編碼表的升級,融合了更多表示中文文字符號
       GB18030:GBK的取代版本
       BIG-5:同行與港台地區,是繁體字編碼方案,俗稱“大五碼”
       Uicode:國際標准碼,融合了多種文字
       UTF-8:是Unicode編碼的實現方式,最多用三個字節來表示一個字符
    
       GBK編碼     中文占用2個字節,英文占用1個字節
       UTF-8編碼   中文占用3個字節,英文占用1個字節
       UTF-16be編碼中文占用2個字節,英文占用2個字節
       Java是雙字節編碼 utf-16be,即java中每個字符占用兩個字節
       
       當你想把一個字節序列變成一個字符串時,字節序列使用什么編碼,就需要使用什么編碼去顯示的調用s.getBytes("字節序列的編碼格式");,否則會出現亂碼
 
       文本文件就是字節序列,可以是任意編碼的字節序列,但是如果是在中文機器上直接創建文本文件,那么該文本文件只認識ANSI(本地編碼)編碼。如,新建一個TXT文件,內容為聯通,打開則會出現亂碼,是一種巧合,正好符合了UTF-8編碼的規則
   
       Integer.toHexString(Byte);//以十六進制的方式顯示
二、File工具類的使用
         1、File類用於表示文件和目錄都可以
            File類只用於表示文件(目錄)的信息(名稱、大小等),不能用於文件內容的訪問
         2、File類的基本API(看手冊)
                 構造函數的情況
                創建功能:createNewFile(),mkdir(),mkdirs()
                刪除功能:delete()
                重命名功能:renameTo()
                判斷功能:isFile(),isDirectory(),exists()等
                獲取功能:getName(),getPath(),list()等
                文件過濾器的作用:list(FilenameFilter filter),返回滿足指定條件的文件列表
                
            判斷參數的時候,可以使用 IllegalArgumentException參數拋出異常
            File.separator設置目錄分隔符,Windows、Unix都識別
            相對目錄是當前目錄,也即在項目的根目錄下
         3、遍歷目錄(遞歸 dir.listFiles())
            訪問文件系統的時候因為是與JVM以外的資源進行交互,所以,寫代碼一定要嚴謹,把各種情況考慮到了
             
三、RandomAccessFile類的使用
       1、 RandomAccessFile  java提供的對文件內容的訪問,既可以讀,也可以寫
          且支持隨機訪問文件,可以訪問文件的任意位置
       2、Java文件模型
             在硬盤上的文件是byte byte byte存儲的,是數據的集合
       3、打開文件  
1 RandomAccessFile raf =newRandomAccessFile(file,"rw");//rw,讀寫,r只讀
2 //打開文件時,文件指針在開頭,pointer = 0;
3 raf.write(byte);//write方法只會寫一個字節,同時直接指針指向下一個位置
4 int b = raf.read();//每次讀一個字節,java中每個字符占用兩個字節,使用右移8位的方式分次寫入
5 raf.seek(指針位置);//移動指針
6 raf.close();//文件讀寫完一定要關閉,否則可能會有意想不到的后果
在文件下載文件的時候,這種方式有很大的好處,每個線程下載文件的一部分,
          然后再拼接在一起,迅雷就是使用的這種方式,會記錄指針的位置
 
四、字節流(InputStream、OutputStream,兩個都是抽象類)
         1、I/O流用來處理設備之間的數據傳輸
            InputStream抽象了應用程序讀取數據的方式
             OutputStream抽象了應用程序寫出數據的方式
         2、EOF = End  讀到 -1 就讀到結尾
         3、輸入流的基本方式主要是讀
              int b = in.read();//讀取一個字節無符號填充到int第八位,-1是EOF
              in.read(byte[] buf);//讀入多個字節填充的字節數組
         4、輸出流的基本方式主要是寫
              out.write(int b);
              out.write(byte[] buf);
         5、FileInputStream具體實現了文件的讀取操作
                while((b=in.read())!=-1){讀一個文件}
                in.close();//一定要記得關閉流釋放系統資源
                批量讀取(速度非常快,效率高) vs. 單字節讀取(不適合讀大文件,效率很低)
          6、FileOutputStream具體實現了向文件中寫數據的操作
                是刪除文件重新創建,還是在原文件上追加內容,看構造方法
                自己實現文件的copy操作
                out.flush();
                out.close();
          7、數據輸入輸出流DataOutputStream/DataInputStream
                對流功能的擴展,是一個包裝類,可以更加方便的讀取int,long,字符等類型數據,本質是使用的一種裝飾模式實現的
         8、字節緩沖流BufferedInputStream/BufferedOutputStream
                 為I/O提供了帶緩沖區的操作,這種流模式提高了I/O的性能     
                 .write();
                 .flush();//刷新緩沖區,否則寫入不到文件中
                 .close();
 
五、字符流(參考API)
       1、Java為什么引入字符流?
             操作文本時,尤其是包含中文字符等非ASCII碼的字符會很不方便
             字符流 = 字節流+編碼
             所以,要對編碼問題非常清楚    
       2、java的文本(char)是16位無符號整數,是字符的Unicode編碼(雙字節)    
          文件是byte byte byte……的數據序列
          文本文件是文本序列按照某種編碼方式序列化為byte的存儲
       3、字符流(Reader Writer)操作的是文本文件
          一次處理一個字符,字符的底層仍然是基本的字節序列
          InputStreamReader 完成byte流按照編碼解析為char流
          OutputStreamWriter 提供char流按照編碼解析成byte流
       4、文件讀寫流  FileReader、FileWriter
             沒法設置編碼,必須回到字符流設置編碼
       5、字符流的過濾器BufferedReader、BufferedWriter、PrintWriter
             readLine  可以一次讀一行,一次寫一行
             可以設置編碼,不識別換行,單獨寫出換行操作
 
六、對象的序列化和反序列化
         1、將Object對象轉換成byte序列,反之叫對象的反序列化
         2、序列化流(ObjectOutputStream),是過濾流---writeObject()
            反序列化流(ObjectInputStream),    ----readObject
         3、序列化接口(Serializable)
            對象必須實現序列化接口,才能進行序列化,否則將出現異常
            這個接口沒有任何方法,只是一個標准,是標記接口
            
            對象序列化后,如果對再次對類文件修改,那么反序列化的時候就會出問題,那么怎么解決呢?
            需要在類中設置序列版本id,唯一標記,這樣無論怎么修改讀取的時候都不會再有問題   serialVersionUID

 

 
         4、transient關鍵字
               聲明的元素不會進行JVM默認的序列化,也可以自己完成這個元素的序列化
               網絡中傳輸時,並不是所有的元素都是有必要傳輸的,尤其是要考慮節約網絡流量的時候
               在有些情況下,可以幫助我們提高性能(ArrayList在數組沒有放滿的時候,只把有效元素序列化)
         5、序列化中 子類和父類構造函數的調用問題
             父類實現了序列化接口,子類不需要再次實現,就能進行序列化    
             對子類對象進行反序列化操作時,如果其父類沒有顯示的實現序列化接口,那么其父類的構造函數會被調用
 
七、輸入輸出流的一些包裝類
       1、打印流
               PrintStream  :字節打印流
               PrintWriter  :字符打印流
               集成了Print()格式化輸出方法,可以操作任意類型的數據
       2、標准輸入輸出流
               System類的in、out字段
               默認輸入設備是鍵盤,輸出設備是顯示器
               
               標准IO重定向
               System.setIn(InputStream);
               //重定向輸出可以將打印到控制台的日志寫到文件
               System.setOut(PrintStream);
               System.err(PrintStream);
 
       3、進程控制
              在Java內部執行其他操作系統的程序,並要求控制這些程序的輸入輸出時
              向OSExecute.command()傳遞一個command字符串    
Process process = new ProcessBuilder(command.split(" ")).start();

OSExecute.command("javap test");

//javap是java的一個反編譯程序

八、IO操作過程中異常處理

        
       自己編程要用try-catch-finally包圍起來,如果有異常盡量處理,千萬不要僅僅是用printStackTrace()打印棧信息,在finally中進行流的關閉(判斷引用不為空的話關閉),以確保一定能得到執行


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM