java中的IO操做總結

一.InputStream重用技巧(利用ByteArrayOutputStream)html

對同一個InputStream對象進行使用屢次。java

好比,客戶端從服務器獲取數據 ,利用HttpURLConnection的getInputStream()方法得到Stream對象,這時既要把數據顯示到前臺(第一次讀取),又想把數據寫進文件緩存到本地(第二次讀取)。linux

但第一次讀取InputStream對象後,第二次再讀取時可能已經到Stream的結尾了(EOFException)或者Stream已經close掉了。android

而InputStream對象自己不能複製,由於它沒有實現Cloneable接口。此時,能夠先把InputStream轉化成ByteArrayOutputStream,後面要使用InputStream對象時,再從ByteArrayOutputStream轉化回來就行了。代碼實現以下:編程

InputStream input = httpconn.getInputStream(); 
//字節數組輸出流 ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; //遍歷讀取字節 while ((len = input.read(buffer)) > -1 ) { baos.write(buffer, 0, len); } //通知字節讀取即將關閉 baos.flush(); //獲取內存緩存的字節數組 byte[] byteArray = baos.toByteArray(); //顯示到前臺 InputStream stream1 = new ByteArrayInputStream(byteArray); //本地緩存 InputStream stream2 = new ByteArrayInputStream(byteArray);

