1. 程式人生 > >IO流基礎

IO流基礎

IO流概述

    (1)用來處理裝置(硬碟,控制檯,記憶體)間的資料。
    (2)java中對資料的操作都是通過流的方式。
    (3)java用於操作流的類都在io包中。
    (4)按照流操作的資料的型別不同:分為位元組流和字元流。字元流是為了方便中文的操作而來的。    
    (5)按照流的流向不同分為:輸入流,輸出流

IO流常用基類

    (1)位元組流
        輸出位元組流:OutputStream:位元組寫入流抽象類
                |--->FileOutputStream:
                            位元組寫入流
                |--->BufferedOutputStream:
                            位元組寫入流緩衝區
                |--->PrintStream:
                            列印流
        輸入位元組流:InputStream:位元組讀取流抽象類
                |--->FileInputStream:
                            位元組讀取流
                |--->BufferedInputStream:
                            位元組讀取流緩衝區

IO流常見需求

****字元流:
    (1)需求1:在硬碟上建立一個檔案並寫入資訊
        用字元寫入流:FileWriter

FileWriter fw = new FileWriter("g:\\filewriter.txt");
fw.write("輸入資訊");
fw.write("也可以寫入字元陣列".toCharArray());
fw.flush();
fw.close();


    (2)需求2:在原有檔案上續寫資料

FileWriter fw = new FileWriter("g:\\filewriter.txt",true);
fw.write("還可以續寫資訊");
fw.write("也可以寫入字元陣列".toCharArray());
fw.flush();
fw.close();


    (3)需求3:讀取硬碟上的文字檔案,並將資料列印在控制檯

//**第一種讀取方法:只能讀取一個字元
try {
     FileReader fr = new FileReader("d:\\test.txt");
     int ch = 0;
     ch = fr.read();
     System.out.println((char)ch);
     fr.close();
} catch (IOException e) {
     e.printStackTrace();
 }
//**第二種讀取方法:利用陣列來提高效率
try {
      FileReader fr = new FileReader("d:\\test.txt");
      char[] buf = new char[1024];
      int len = 0;
      while((len = fr.read(buf))!=-1)
      {
         System.out.println(new String(buf,0,len));
      }
      fr.close();
} catch (IOException e) {
     e.printStackTrace();
}


    (4)需求4:拷貝文字檔案
        利用緩衝區提高資料讀寫效率
        (無緩衝區就相當於一滴一滴的喝水,有緩衝區就相當於一杯一杯的喝水)

       try {
           BufferedReader bufr = new BufferedReader(new FileReader("d:\\test.txt"));
           BufferedWriter bufw = new BufferedWriter(new FileWriter("d:\\test2.txt"));
           String line = null;
           while((line = bufr.readLine())!=null)
           {
               bufw.write(line);
               bufw.newLine();
               bufw.flush();  //重新整理此輸出流並強制寫出所有緩衝的輸出字元。
           }
           bufr.close();
           bufw.close();
       } catch (IOException e) {
           e.printStackTrace();
       }

****位元組流:位元組流寫入時沒有重新整理
    (1)需求1:在硬碟上建立一個檔案並寫入資訊(位元組流寫入時沒有重新整理)

        FileOutputStream fos = new FileOutputStream("g:\\filestream.txt");
        fos.write(97);//寫入一個位元組,int:97代表寫入char:a
        fos.write("也可以寫入位元組陣列".getBytes());//通常使用此種方式寫入,直觀!
        fos.close();


    (2)需求2:在硬碟已有檔案上續寫資料(位元組流寫入時沒有重新整理)

        FileOutputStream fos = new FileOutputStream("g:\\filestream.txt",true);
        fos.write("建立位元組寫入流時,傳進去一個true引數就可以繼續寫入資訊".getBytes());
        fos.close();    


    (3)需求3:讀取硬碟上的檔案

        FileInputStream fis = new FileInputStream("g:\\filestream.txt");
        //**第一種讀法:一個位元組一個位元組的讀(此種讀法慢)
        int ch = 0;
        while((ch = fis.read())!=-1)
        {
            System.out.println(char)ch);
        }


        **第一種讀法:利用位元組陣列讀(此種讀法效率有一定提高)

        byte[] buf = new byte[1024];
        int len = 0;
        while((len = fis.read())!=-1)
        {
            System.out.println(new String(buf,0,len));
        }


    (4)需求4:拷貝位元組檔案,如圖片或者MP3或者電影
        **第一種拷貝:不帶緩衝區(慢,還是效率問題)

        FileInputStream fis = new FileInputStream("g:\\1.mp3");
        FileOutputStream fos = new FileOutputStream("g:\\copy1.mp3");
        byte[] buf = new byte[1024];
        int len = 0;
        while((len = fis.read(buf))!=-1)
        {
            System.out.priintln(buf,0,len);//位元組流寫入無需重新整理
        }
        fis.close();
        fos.close();


        **第二種拷貝:帶緩衝區,高效
 

BufferedInputStream bufi = new BufferedInputStream(new FileInputStream("g:\\1.mp3"));
BufferedOutputStream bufo = new BufferedOutputStream(new FileOutputStream("g:\\copy1.mp3"));
int ch = 0;
while((ch = bufi.read())!=-1)
 {
    bufo.write(ch);
  }
bufi.close();
bufo.close();

