1. 程式人生 > >java關於流的學習筆記大全,包含全部流的概念及用法

java關於流的學習筆記大全,包含全部流的概念及用法

        2.資料型別不同分
位元組流:流中的資料以位元組為單位流動   InputStream     OutputStream
    InputStream  位元組輸入流  從磁碟到記憶體     FileInputStream
   根據記憶體大小做一個位元組陣列  byte[] arr = new byte[fis.available()];//弊端                                有可能會造成記憶體溢位
OutputStream    位元組輸出流  從記憶體到磁碟      FileOutputStream位元組緩衝區
BufferedInputStream(InputStream in)
BufferedInputStream會一次性從檔案中讀取8192個 存在緩衝區中,返回給程式一個
程式再次讀取的時候 就不用找檔案了 直接從緩衝區中獲取
         BufferedOutputStream(OutputStream in)   BufferedOutputStream程式向流中寫出位元組時,不會直接寫到檔案中,先寫到緩衝區中直到緩衝區裝滿 才會把緩衝區中的資料異型性寫到檔案裡位元組流一次讀寫一個數組的速度明顯比一次讀一個位元組速度快
java本身在設計的時候 就加入了這樣的功能 就是緩衝區陣列的讀寫和帶Buffered的讀寫
如果陣列定義8192個位元組大小和Buffered比較的話    陣列會好一些  因為陣列讀和寫  操作的都是同一個陣列  而Buffered操作的是兩個陣列
字元流

流中的資料以字元為單位流動    Reader  Writer
可以讀寫字元的IO流    底層也是位元組流   國際編碼表 ---UTF-8                                 Writer     ------> FileWriter
Reader    ------>FileReader
字元流緩衝區
作用
BufferedReader            BufferedWriter
            緩衝區的出現提高了對資料的讀寫效率
緩衝區要結合流才可以使用在流的基礎上 對流的功能進行了增強
使用情況
文字檔案 讀取一段文字 或者是寫出一段文字不可以拷貝非純文字檔案
因為在讀的時候 會將位元組轉換成字元 在轉換的過程中 可能找不到對應的字元
就會用?替代 寫出的時候 將字元轉換成位元組寫出 如果是? 直接寫出 這樣寫出之後的檔案就亂了
轉換流

Reader 類 
位元組轉字元 輸入流 InputStreamReader 是位元組流通向字元流的橋樑:
InputStreamReader(InputStream in) 建立一個使用預設字符集的InputStreamReader
InputStreamReader(InputStream in, Charset cs) 建立使用給定字符集的InputStreamReader
InputStreamReader(InputStream in, String charsetName) 建立使用指定字符集的InputStreamReader
Writer 類 
Writer 類 位元組轉字元 輸出流 OutputStreamWriter 是位元組流通向字元流的橋樑
OutputStreamWriter(OutputStream out) 建立使用預設字元編碼的OutputStreamWriter
OutputStreamWriter(OutputStream in, Charset cs) 建立使用給定字符集的OutputStreamWriter
OutputStreamWriter(OutputStream in, String charsetName) 建立使用指定字符集的OutputStreamWriter
IO的種類
流向分
輸入流

