1. 程式人生 > >Java核心---I/O流

Java核心---I/O流

流概述: 流是一組有序的資料序列,根據操作的型別,可分為輸入流和輸出流兩種。I/O(Input/Output,輸入/輸出)流提供了一條通道程式,可以使用這條通道把源中的位元組序列送到目的地。 輸入和輸出模式如下圖:
輸入/輸出流  所有輸出流淚都是抽象類InputStream(位元組輸入流)或抽象類Reader(字元輸入流)的子類,所有輸出流都是抽象類OutputStream(位元組輸出流)或抽象類Writer(字元輸出流)的子類。 字元流和位元組流的區別:    因為資料編碼的不同,而有了對字元進行高效操作的流物件。本質其實就是基於位元組流讀取時,去查了指定的碼錶。 1.讀寫單位不同,位元組流以位元組為單位,字元流以字元為單位,根據碼錶對映字元,一次可能讀多個位元組。
2.處理物件不同,位元組流能處理所有的型別的資料,而字元流自能處理字元型別的資料 3.位元組流在操作的時候不會用到緩衝區,是檔案本身的直接操作,而字元流在操作時會用到緩衝區。  總的來說,一般都選擇用位元組流,除了純文字的情況用字元流更加高效。 示例(將一些文字儲存到檔案中):
/*
 思路:因為是純文字的,所以使用字元流
 因為是寫入到檔案中,所以要建立一個輸出流物件,並且要明確一個目的地,如果目的地沒有
 檔案那麼就自動建立一個,如果存在就覆蓋
*/
import java.io.*;
class  FileWriterDemo
{
	public static void main(String[] args) throws IOException
	{
		FileWriter fw = new FileWriter("FileDemo.txt");//建立目的檔案
		fw.write("abc");//用write方法寫入資料
		fw.flush();//重新整理流資料,將資料寫入到目的地中
		fw.close();//關閉流
	}
}
如果建立檔案物件時,使用FileWriter fw = new FileWriter("FileDemo.txt",true) 那麼目的中的檔案就不會被覆蓋,而是會續寫。 示例(將一個檔案中的資料在控制檯顯示):
import java.io.*;
class  FileReaderDemo
{
	public static void main(String[] args) throws IOException
	{
		FileReader fr = new FileReader("FileDemo.txt");//選擇原始檔
		int i = 0;
		while((i=fr.read())!=-1)
		{
			System.out.println((char)i); //強轉之後輸出到控制檯
		}
		fr.close();//關閉流
	}
}
執行結果:

示例(複製一個文字檔案):
import java.io.*;
class  CopyDemo
{
	public static void main(String[] args) throws IOException
	{
		FileReader fr = new FileReader("FileDemo.txt"); //讀取一個已有的本文檔案並用字元流關聯

		FileWriter fw = new FileWriter("FileDemoCopy.txt");//建立一個目的檔案用來儲存資料
		int i = 0;
		while((i=fr.read())!=-1)//迴圈讀寫
		{
			fw.write(i);
		}
		fw.close();
		fr.close();
 	}
}
可以使用緩衝區提高讀寫效率。 緩衝區:就像是喝水,一滴一滴的喝想要解渴太久了,用水杯將水裝滿之後再喝就快多了。
import java.io.*;
public class BufferedWriterDemo{
       public static void main(String[] args) throws IOException{
            FileWriter fw = new FileWriter("buf.txt" );
             //建立一個字元寫入流的緩衝區物件,並且指定與要被緩衝的流物件相關聯
            BufferedWriter bufw = new BufferedWriter(fw);

             for(int x = 1; x <= 4; x++){
                   //將資料先寫入到緩衝區中
                  bufw.write( "abcdef" + x);
                   //換行方法:newLine();
                  bufw.newLine();
                  bufw.flush();
            }

             //將資料刷目的地中
            bufw.flush();

             //關閉緩衝區
            fw.close();
      }
}

操作文字檔案用字元流更高效。不過位元組流的運用更廣。例如音訊視屏檔案都只能用位元組流來操作。 示例(複製一個map3檔案,運用緩衝區更加高效):
import java.io.*;
class  CopyMp3Demo
{
	public static void main(String[] args) throws IOException
	{
		FileInputStream fis = new FileInputStream("1.map3"); //讀取已有檔案並用位元組流關聯
		FileOutputStream fos = new FileOutputStream("2.mp3");  //建立一個目的儲存資料

		byte[] buf = new byte[1024];  //建立緩衝區
		int len = 0;
		while((len=fis.read(buf))!=-1) //位元組不斷的寫入資料
		{
			fos.write(buf,0,len);
		}
		fis.close(); //關閉流
		fos.close();
	}
}
寫IO流的程式。首先應該明確幾點 1源和目的   源 InputStream 或者 Reader   目的 OutputStream 或者 Writer 2是否是純文字  純文字就用字元流 Reader 或者 Writer 不是純文字就用位元組流 InputStream 或者 OutputStream 另外還有: 判斷是否要加入緩衝區功能

關於轉換流:

