天天看點

c++從txt中讀取資料_「java技術分享」一篇徹底讀懂java中的IO流

c++從txt中讀取資料_「java技術分享」一篇徹底讀懂java中的IO流

一、IO概念

• I/O 即輸入Input/ 輸出Output的縮寫,其實就是計算機排程把各個存儲中(包括記憶體和外部存儲)的資料寫入寫出的過程;

• java中用“流(stream)”來抽象表示這麼一個寫入寫出的功能,封裝成一個“類”,都放在 http:// java.io 這個包裡面。

二、來了解“流”是什麼?

通過“流”的形式允許java程式使用相同的方式來通路不同的輸入/輸出源。stream是從起源(source)到接收的(sink)的有序資料。我們這裡把輸入/輸出源對比成“水桶”,那麼流就是“管道”,這個“管道”的粗細、單向性等屬性也就是區分了不同“流”的特性。

c++從txt中讀取資料_「java技術分享」一篇徹底讀懂java中的IO流

三、IO流的分類

可以從三個不同的次元進行分類:

• 1、按照流的方向(輸出輸入都是站在程式所在記憶體的角度劃分的)

• 輸入流:隻能從中讀取資料【主要由InputStream和Reader作為基類】

• 輸出流:隻能向其寫入資料【主要由outputStream和Writer作為基類】

在下圖中,從磁盤讀取資料到記憶體是輸入流,從client讀取資料到server是輸入流;同樣,把記憶體資料寫到磁盤是輸出流,把server資料寫到client是輸出流

c++從txt中讀取資料_「java技術分享」一篇徹底讀懂java中的IO流
• 2、按照流的操作顆粒度劃分

• 位元組流:以位元組為單元,可操作任何資料【主要由InputStream和outPutStream作為基類】

• 字元流:以字元為單元,隻能操作純字元資料,比較友善【主要由Reader和Writer作為基類】

• 3、按照流的角色劃分

• 節點流:可以從/向一個特定的IO裝置(如磁盤,網絡)讀/寫資料的流,也叫【低級流,主要由】

• 處理流:用于對一個已存在的流進行連接配接和封裝,通過封裝後的流來實作資料的讀/寫功能,也叫【進階流】

下圖中可以看出來,處理流就是在基礎的位元組流上,進行了封裝,增加了特定的功能,使得傳輸更适合特定的場景。

c++從txt中讀取資料_「java技術分享」一篇徹底讀懂java中的IO流

四、流的原理以及一共有多少IO流

• 1、流的原了解析

流其實我們可以想象成一個“水管”,源端和目的端就是兩個“水桶”,資料是通過這個“水管”進行流動傳輸的,以InputStream和Reader為例,水管的每個“水滴”就是具體的資料,如果是位元組流,那麼一個“水滴”就是一個位元組,如果是字元流,那麼一個“水滴”就是一個字元。

當建立一個流對象的時候,如fis=new FileInputStream(“…xxxx.txt”),記錄指針來表示目前正準備從哪個“水滴”開始讀取,每當程式從InputStream或者Reader裡面取出一個或者多個“水滴”後,記錄指針自定向後移動;除此之外,InputStream和Reader裡面都提供了一些方法來控制記錄指針的移動。

c++從txt中讀取資料_「java技術分享」一篇徹底讀懂java中的IO流

如果是處理流的話,就相當于在這個水管上面裝了一些“控制閥門”,最終使用者隻要關心“閥門”具備的能力就行

c++從txt中讀取資料_「java技術分享」一篇徹底讀懂java中的IO流
• 2、java中所有流彙總

http://java.io中子類有40個“流”類,我們用以下表格來綜合劃分,當然這些流你不用都去花時間一個一個看過來,我們隻要熟悉掌握幾類常用的“流”就足夠了,後續項目中如果用到陌生的“流”,知道原理的話可以快速地去檢索學習下就ok了。