****轉換流:
    (1)需求1:讀取一個鍵盤錄入

        InputStream in = System.in;//建立一個鍵盤錄入流,流不關則可以一直錄入
        int by = in.read();//一次讀一個位元組
        System.out.println((char)by);
        in.close();  

 
    (2)需求2:鍵盤錄入一行資料列印一行資料,如果錄入的是over則結束錄入

		InputStream in = System.in;
		StringBuilder sb = new StringBuilder();
		while(true)
		{
			int ch = in.read();
			if(ch=='\r')
				continue;
			if(ch=='\n')
			{
				String line = sb.toString();
				if("over".equals(line))
					break;
				sop(line.toUpperCase());//輸出大寫
				sb.delete(0.sb.length());//清除上一行錄入的資料

			}
			else
				sb.append((char)ch);
		}
		in.close();


    (3)需求3:發現需求2中其實就是讀一行的原理,故引入位元組通向字元的橋樑:InputStreamReader
        為提高效率加入緩衝區:

        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        while((line = bufr.readLine())!=null)
        {
            if("over".equals(line))
                break;
            System.out.println(line.toUpperCase());//輸出大寫
        }
        bufr.close();


    (4)需求4:鍵盤錄入資料並列印到控制檯

        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bufw = new BufferedWriter(new OntputStreamWriter(System.out));
        String line = null;
        while((line = bufr.readLine())!=null)
        {    
            if("over".equals(line))
                break;
            bufw.write(line.toUpperCase());
            bufw.newLine();
            bufw.flush();    
        }
        bufr.close();
        bufw.close();


    (5)需求5:將鍵盤錄入的資料儲存到硬碟檔案
        則只需將(4)中的

        BufferedWriter bufw = new BufferedWriter(new OntputStreamWriter(System.out));
        改為:
        BufferedWriter bufw = new BufferedWriter(new OntputStreamWriter(new FileWriter("g:\\demo.txt")));
        即:
        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bufw = new BufferedWriter(new OntputStreamWriter(new FileWriter("g:\\demo.txt")));
        String line = null;
        while((line = bufr.readLine())!=null)
        {    
            if("over".equals(line))
                break;
            bufw.write(line.toUpperCase());
            bufw.newLine();
            bufw.flush();    
        }
        bufr.close();
        bufw.close();


    (6)需求6:將硬碟檔案的資料列印到控制檯
        則只需將(4)中的

        BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
        改為:
        BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileReader("g:\\demo.txt")));
        即:
        BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileReader("g:\\demo.txt")));
        BufferedWriter bufw = new BufferedWriter(new OntputStreamWriter(System.out));
        String line = null;
        while((line = bufr.readLine())!=null)
        {    
            if("over".equals(line))
                break;
            bufw.write(line.toUpperCase());
            bufw.newLine();
            bufw.flush();    
        }
        bufr.close();
        bufw.close();

File類常見需求

    (1)檔名過濾:列出給定目錄的所有.java檔案

        public void showFileName(File file)
        {
            String[] filenames = file.list(new FilenameFilter()//匿名內部類
            {
                public boolean accept(File dir,String name)//複寫唯一方法
                {
                    return name.endsWith(".java");//列出所有.java檔案
                }
            });
        }


    (2)列出指定目錄下的所有檔案和資料夾(遞迴)
    **示例1:不帶層次遞迴:

    public static void showDir(File dir)
    {
        File[] files = dir.listFile();
        for(int i = 0;i<files.length;i++)
        {
            if(files[i].isDirectory&&!files[i].isHidden())
                showDir(files[i]);
            else
                sop(files[i]);
        }
    }


    **示例2:帶層次遞迴:

    public static void showDir(File dir,int level)
    {
        sop(getLevel(level)+C);//進來先列印層次和目錄
        level++;
        File[] files = dir.listFile();
        for(int i = 0;i<files.length;i++)
        {
            if(files[i].isDirectory&&!files[i].isHidden())
                showDir(files[i]);
            else
                sop(getLevel(level)+files[i]);//是檔案就列印層次和目錄
        }
    }
    public static String getLevel(int level)
    {
        sop("|--");
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<level;i++)
        {
            sb.inset(0."|  ")
        }
        return sb.toString();
    }


    (3)需求:刪除帶內容的目錄:

    public static void removeDir(File dir)
    {
        File[] files = file.listFile();
        for(int i = 0;i<files.length;i++)
        {
            if(files[i].isDirectory&&!files[i].isHidden())
                removeDir(files[i]);//如果是資料夾則繼續呼叫函式
            else//如果是檔案則刪除。注意刪除的時候列印刪除的結果,防止誤刪或者重刪的情況
                sop(files[i].toString()+"::"+files[i].delete());
        }
        sop(dir+"::"+dir.delete());
    }


    (4)需求:將制定目錄下的java檔案的絕對路徑儲存到文字檔案中。
       思路:
       **對指定目錄進行遞迴
       **獲取遞迴過程中所有java檔案的路徑
       **將這些路徑儲存到集合中
       **將集合中的資料寫入檔案中
     //對指定目錄進行遞歸併將所以Java檔案儲存到集合中
  

  public static void getFileName(File file,ArrayList<File> arraylist){
        File[] files = file.listFiles();
        for (int i = 0; i < files.length; i++) {
            if(files[i].isDirectory()&&!files[i].isHidden()){
                getFileName(files[i],arraylist);
            }else{
                if(files[i].getName().endsWith(".java")){
                    arraylist.add(files[i]);
                }
            }
        }
    }
    //將集合中所有資料儲存到新檔案中
    public static void saveFileToNewDir(ArrayList<File> arraylist,File newDir){
        BufferedWriter bufw = null;
        try {
            bufw = new BufferedWriter(new FileWriter(newDir));
            for (File file : arraylist) {
                String fileAbsolutePath = file.getAbsolutePath();
                bufw.write(fileAbsolutePath);
                bufw.newLine();
                bufw.flush();    
            }
        } catch (Exception e) {
            System.out.println("檔案寫入失敗");
        }finally{
            try {
                if(bufw!=null)
                    bufw.close();
            } catch (Exception e2) {
                System.out.println("檔案寫入流關閉失敗");
            }
        }
    }