Java BIO

BIO是出現得比較陳舊的IO技術了,它的缺點在於併發量高時,IO操作等待的時間會比較長,因爲它是阻塞IO。在IO中,一般按照數據的不同,可以分爲字節流和字符流,字節流把讀到的數據當做字節來處理,而字符流把數據當做字符來處理。

字節流

根據輸入和輸出,字節流又可以分爲輸入字節流InputStream和輸出字節流OutputStream。

輸入字節流InputSteam

這是一個Java接口,其原型如下:
int read();//每次從字節流當前位置中讀入一個字節
int read(byte[] buffer);//從字節流中當前位置開始讀取數據今日到數值buffer中,最多讀取buffer.length個字節
int read(byte[] buffer, int off, int len);//從字節流當前位置開指定的偏移off開始,讀取len個字節到數組buffer中
int available();//返回字節流中可以讀取的字節數
long skip(long a);//從字節流當前位置開始,跳過a個字節
void close();//關閉字節輸入流

該接口還有許多實現類
ByteArrayInputStream:把一個byte[]當做輸入流源
FileInputStream:把一個File對象當做輸入流源
ObjectInputStream:把一個Java對象當做輸入流源
StringBufferInputStream:把一個String對象當做輸入流源
並且有這其他的三種特殊實現:
PipedInputStream:實現了管道的,主要在線程中使用。
SequenceInputStream:把多個InputStream合併爲一個InputStream。
FilterInputStream:對輸入流進行各種過濾操作。

  • ByteArrayInputStream
這個類包含了兩個構造器
ByteArrayInputStream(byte[] src);
ByteArrayInputStream(byte[] src, int off, int len);

兩個構造器都需要一個byte[]作爲源。這個類可以直接操作byte[]。
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		byte[] src = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
		ByteArrayInputStream is = new ByteArrayInputStream(src);
		while(is.available() > 0)
		{
			int num = is.read();
			System.out.print(num);
		}
		try {
			is.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

  • FileInputStream
這個類使用文件作爲源,它的構造器很多,但最主要的還是

FileInputStream(File file);

這個實現類用得是相當多,因爲文件IO其實用得是非常多的。

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		File file = new File("test.txt");
		if(file.exists())
		{
			try {
				FileInputStream is = new FileInputStream(file);
				byte[] buffer = new byte[1024];//緩衝區
				int len = -1;
				while((len = is.read(buffer, 0, buffer.length)) != -1)
				{
					System.out.println(new String(buffer, 0 , len));
				}
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}	
		}
	}

  • ObjectInputStream
這個類可以讀取寫到磁盤上的序列化對象,它的構造器如下
ObjectInputStream(InputStream is);

通常來說,一個序列化的對象被寫到了磁盤上,也算是一個文件了,所以通常的InputStream會採用其子類FileInputStream作爲實際的參數。

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		File file = new File("person.txt");
		if(file.exists())
		{
			FileInputStream is1;
			try {
				is1 = new FileInputStream(file);
				ObjectInputStream is2 = new ObjectInputStream(is1);
				Object obj = is2.readObject();
			}catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}		
		}
	}

  • StringBufferInputStream

這個類使用字符創String作爲源,它的構造器如下