c++從txt中讀取資料_「java技術分享」一篇徹底讀懂java中的IO流

上圖中我們可以看到,InputStream/Reader,OutputStream/Writer 是整個I/O體系的基類,他們本身不能用來建立執行個體,下面開始逐一對常見的I/O類進行實戰

五、常見IO流的實戰

1、通路操作檔案(FileInputStream/FileReader ,FileOutputStream/FileWriter)

FileInputStream中包含以使用FileInputStream為例,類中包含的屬性及方法,我們可以線上檢視jdk的api文檔http://tool.oschina.net/apidocs/apidoc?api=jdk-zh),下面隻是截圖了FileInputStream的構造方法:

c++從txt中讀取資料_「java技術分享」一篇徹底讀懂java中的IO流

1)使用FileInputStream,從檔案讀取資料

import java.io.*;
public class TestFileImportStream {

	public static void main(String[] args) {
		int b=0;
		FileInputStream in = null;
		try {
		in =new FileInputStream("C:Users41639DesktopjavaFileTextsrcTestFileImportStream.java");
		}catch(FileNotFoundException e){
			System.out.println("file is not found");
			System.exit(-1);
		}
		try {
			long num=0;
			while ((b=in.read())!=-1) {
				System.out.println((char)b);
				num++;
			}
			in.close();
			System.out.println();
			System.out.println("共讀取了"+num+"個位元組");
		}catch(IOException e) {
			System.out.println("IO異常,讀取失敗");
			System.exit(-1);
		}
	}

}
           

2)使用FileOutputStream,往檔案裡寫資料

import java.io.*;
public class TextFileOutputStream {

	public static void main(String[] args) {
		int b=0;
		FileInputStream in = null;
		FileOutputStream out = null;
		try {
		in =new FileInputStream("C:Users41639DesktopjavaFileTextsrcTestFileImportStream.java");
		out=new FileOutputStream("C:Users41639Desktopjavatempout.java");
		}catch(FileNotFoundException e){
			System.out.println("file is not found");
			System.exit(-1);
		}
		try {
			while ((b=in.read())!=-1) {
				out.write(b);
			}
			in.close();
			out.close();
		}catch(IOException e) {
			System.out.println("IO異常,讀取失敗");
			System.exit(-1);
		}
		System.out.println("檔案複制完成");
	}

}
           

PS:大家也可以嘗試使用FileReader、FileWriter,看看和FileInputStream、FileOutputStream有什麼差別

2、緩存流的使用(BufferedInputStream/BufferedOutputStream,BufferedReader/BufferedWriter)
import java.io.*;
public class TestBufferStream {
	public static void main (String[] args) throws IOException{
		BufferedInputStream bis=null;
		BufferedOutputStream bos=null;
		try {
			FileInputStream fis = new FileInputStream("C:Users41639DesktopjavaFileTextsrcTestFileImportStream.java");
			FileOutputStream fos = new FileOutputStream("C:Users41639Desktopjavatempout2.java");
			bis = new BufferedInputStream(fis);
			bos = new BufferedOutputStream(fos);
			byte[] b = new byte[1024];
			int off=0;
			while ((off=bis.read(b))>0) {
				bos.write(b,0,off);
			}
			bis.close();
			bos.close();
		}catch (IOException e) {
			e.printStackTrace();
		}finally {
			bis.close();
			bos.close();
		}		
	}
}
           

從代碼中可以看到,他們最基本的其實也是FileInputStream和FileOutputStream,在這個“流”的基礎上,又加了緩存的功能流BufferedInputStream和BufferedOutputStream。相對比較好了解。

3、轉換流的使用(InputStreamReader/OutputStreamWriter)

字面意思了解,轉化流就是用來轉化的,那麼到底是什麼轉什麼呢?我們可以通過以下的例子來熟悉。讀取鍵盤輸入的每一行内容,并寫入到文本中,直到遇到over行結束輸入