從磁碟等物理介質到當前記憶體中    InputStream(位元組流)     Reader(字元流)
輸出流
將程式處理好的資料從記憶體中輸出到磁碟等儲存介質中     OutputSteam(位元組流)       Writer(字元流)
資料型別不同分
位元組流
流中的資料以位元組為單位流動   InputStream     OutputStream
InputStream  位元組輸入流  從磁碟到記憶體     FileInputStream
根據記憶體大小做一個位元組陣列  byte[] arr = new byte[fis.available()];//弊端 有可能會造成記憶體溢位
OutputStream    位元組輸出流  從記憶體到磁碟       FileOutputStream
位元組緩衝區
BufferedInputStream(InputStream in)  BufferedInputStream會一次性從檔案中讀取8192個 存在緩衝區中,返回給程式一個
程式再次讀取的時候 就不用找檔案了 直接從緩衝區中獲取
BufferedOutputStream(OutputStream in)
BufferedOutputStream程式向流中寫出位元組時,不會直接寫到檔案中,先寫到緩衝區中直到緩衝區裝滿 才會把緩衝區中的資料異型性寫到檔案裡位元組流一次讀寫一個數組的速度明顯比一次讀一個位元組速度快java本身在設計的時候 就加入了這樣的功能 就是緩衝區陣列的讀寫和帶Buffered的讀寫,如果陣列定義8192個位元組大小和Buffered比較的話    陣列會好一些  因為陣列讀和寫  操作的都是同一個陣列  而Buffered操作的是兩個陣列
字元流
流中的資料以字元為單位流動    Reader  Writer
可以讀寫字元的IO流    底層也是位元組流   國際編碼表 ---UTF-8                                 Writer     ------> FileWriter
Reader    ------>FileReader
字元流緩衝區
作用
BufferedReader
BufferedWriter
緩衝區的出現提高了對資料的讀寫效率
緩衝區要結合流才可以使用
在流的基礎上 對流的功能進行了增強
使用情況
文字檔案 讀取一段文字 或者是寫出一段文字
不可以拷貝非純文字檔案
因為在讀的時候 會將位元組轉換成字元 在轉換的過程中 可能找不到對應的字元
就會用?替代 寫出的時候 將字元轉換成位元組寫出 如果是? 直接寫出 這樣寫出之後的檔案就亂了
轉換流
Reader 類 
位元組轉字元 輸入流 InputStreamReader 是位元組流通向字元流的橋樑:
InputStreamReader(InputStream in) 建立一個使用預設字符集的InputStreamReader
InputStreamReader(InputStream in, Charset cs) 建立使用給定字符集的InputStreamReader
InputStreamReader(InputStream in, String charsetName) 建立使用指定字符集的InputStreamReader
Writer 類 
Writer 類 位元組轉字元 輸出流 OutputStreamWriter 是位元組流通向字元流的橋樑
OutputStreamWriter(OutputStream out) 建立使用預設字元編碼的OutputStreamWriter
OutputStreamWriter(OutputStream in, Charset cs) 建立使用給定字符集的OutputStreamWriter
OutputStreamWriter(OutputStream in, String charsetName) 建立使用指定字符集的OutputStreamWriter
其他流
列印流
PrintStream(位元組列印流)
建構函式接收的引數型別
1、file物件   2.字串路徑   3.位元組輸出流   OutputStream PrintWriter(字元列印流)
在wed階段 
用來將資料打到客戶端  讓客戶端對他解析執行   B/S(從網頁到伺服器)   C/S(從客戶端到網頁)
建構函式接收型別
1.File物件     2.字串路徑    3.位元組輸出流(OutputStream)   4.字元輸出流(Writer)
該流提供了列印方法  可以對基本資料型別進行直接操作  可以保持資料的原樣性  打印出去  此類中不會丟擲I/O異常
使用範例
PrintWriter writer= new PrintWriter(new FileWriter("f:\\aaa\\reade.txt"),true);
標準輸入輸出流
System.in
System.in是InputStream標準輸入流  預設可以從鍵盤輸入讀取位元組資料
System.out
System.out是PrintStream 標準輸出流 預設可以向控制檯中輸出字元或位元組資料
用法例項
System.setIn(new FileInputStream(file));
System.setOut(new PrintStream("f:\\aaa\\yy.txt"));
InputStream in=System.in;
                                                PrintStream xx=System.out;
   修改標準輸入輸出流  1.System.setIn(InputStream)        2.System.setOut(PrintStream)    修改標準輸入輸出流的員的 源 地和 目的地 這樣可以實現拷貝的功能