StringBufferInputStream(String src);
這個類已經過時了,不推薦使用。

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String src = "hello,world";
		
		StringBufferInputStream is = new StringBufferInputStream(src);
		
		byte[] buffer = new byte[is.available()];
		
		try {
			is.read(buffer);
			System.out.println(new String(buffer));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

  • PipedInputStream

管道輸入流,該輸入流需要從管道處獲取數據。它的構造器如下

PipedInputStream(PipedOutputStream os);
PipedInputStream();

第一個構造器將使用管道輸出流作爲源,第二個構造器將創建一個無源的輸入流。

  • SequenceInputStream

該類可以將兩個個InputStream串聯起來。它的構造器如下

SequenceInputStream(InputStream is1, InputStream is2);
SequenceInputStream(Enumeration<? extends InputStream> e);

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			FileInputStream is1 = new FileInputStream(new File("src/a.txt"));
			FileInputStream is2 = new FileInputStream(new File("src/b.txt"));
			FileInputStream is3 = new FileInputStream(new File("src/c.txt"));
			Vector<InputStream> v = new Vector<InputStream>();
			v.add(is1);
			v.add(is2);
			v.add(is3);
			SequenceInputStream sis = new SequenceInputStream(v.elements());
			System.out.println(sis.available());
			int i = -1;
			while((i = sis.read()) != -1)
			{
				System.out.print((char)i);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

注意,這裏不能使用available()來判斷流的可用數據,而是需要判斷是否到流的尾部read()是否==-1,才能將合併後的數據全部輸出來。

  • 過濾輸入流FilterInputStream

它把其他的流作爲基本數據源,FilterInputStream會將所有請求傳遞給包含InputStream的所有方法。這個類本身對於數據流沒有什麼用,它的子類DataInputStream和PushBackInputStream倒是蠻有用的。

DataInputStream

這個類可以將一些字節數據讀取出來並轉化成爲基本的Java類型

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		byte[] src = new byte[]{1,1};
		ByteArrayInputStream is = new ByteArrayInputStream(src);
		DataInputStream dis = new DataInputStream(is);
		short s = dis.readShort();
		System.out.println(s);
	}
PushBackInputStream

這個類可以有推回或者取消讀取一個字節的能力,使用unread()方法可以讓遊標重新回到上一個讀取過了的字節處。

字節輸出流OutputStream

字節輸入流負責字節流的取得,而字節輸出流則負責字節的輸出。

OutputStream是一個接口,它有着以下的一些實現類:

ByteArrayOutputStream

FileOutputStream

StringBufferOutputStream

ObjectOutputStream

此外,還有特殊的實現

PipedOutputStream

SequenceOutputStream

FilterOutputStream

  • ByteArrayOutputStream

該類可以將字節流輸出到字節數組裏面

  • FileOutputStream

該類可以將字節流輸出到文件裏面

  • StringBufferOutputStream

該類可以將字節流輸出到字符串裏面

  • ObjectOutputStream

該類可以將序列化對象輸出

字符流

字符輸入流Reader

Reader是一個接口,其原型如下:
int read(char[] chs, int off, int len);//從字符流當前位置開始,將字符流讀入到字符數組chs中,從off偏移位置開始存放,讀入的字符流長度爲len
int read();//從字符流當前位置開始,一次讀取一個字符
int read(char[] chs);//從字符流當前位置開始,將字符流讀入存放到chs字符數組中
boolean ready();//判斷該流是否準備好
void reset();//重置流的位置
long skip(long n);//從字符流當前位置開始,跳過n個字符
void mark(int n);//對流進行標記
void colse();//關閉流

Reader有許多相關的實現類:
CharArrayReader
StringReader
InputStreamReader
BufferReader
FilterReader
PipedReader

  • CharArrayReader
該實現類以char數組爲源,從char數組中讀取數組,其構造器如下
CharArrayReader(char[] src);
CharArrayReader(char[] src, int off, int len);

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		char[] src = new char[]{'h', 'e', 'l', 'l', 'o'};
		CharArrayReader reader = new CharArrayReader(src);
		int i = -1;
		while((i = reader.read()) != -1)
		{
			System.out.print((char) i);
		}
	}

  • StringReader
該類以String作爲源,從String中讀入字符,其構造器
StringReader(String src);

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		String src = new String("hello");
		StringReader reader = new StringReader(src);
		int i = -1;
		while( (i = reader.read()) != -1)
		{
			System.out.print((char) i);
		}
	}

InputStreamReader
該類以InputStream作爲源,從InputStream中讀入字符流,其構造器
InputStreamReader(InputStream is);

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		File file = new File("src/a.txt");
		if(file.exists())
		{
			FileInputStream is = new FileInputStream(file);
			InputStreamReader reader = new InputStreamReader(is);
			int i = -1;
			while( (i = reader.read()) != -1)
			{
				System.out.print((char) i);
			}
		}
	}

適合用於讀取一些全是字符的文件。這個類還有一個子類FileReader,FileReader是以文件作爲源,從文件中讀取字符流的,其構造器
FileReader(String filename);
FileReader(File file);

  • PipedReader
該類以管道作爲源,從管道中讀取字符流,其構造器
PipedReader(PipedWriter writer);

  • BufferReader
一個帶緩衝區的Reader,其構造器
BufferedReader(Reader r);
BufferedReader(Reader r, int size);

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		File file = new File("src/a.txt");
		if(file.exists())
		{
			FileInputStream is = new FileInputStream(file);
			InputStreamReader reader = new InputStreamReader(is);
			BufferedReader r = new BufferedReader(reader);
			int i = -1;
			while( (i = r.read()) != -1)
			{
				System.out.print((char) i);
			}
		}
	}

  • FilterReader
跟FilterInputStream一樣,這個類本身沒有什麼用,而其子類PushBackReader比較有用,這是一個可以回退一個字符的Reader。

字符輸出流Writer

Writer是一個接口,其原型如下:
write(String str);
write(String str, int off, int len);
write(char[] chs);
write(char[] chs, int off, int len);
write(int i);
void flush();
void close();

其實現類如下:
CharArrayWriter
StringWriter
OutputStreamWriter
PrintWriter
PipedWriter
BufferedWriter

  • CharArrayWriter
該類以char[]爲目標,向char[]輸出字符

  • StringWriter
該類以String爲目標,向String輸出字符

  • OutputStreamWriter
該類以OutputStream爲目標,想OutputStream輸出字符,其構造器
OutputStreamWriter(OutputStream os);

該類還有一個子類FileWriter,可以向文件輸出字符,其構造器
FileWriter(String filename);
FileWriter(File file);

  • PrintWriter
該類比較重要,它可以格式化輸出字符流。使用format(String format, String content)
它有一個以OutputStream爲對象構造的
PrintWriter(OutputStream os)


  • PushBackWriter

該類可以回退一個字符。

標準輸入輸出流

標準輸入流System.in

這是一個InputStream對象

標準輸出流System.out

這是一個OutputStream對象

字節流轉換流InputStreamReader和OutputStreamWriter

這兩個字符流可以將字節流轉換,然後以字符流形式輸入或者輸出到目標。
發佈了70 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章