import java.io.*;
public class TransStreamTest {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new FileWriter("C:Users41639Desktopjavatemptest1031.txt"));
		String line =null;
		while ((line=br.readLine())!=null) {
			if ("over".contentEquals(line)) {
				break;
			}
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
    bw.close();
    br.close();
	}

}
           

PS:readLine()方法在進行讀取一行時,隻有遇到回車(r)或者換行符(n)才會傳回讀取結果,這就是“讀取一行的意思”,有興趣的同學檢視readLine()源碼

4、對象流的使用(FileInputStream/ObjectOutputStream)

前面講了位元組和字元流,包括封裝在他們上面的處理流,那麼我們想,在程式設計的過程中,我們都是用類和對象來描述定義,能不能直接把對象進行傳輸。答案當然是肯定的,對象流其實就是一種特殊的處理流水,也是在基礎的位元組流上去作封裝。【可以應用于遊戲存盤】

下面程式使用一個對象流,把對象直接寫到檔案中

import java.io.*;
public class ObjectStreamTest {
	public static void main(String[] args) throws Exception{
		try {
			Person P=new Person("Jeccica",26);
			FileOutputStream fos=new FileOutputStream("C:UsersadminDesktopJavatemp22.txt");
			ObjectOutputStream oos=new ObjectOutputStream(fos);
			oos.writeObject(P);
			oos.flush();
			oos.close();
		}catch(FileNotFoundException e) {
			e.printStackTrace();
		}catch(IOException e) {
			e.printStackTrace();
		}			
		
		FileInputStream fis=new FileInputStream("C:UsersadminDesktopJavatemp22.txt");
		ObjectInputStream ois=new ObjectInputStream(fis);
		Person P2=(Person)ois.readObject();
		System.out.println(P2.name+"的年齡為"+P2.age);
	}

}

class Person implements Serializable{
	String name=null;
	int age=0;
	Person(String _name,int _age){
		name=_name;
		age=_age;
	}
}
           
5、位元組數組流的使用(ByteArrayInputStream/ByteArrayOutputStream)【通常結合資料流DataInputStream/DataOutputStream】

我們分析了常見的節點流和常見的處理流等,經常而言我們都是針對檔案的操作,然後帶上緩沖的節點流進行處理,但有時候為了提升效率,我們發現頻繁的讀寫檔案并不是太好,那麼于是出現了位元組數組流,即存放在記憶體中,是以又稱之為記憶體流;其中位元組數組流也一種節點流;除了節點流外,我們也将學習另外一種處理流,即資料流。資料處理流是用于針對資料類型傳輸處理的,是一種處理流,即是在節點流之上的增強處理,一般用于序列化和反序列化的時候用到。

import java.io.*;
public class DataStream {
	public static void main(String[] args) {
		ByteArrayOutputStream baos=new ByteArrayOutputStream();//建立位元組數組流,同時會在記憶體裡面建立數組
		DataOutputStream dos=new DataOutputStream(baos);//對位元組數組流外封裝成資料處理流
		try {
			dos.writeDouble(Math.random());//利用資料流裡面的寫入方法,寫一個Double類型的随機資料
			dos.writeBoolean(true);
			ByteArrayInputStream bias=new ByteArrayInputStream(baos.toByteArray());//toByteArray()方法是建立一個新配置設定的位元組數組。數組的大小和目前輸出流的大小。這裡指的是baos這個位元組數組
			System.out.println(bias.available());
			DataInputStream dis=new DataInputStream(bias);
			System.out.println(dis.readDouble());
			System.out.println(dis.readBoolean());		
			dos.close();
			dis.close();
		}catch (IOException e) {
			e.printStackTrace();
		}
	}
}
           

感謝你看到這裡,我是

程式員麥冬

,一個java開發從業者,深耕行業六年了,每天都會分享java相關技術文章或行業資訊

歡迎大家關注和轉發文章,後期還有福利贈送!