天天看點

Java核心---I/O流

流概述: 流是一組有序的資料序列,根據操作的類型,可分為輸入流和輸出流兩種。I/O(Input/Output,輸入/輸出)流提供了一條通道程式,可以使用這條通道把源中的位元組序列送到目的地。 輸入和輸出模式如下圖:

Java核心---I/O流
Java核心---I/O流

輸入/輸出流  所有輸出流淚都是抽象類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();//關閉流
	}
}
           

運作結果:

Java核心---I/O流

示例(複制一個文本檔案):

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();
		}
	}
}
           

運作結果:

Java核心---I/O流

示例(将鍵盤輸入的資料存儲到檔案中): 分析: 源:鍵盤 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();
	}
}