序列流
概念:
序列流可以把多個位元組輸入流合成一個流   從序列流中讀取資料時 將被整合的第一個流開始讀 ,讀完一個再讀下一個 以此類推  把最後一個小流的-1做為大流的結束
SequenceInputStream( InputStream  s1,InputStream  s2)  將多個源合併   SequenceInputStream( Enumeration< ?   extends  InputStream>   e )
用法例項
多分一  1、兩張圖片和為一張      2、多個檔案的內容填到一個檔案中
FileInputStream stream=new FileInputStream("f:\\aaa\\11.jpg");
FileInputStream stream2=new FileInputStream("f:\\aaa\\22.jpg");
SequenceInputStream stream3=new SequenceInputStream(stream, stream2);
FileOutputStream wStream=new FileOutputStream("f:\\aaa\\33.png");
  int b;
  while ((b=stream3.read())!=-1) {
wStream.write(b);
}
Vector<FileInputStream> vector=new Vector<FileInputStream>();
try {
vector.add(new FileInputStream("f:\\aaa\\11.txt"));
vector.add(new FileInputStream("f:\\aaa\\22.txt"));
 Enumeration<FileInputStream> en=vector.elements();
 SequenceInputStream seq=new SequenceInputStream(en);
 FileOutputStream outputStream=new FileOutputStream("f:\\aaa\\55.txt");
  byte[] by=new byte[1024];
  int i=0;
  while ((i=seq.read(by))!=-1) {
  outputStream.write(by,0,i);
}
將一個檔案按照大小分
try {
  FileInputStream stream=new FileInputStream("f:\\aaa\\11.mp3");
  FileOutputStream out=null; 
  byte[] by=new byte[1024*1024];
  int len=0;
  int cunt=1;
  while ((len=stream.read(by))!=-1) {
  out=new FileOutputStream("f:\\aaa\\"+(cunt++)+".mp3");
  out.write(by,0,len);
  out.close();
物件操作流
概念
該流可以將一個物件寫出或者讀取一個物件到程式中 也就是執行了序列化和反序列化的操作   1.ObjectInputStream          2.ObjectOutputStream
Serializable     ( 是一個藉口  用implements實現   public static final long serialVersionUID = 42L; )
這種介面  沒有方法  給類載入一  serialVersionUID 號  就證明你的類具備了序列化(持久化) ---->找一個介質 長期儲存資料        物件儲存在堆記憶體中  相要將物件儲存在物理介質中  ------>物件的序列化/持久化(資料隨著物件存入到硬碟上  如果下次想要使用  只要讀取該檔案 就可以再次使用)     序列化是將堆記憶體中的資料序列號  被static修飾的成員 無法序列化
transient    (transient String sex;)  想存放在堆記憶體中 不想要序列化 也不想是靜態
當類實現了Serializable介面  那麼類中屬性就是預設能被序列化的  為了讓某些資料既能使用 有不被序列化  用一次就消亡  就可以使用當前關鍵字
1.一旦被transient修飾  變數將不再是物件序列化的一部分  該變數內容在序列化後 無法獲得訪問        2.transient 關鍵字只能修飾的變數  不能修飾方法和類     3.被transient關鍵字修飾的變數不在被序列化  和static修飾的一樣  但是在記憶體中儲存區域不一樣  不可混淆  被static 修飾的變數也不能被序列化的
注意事項
ObjectInputStream和ObjectOutputStream所讀寫的物件  必須實現Serializable 介面
物件中被static或者transient修飾的成員變數 不能被序列化  自己寫serialVersionUID 號
資料輸入輸出流
DataInputStream       DataOutputStream
可以按照基本資料型別大小讀寫資料   例:按Long 大小寫出一個數字  寫出時該資料佔8個位元組  讀取的時候也可以按照Long來讀取  一次讀8個    僅是了操作基本資料型別是流  和資料相結合的功能  分別儲存對應的位元組數
建構函式
DataOutputStream(OutputStream  out)     void   write(int   b)                  1int =4byte=32bit  將指定位元組寫入基礎輸出流(8個低位)
void  writeUTF( String  str )
以與機器無關方式使用UTF-8修改版編碼將一個字串寫入基礎輸出流    gbk 一箇中文2位元組     utf-8一箇中文3個位元組   writeUTF  一箇中文4個位元組
DataOutputStream dos = new DataOutputStream
(new FileOutputStream("writeUTF.txt"));
dos.writeUTF("你好");
dos.close();
  }
public static void readUTFDemo() throws IOException{
DataInputStream dis = new DataInputStream(
new FileInputStream("writeUTF.txt"));
String s = dis.readUTF();
System.out.println(s);
記憶體流ByteArrayStream
可以直接操作位元組陣列中資料的流向         該輸出流可以向記憶體中寫資料  把記憶體當做一個緩衝區  寫出之後可以一次性獲取出所有資料
ByteArrayInputStream
在構造的時候  需要接收資料來源  而且資料來源是一個位元組陣列
ByteArrayOutputStream
在構造的時候  不用定義資料的目的地  因為該物件中已經內部封裝了可變長度的位元組陣列  這就是目的地    因為兩個流都操作的是陣列  並沒有使用系統資源  使用不用close關閉
使用方法
ByteArrayInputStream(byte[] buf) 
ByteArrayOutputStream() 
//寫出到檔案中
bos.writeTo(new FileOutputStream("x.txt"));
//將記憶體緩衝區中所有的位元組儲存到陣列中
byte[] newArr = bos.toByteArray();
RandomAccessFile
概念
在Java io包中   類RandomAccessFile不屬於流 是Object的子類   但是它融合了InputStream和OutputStream的功能     支援對隨機訪問檔案的讀取和寫入  這個物件內部封裝了一個byte陣列 可以通過指標對陣列元素進行操作    可以通過getFilePointer 方法獲取指標位置       seek方法  改變指標的位置
建構函式
public  RandomAccessFile(File   file,String   mode)   mode 引數指定用以開啟檔案的訪問模式       值:“r” 以只讀方式開啟,呼叫結果物件的任何write方法都將導致丟擲IOException.     “ew”  開啟以便讀取和寫入。如果該檔案尚不存在  則嘗試建立該檔案。             “rws” 開啟以便讀取和寫入,對於“rw”,還要求以便讀取和寫入到底層儲存裝置。      “rwd” 開啟以便讀取和寫入  對於“rw” 還要求對檔案內容的每個更新都同步寫入到底層儲存裝置
使用
void seek(long pos) 
例如:有一個檔案 這個流可以分段寫入資料
我們用一個執行緒負責檔案的其中一段 多執行緒可以同時向檔案中寫入內容
互不衝突 這就是多執行緒下載
如果用其他的流 都是從頭向後寫 那麼第一個執行緒寫個資料 第二個執行緒接著寫另一個數據
以此類推 雖然資料存完了 但是 這樣會導致讀出來的都是錯誤的 不是完整的檔案 解碼錯誤
io中 只有這個可以實現多執行緒下載 seek方法