InputStreamReader 位元組到字元,解碼 OutputStreamWriter 字元到位元組,編碼 為了方便字元流和位元組流之間的操作 當位元組流中的資料都是字元時,將位元組轉換成字元操作更高效 示例(將輸入的字母轉換成小寫的,並在控制檯顯示):
import java.io.*;
class  TranDemo
{
	public static void main(String[] args) throws IOException
	{
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
		String line = null;
		while((line=bufr.readLine())!=null)
		{
			if("886".equals(line))
				break;
			bufw.write(line.toLowerCase());
			bufw.newLine();
			bufw.flush();
		}
	}
}
執行結果:
示例(將鍵盤輸入的資料儲存到檔案中): 分析: 源:鍵盤 System.in 目的:檔案  FIle 是否純文字: 是 是否要使用緩衝區:是  另外:將讀取的位元組流資料轉換成字元流操作更高效,所以要用到轉換流
import java.io.*;
class  TranDemo
{
	public static void main(String[] args) throws IOException
	{
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("TranDemo.txt")));
		String line = null;
		while((line=bufr.readLine())!=null)
		{
			if("886".equals(line))
				break;
			bufw.write(line);
			bufw.newLine();
			bufw.flush();
		}
	}
}


FileWriter其實就是轉換流指定了本機預設碼錶的體現,而且這個轉換流的子類物件,可以方便操作文字檔案。
簡單說:操作檔案的位元組流+本機預設的編碼表。
這是按照預設碼錶來操作檔案的便捷類
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"GBK");           
如果操作文字檔案需要明確具體的碼錶,FileWriter就不行了,必須用轉換流。
示例:
import java.io.*;
public class TransStreamDemo {
       public static void main(String[] args) throws IOException {
            writeText();
      }
       public static void writeText() throws IOException {
             //下面這句程式碼等同於FileWriter fw = new FileWriter("b.txt");
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt" ),"UTF-8" );
            osw.write( "您好");
            osw.close();
      }
}
示例(將一個指定的txt檔案中的內容在控制檯顯示):
import java.io.Exception
class TransStreamDemo {
       public static void main(String[] args) throws IOException {
            writeText();//呼叫方法
      }
       public static void writeText() throws IOException {
            InputStreamReader isr = new InputStreamReader(new FileInputStream("demo.txt" ),"UTF-8" );//確定一個源並用流聯立
             char[] buf = new char[10];//建立一個緩衝區
             int len = isr.read(buf); //讀取文件中的內容
            String str = new String(buf,0,len);  //將資料封裝到字串
            System.out.println(str);
            isr.close(); //流關閉
      }
}
示例(獲取目錄下的檔案和檔案的名稱):
import java.io.*;
class FileListDemo{
       public static void main(String[] args) throws IOException {
            listDemo();
      }

       public static void listDemo() throws IOException {
            File file = new File("c:\\" );

             //獲取目錄下的檔案以及資料夾的名稱,包含隱藏檔案
             //呼叫list方法的File物件中封裝的必須是目錄,否則會產生NullPointerException
             //如果訪問的是系統級目錄也會發生空指標異常
             //如果目錄存在但是沒有內容,會返回一個數組,但是長度為0
            String[] names = file.list();
      
             for(String name : names){
                  System.out.println(name);
            }
      }
}

示例(獲取D盤下java資料夾中.java結尾的檔案):
import java.io.*;
class FileListDemo{
       public static void main(String[] args){
            listDemo(); //呼叫listDemo()方法
      }

       public static void listDemo(){
            File dir = new File("d:\\java" );  //讀取指定目錄         
            String[] names = dir.list( new FilterByJava());  //獲取文件名稱
             for(String name : names){  //高階的for迴圈遞迴
                  System.out.println(name);
            }
      }
}

class FilterByJava implements FilenameFilter{
       public boolean accept(File dir,String name){//判斷檔名稱是否符合
             return name.endsWith(".java" );  
      }
}


示例(將指定目錄下所有.java檔案拷貝到另一個目的中,並改為.txt格式):
import java.io.*;
import java.util.*;
class  JavaDocDemo
/*
	要求:編寫程式,將指定目錄下所有.java檔案拷貝到另一個目的中,並將副檔名改為.txt
	思路 1.用遞迴的方法遍歷指定目錄下的檔案
	     2.將以.java結尾的檔名存入集合
		 3.將以.java結尾的檔案複製到指定目的並改名
*/
{
	public static void main(String[] args) throws Exception
	{
		ArrayList<String> list = new ArrayList<String>();//定義集合用來儲存java檔案的名字
		File src = new File("C:\\Users\\zlf\\Desktop\\java");//原始檔的路徑
		File des = new File("C:\\Users");//目的檔案路徑
		if(!des.exists())//判斷目的檔案是否存在,不存在建立
			des.mkdirs();
		fileTolist(src,list);//將原始檔中的Java檔案的名字存入到集合中
		for(String fileName:list)
			writeTofile(src,des,fileName);//將原始檔中的Java檔案存入到目的資料夾中
	}

	//將原始檔中的Java檔案的名字存入到集合中
	public static void fileTolist(File file,List<String>list)
	{
		File[] files = file.listFiles();//獲取原始檔夾中的檔案
		for(File f:files)//遍歷檔案並將Java檔案的名字存到集合中
		{
			list.add(f.getName());
		}
	}

	 //將原始檔中的Java檔案存入到目的資料夾中
	public static void writeTofile(File src,File des,String fileName)throws Exception
	{	
		BufferedReader bufr = new BufferedReader(new FileReader(new File(src,fileName)));
		BufferedWriter bufw = new BufferedWriter(new FileWriter(new File(des,fileName.replace(".java",".txt"))));
		String line = null;
		while((line=bufr.readLine())!=null)
		{
			bufw.write(line);
			bufw.newLine();
			bufw.flush();
		}
		bufw.close();
		bufr.close();
	}
}