2.流轉化爲字符串windows

          FileInputStream in = null;
		StringBuilder sb = new StringBuilder();
		
	    try {
			in = new FileInputStream(new File("D:/新版帳戶流程20150518.bpmn20.xml"));
			
			byte[] buff = new byte[1024];
			int len = 0;
			while((len = in.read(buff, 0, 1024)) != -1){
			       sb.append(new String(buff, 0, len));
			}
			System.out.println(sb.toString());
		
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(in != null){
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

二.IO操做數組

所謂IO,也就是Input與Output的縮寫。在java中,IO涉及的範圍比較大,這裏主要討論針對文件內容的讀寫緩存

其餘知識點將放置後續章節(我想,文章太長了,誰都沒耐心翻到最後)服務器

 

對於文件內容的操做主要分爲兩大類app

分別是:

  字符流

  字節流

其中,字符流有兩個抽象類:Writer   Reader

其對應子類FileWriterFileReader可實現文件的讀寫操做

BufferedWriterBufferedReader可以提供緩衝區功能,用以提升效率

 

一樣,字節流也有兩個抽象類:InputStream   OutputStream

其對應子類有FileInputStreamFileOutputStream實現文件讀寫

BufferedInputStreamBufferedOutputStream提供緩衝區功能

 

俺當初學IO的時候犯了很多迷糊,網上有些代碼也沒法經過編譯,甚至風格都很大不一樣,因此新手請注意:       

        1.本文代碼較長,不應省略的都沒省略,主要是由於做爲一個新手須要養成良好的代碼編寫習慣

   2.本文在linux下編譯,相似於File.pathSeparator和File.separator這種表示方法是出於跨平臺性和健壯性考慮

   3.代碼中有些操做有多種執行方式,我採用了方式1...方式2...的表述,只需輕輕解開註釋即可編譯

   4.代碼中並無在主方法上拋出異常,而是分別捕捉,形成代碼過長,若是僅是測試,或者不想有好的編程習慣,那你就隨便拋吧……

        5.功能相似的地方就沒有重複寫註釋了,若是新手看不懂下面的代碼,那確定是上面的沒有理解清楚

 

字符流

實例1:字符流的寫入

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
 
public class Demo {
    public static void main(String[] args ) {
         
        //建立要操做的文件路徑和名稱
        //其中,File.separator表示系統相關的分隔符,Linux下爲:/  Windows下爲:\\
        String path = File.separator + "home" + File.separator + "siu" +
                      File.separator + "work" + File.separator + "demo.txt";
     
        //因爲IO操做會拋出異常,所以在try語句塊的外部定義FileWriter的引用
        FileWriter w = null;
        try {
            //以path爲路徑建立一個新的FileWriter對象
            //若是須要追加數據,而不是覆蓋,則使用FileWriter(path,true)構造方法
            w = new FileWriter(path);
             
            //將字符串寫入到流中,\r\n表示換行想有好的
            w.write("Nerxious is a good boy\r\n");
            //若是想立刻看到寫入效果,則須要調用w.flush()方法
            w.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //若是前面發生異常,那麼是沒法產生w對象的
            //所以要作出判斷,以避免發生空指針異常
            if(w != null) {
                try {
                    //關閉流資源,須要再次捕捉異常
                    w.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

編譯以後,在目錄下面生成文件,並寫入字符串

實例2:字符流的讀取

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
 
public class Demo2 {
    public static void main(String[] args ) {
        String path = File.separator + "home" + File.separator + "siu" +
                      File.separator + "work" + File.separator + "demo.txt";
 
        FileReader r = null;
        try {
            r = new FileReader(path);
             
            //方式一:讀取單個字符的方式
            //每讀取一次,向下移動一個字符單位
            int temp1 = r.read();
            System.out.println((char)temp1);
            int temp2 = r.read();
            System.out.println((char)temp2);
                         
            //方式二:循環讀取
            //read()方法讀到文件末尾會返回-1
            /*
            while (true) {
                int temp = r.read();
                if (temp == -1) {
                    break;
                }
                System.out.print((char)temp);
            }
            */
             
            //方式三:循環讀取的簡化操做
            //單個字符讀取,當temp不等於-1的時候打印字符
            /*int temp = 0;
            while ((temp = r.read()) != -1) {
                System.out.print((char)temp);
            }
            */
             
            //方式四:讀入到字符數組
            /*
            char[] buf = new char[1024];
            int temp = r.read(buf);
            //將數組轉化爲字符串打印,後面參數的意思是
            //若是字符數組未滿,轉化成字符串打印後尾部也許會出現其餘字符
            //所以,讀取的字符有多少個,就轉化多少爲字符串
            System.out.println(new String(buf,0,temp));
            */
             
            //方式五:讀入到字符數組的優化
            //因爲有時候文件太大,沒法肯定須要定義的數組大小
            //所以通常定義數組長度爲1024,採用循環的方式讀入
            /*
            char[] buf = new char[1024];
            int temp = 0;
            while((temp = r.read(buf)) != -1) {
                System.out.print(new String(buf,0,temp));
            }
            */
             
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(r != null) {
                try {
                    r.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

編譯以後的效果:

實例3:文本文件的複製

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
 
public class Demo {
    public static void main(String[] args ) {
         
        String doc = File.separator + "home" + File.separator + "siu" +
                      File.separator + "work" + File.separator + "demo.txt";
         
        String copy = File.separator + "home" + File.separator + "siu" +
                     File.separator + "life" + File.separator + "lrc.txt";
 
        FileReader r = null;
        FileWriter w = null;
        try {
            r = new FileReader(doc);
            w = new FileWriter(copy);
             
            //方式一:單個字符寫入
            int temp = 0;
            while((temp = r.read()) != -1) {
                w.write(temp);
            }
             
            //方式二:字符數組方式寫入
            /*
            char[] buf = new char[1024];
            int temp = 0;
            while ((temp = r.read(buf)) != -1) {
                w.write(new String(buf,0,temp));
            }
            */
             
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //分別判斷是否空指針引用,而後關閉流
            if(r != null) {
                try {
                    r.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(w != null) {
                try {
                    w.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 編譯以後,產生life目錄下的lrc.txt文件,複製成功

實例4:利用字符流的緩衝區來進行文本文件的複製

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
 
public class Demo {
    public static void main(String[] args ) {
         
        String doc = File.separator + "home" + File.separator + "siu" +
                      File.separator + "work" + File.separator + "demo.txt";
         
        String copy = File.separator + "home" + File.separator + "siu" +
                     File.separator + "life" + File.separator + "lrc.txt";
 
        FileReader r = null;
        FileWriter w = null;
        //建立緩衝區的引用
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            r = new FileReader(doc);
            w = new FileWriter(copy);
            //建立緩衝區對象
            //將須要提升效率的FileReader和FileWriter對象放入其構造函數內
            //固然,也可使用匿名對象的方式 br = new BufferedReader(new FileReader(doc));
            br = new BufferedReader(r);
            bw = new BufferedWriter(w);
             
            String line = null;
            //讀取行,直到返回null
            //readLine()方法只返回換行符以前的數據
            while((line = br.readLine()) != null) {
                //使用BufferWriter對象的寫入方法
                bw.write(line);
                //寫完文件內容以後換行
                //newLine()方法依據平臺而定
                //windows下的換行是\r\n
                //Linux下則是\n
                bw.newLine();
            }      
             
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //此處再也不須要捕捉FileReader和FileWriter對象的異常
            //關閉緩衝區就是關閉緩衝區中的流對象
            if(br != null) {
                try {
                    r.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(bw != null) {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

字節流

實例5:字節流的寫入

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class Demo {
    public static void main(String[] args ) {
          
        String path = File.separator + "home" + File.separator + "siu" +
                      File.separator + "work" + File.separator + "demo.txt";
         
        FileOutputStream o = null;
         
        try {
            o = new FileOutputStream(path);
            String str = "Nerxious is a good boy\r\n";
            byte[] buf = str.getBytes();
            //也能夠直接使用o.write("String".getBytes());
            //由於字符串就是一個對象,能直接調用方法
            o.write(buf);
             
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(o != null) {
                try {
                    o.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
    }
}

編譯以後產生的文件,以上在字符串中加\r\n就是爲了便於終端顯示

其實在linux下面換行僅用\n便可

實例6:字節流的讀取

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
 
public class Demo {
    public static void main(String[] args ) {
          
        String path = File.separator + "home" + File.separator + "siu" +
                      File.separator + "work" + File.separator + "demo.txt";
         
        FileInputStream i = null;
         
        try {
            i = new FileInputStream(path);
             
            //方式一:單個字符讀取
            //須要注意的是,此處我用英文文本測試效果良好
            //但中文就悲劇了,不過下面兩個方法效果良好
            int ch = 0;
            while((ch=i.read()) != -1){
                System.out.print((char)ch);
            }
             
            //方式二:數組循環讀取
            /*
            byte[] buf = new byte[1024];
            int len = 0;
            while((len = i.read(buf)) != -1) {
                System.out.println(new String(buf,0,len));
            }
            */
             
             
            //方式三:標準大小的數組讀取
            /*
            //定一個一個恰好大小的數組
            //available()方法返回文件的字節數
            //可是,若是文件過大,內存溢出,那就悲劇了
            //因此,親們要慎用!!!上面那個方法就不錯
            byte[] buf = new byte[i.available()];
            i.read(buf);
            //由於數組大小恰好,因此轉換爲字符串時無需在構造函數中設置起始點
            System.out.println(new String(buf));
            */
             
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(i != null) {
                try {
                    i.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
    }
}

讀取文件到終端

實例7:二進制文件的複製

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class Demo {
    public static void main(String[] args ) {
          
        String bin = File.separator + "home" + File.separator + "siu" +
                      File.separator + "work" + File.separator + "一我的生活.mp3";
         
        String copy = File.separator + "home" + File.separator + "siu" +
                      File.separator + "life" + File.separator + "一我的生活.mp3";
         
        FileInputStream i = null;
        FileOutputStream o = null;
         
        try {
            i = new FileInputStream(bin);
            o = new FileOutputStream(copy);
             
            //循環的方式讀入寫出文件,從而完成複製
            byte[] buf = new byte[1024];
            int temp = 0;
            while((temp = i.read(buf)) != -1) {
                o.write(buf, 0, temp);
            }
 
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(i != null) {
                try {
                    i.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(o != null) {
                try {
                    o.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

複製效果,如圖:

 實例8:利用字節流的緩衝區進行二進制文件的複製

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
 
public class Demo {
    public static void main(String[] args ) {
          
        String bin = File.separator + "home" + File.separator + "siu" +
                      File.separator + "work" + File.separator + "一我的生活.mp3";
         
        String copy = File.separator + "home" + File.separator + "siu" +
                      File.separator + "life" + File.separator + "一我的生活.mp3";
         
        FileInputStream i = null;
        FileOutputStream o = null;
        BufferedInputStream bi = null;
        BufferedOutputStream bo = null;
         
        try {
            i = new FileInputStream(bin);
            o = new FileOutputStream(copy);
            bi = new BufferedInputStream(i);
            bo = new BufferedOutputStream(o);
             
            byte[] buf = new byte[1024];
            int temp = 0;
            while((temp = bi.read(buf)) != -1) {
                bo.write(buf,0,temp);
            }
             
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(bi != null) {
                try {
                    i.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(bo != null) {
                try {
                    o.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 兩個目錄都有 「一我的生活.mp3」文件,順便說一下,這歌挺好聽的

初學者在學會使用字符流和字節流以後未免會產生疑問:何時該使用字符流,何時又該使用字節流呢?

其實仔細想一想就應該知道,所謂字符流,確定是用於操做相似文本文件或者帶有字符文件的場合比較多

而字節流則是操做那些沒法直接獲取文本信息的二進制文件,好比圖片,mp3,視頻文件等

說白了在硬盤上都是以字節存儲的,只不過字符流在操做文本上面更方便一點而已

此外,爲何要利用緩衝區呢?

咱們知道,像迅雷等下載軟件都有個緩存的功能,硬盤自己也有緩衝區

試想一下,若是一有數據,不論大小就開始讀寫,勢必會給硬盤形成很大負擔,它會感受很不爽

人不也同樣,一頓飯不讓你一次吃完,每分鐘喂一勺,你怎麼想?

所以,採用緩衝區可以在讀寫大文件的時候有效提升效率

相關文章
相關標籤/搜索