1. 程式人生 > >Java IO程式設計

Java IO程式設計

Java IO

      Java有非常豐富的IO介面,從流型別可劃分為位元組流和字元流,從流操作的位置可劃分為網路IO和本地IO。

本地IO
  1. 本地IO時,普通IO和BIO最為常用,BIO較普通IO有更豐富的流操作元件,而NIO、AIO對於本地IO來說反而會在效率上大打折扣
  1. 那麼buffer有什麼作用呢?它會在記憶體中開闢一塊緩衝區,用於優化對流的操作,讀流時:不間斷地從裝置讀到緩衝區中,同時對緩衝區進行間斷(每次1024位元組)地讀取操作,速度加快。寫流時:先將流間斷(每次1024位元組)地寫入到緩衝區中,再統一對裝置寫入,速度加快,mark/reset就是通過這種方式實現的
網路IO
  • 網路IO時,普通IO效率最低,BIO效率較普通IO更高,但BIO每個連線都需要起一個執行緒,而NIO通過selector完美地解決了這個問題,AIO是併發量較大網路IO的解決方案,它的內部其實是通過執行緒池去併發處理各個請求,那麼是不是意味著普通BIO和NIO中加入執行緒池就可以替代AIO呢?毋庸置疑不是的,BIO 和 NIO 的使用中加執行緒池不是什麼好主意,因為有channel的限制,所以AIO這套框架並沒有白做。
  1. IO:普通的IO,每次操作stream,都需要和磁碟互動,效率最低
  1. BIO:一個連線一個執行緒,客戶端有連線請求時伺服器端就需要啟動一個執行緒進行處理,如果這個連線不做任何事情會造成不必要的執行緒開銷,當然可以通過執行緒池機制改善
  1. NIO:一個請求一個執行緒,通過selector對多個channel監聽,並統一響應和處理,selector輪詢到連線有I/O請求時才啟動一個執行緒進行處理
  1. AIO:一個請求一個執行緒,客戶端的I/O請求都是由OS先完成(將IO直接讀到緩衝區)了再通知伺服器應用去啟動執行緒進行處理,但沒有selector的概念,併發情況下效率高於NIO
以下是幾種IO的技術架構圖
BIO
在這裡插入圖片描述
NIO
在這裡插入圖片描述
AIO
在這裡插入圖片描述
NIO和BIO的區別

在這裡插入圖片描述

接下來上程式碼

  • 普通IO

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.PushbackInputStream;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Date;
import java.util.zip.ZipInputStream;

/**
 * 位元組IO
 */
 public class IOByteStream {
	public static void main(String[] args) {
		File fin = new File("C:\\Users\\Administrator\\Desktop\\test\\J0.java");
		File fout = new File("C:\\Users\\Administrator\\Desktop\\test\\J1.java");

		level1(fin, fout);
		level2(fin);
		level4Object(fout);
	}

	public static void level1(File fin, File fout) {
		try (
				FileInputStream fis = new FileInputStream(fin);
				BufferedInputStream bis = new BufferedInputStream(fis);
				FileOutputStream fos = new FileOutputStream(fout, false);
				BufferedOutputStream bos = new BufferedOutputStream(fos);
				) {
			System.out.println("stream markSupported - " + fis.markSupported());
			System.out.println("buffer markSupported - " + bis.markSupported());
			//mark後讀取超過readlimit位元組資料,mark標記就會失效
			bis.mark(40960);
			byte[] b = new byte[1024];
            int i = 0;
            while ((i = bis.read(b)) > 0) {
            	bos.write(b, 0, i);
            }
            bos.flush();
            
            bis.reset();
			byte[] b2 = new byte[1024];
            int i2 = 0;
            while ((i2 = bis.read(b2)) > 0) {
            	bos.write(b2, 0, i2);
            }
            bos.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void level2(File f) {
		try (
				FileInputStream fis = new FileInputStream(f);
				BufferedInputStream bis = new BufferedInputStream(fis);
				PushbackInputStream pbis = new PushbackInputStream(bis);
				DataInputStream dis = new DataInputStream(pbis);
				) {
			int s1 = dis.read();System.out.println(s1);
			pbis.unread(s1);
			int s2 = dis.read();System.out.println(s2);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void level3Zip(File f) {
		try (
				FileInputStream fis = new FileInputStream(f);
				BufferedInputStream bis = new BufferedInputStream(fis);
				ZipInputStream zis = new ZipInputStream(bis);
				PushbackInputStream pbis = new PushbackInputStream(zis);
				DataInputStream dis = new DataInputStream(pbis);
				) {
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void level4Object(File f) {
		try (
				FileOutputStream fos = new FileOutputStream(f, true);
				BufferedOutputStream bos = new BufferedOutputStream(fos);
				ObjectOutputStream oos = new ObjectOutputStream(bos);
				) {
			Object o = new Object();
			oos.writeObject(o);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

/**
 * 字元IO
 */
class IOCharStream {
	public static void main(String[] args) {
		File f = new File("C:\\Users\\Administrator\\Desktop\\test\\J0.java");
		File f2 = new File("C:\\Users\\Administrator\\Desktop\\test\\J1.java");
		level2(f2);
		level1(f);
	}
	
	public static void level1(File f) {
		try (
				FileInputStream fis = new FileInputStream(f);
				InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
				BufferedReader br = new BufferedReader(isr);
				) {
			br.lines().forEach(line -> System.out.println(line));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	
	public static void level2(File f) {
		try (
				FileOutputStream fos = new FileOutputStream(f, true);
				OutputStreamWriter osw = new OutputStreamWriter(fos);
				BufferedWriter bw = new BufferedWriter(osw);
				PrintWriter pw = new PrintWriter(osw, true);
				) {
			pw.print("abcs");
			pw.println("ab");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}

/**
 * NIO讀寫
 */
class NIOStream {
	public static void main(String[] args) {
		File fin = new File("C:\\Users\\Administrator\\Desktop\\test\\J0.java");
		File fout = new File("C:\\Users\\Administrator\\Desktop\\test\\J1.java");
		level1(fin, fout);
	}
	
	public static void level1(File fin, File fout) {
		try (
				RandomAccessFile fis = new RandomAccessFile(fin, "rw");
				FileChannel channelIn = fis.getChannel();
				RandomAccessFile fos = new RandomAccessFile(fout, "rw");
				FileChannel channelOut = fos.getChannel();
				) {
			Charset charset = Charset.forName("UTF-8");//Java.nio.charset.Charset處理了字元轉換問題。它通過構造CharsetEncoder和CharsetDecoder將字元序列轉換成位元組和逆轉換。  
	        CharsetDecoder decoder = charset.newDecoder();
			MappedByteBuffer byteBufferIn = channelIn.map(FileChannel.MapMode.READ_WRITE, 0, channelIn.size());
			channelOut.write(byteBufferIn);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
/**
 * 三種流之間的對比
 */
class CompareWithStream {
	public static void main(String[] args) {
		File fin = new File("C:\\Users\\Administrator\\Desktop\\test\\J0.java");
		File fout = new File("C:\\Users\\Administrator\\Desktop\\test\\J1.java");

		level1NoBuffer(fin, fout);	// 普通IO 讀寫5000次 耗時12毫秒
		level1buffer(fin, fout);	// 緩衝IO 讀寫5000次 耗時13毫秒
		level1NIO(fin, fout);		// NIO 讀寫5000次 耗時70毫秒
	}
	
	public static void level1NoBuffer(File fin, File fout) {
		try (
				FileInputStream fis = new FileInputStream(fin);
				FileOutputStream fos = new FileOutputStream(fout, false);
				) {
			byte[] b = new byte[1024];
			long time3 = new Date().getTime();
			for (int i = 0; i < 5000; i++) {
	            int c = 0;
	            while ((c = fis.read(b)) > 0) {
	            	fos.write(b, 0, c);
	            }
	            fos.flush();
			}
			long time4 = new Date().getTime();
			System.out.println("普通IO:" + (time4 - time3));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void level1buffer(File fin, File fout) {
		try (
				FileInputStream fis = new FileInputStream(fin);
				BufferedInputStream bis = new BufferedInputStream(fis);
				FileOutputStream fos = new FileOutputStream(fout, false);
				BufferedOutputStream bos = new BufferedOutputStream(fos);
				) {
			byte[] b = new byte[1024];
			long time1 = new Date().getTime();
			for (int i = 0; i < 5000; i++) {
	            int c = 0;
	            while ((c = bis.read(b)) > 0) {
	            	bos.write(b, 0, c);
	            }
	            bos.flush();
			}
			long time2 = new Date().getTime();
			System.out.println("緩衝IO:" + (time2 - time1));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void level1NIO(File fin, File fout) {
		try (
				RandomAccessFile fis = new RandomAccessFile(fin, "rw");
				FileChannel channelIn = fis.getChannel();
				RandomAccessFile fos = new RandomAccessFile(fout, "rw");
				FileChannel channelOut = fos.getChannel();
				) {
			long time5 = new Date().getTime();
			for (int i = 0; i < 5000; i++) {
				MappedByteBuffer byteBufferIn = channelIn.map(FileChannel.MapMode.READ_WRITE, 0, channelIn.size());
				channelOut.write(byteBufferIn);
			}
			long time6 = new Date().getTime();
			System.out.println("磁碟對映IO:" + (time6 - time5));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

  • BIO

服務端



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服務端
 */
public final class ServerNormal {
	//預設的埠號
	private static int DEFAULT_PORT = 12345;
	//單例的ServerSocket
	private static ServerSocket server;
	//根據傳入引數設定監聽埠,如果沒有引數呼叫以下方法並使用預設值
	public static void start() throws IOException{
		//使用預設值
		start(DEFAULT_PORT);
	}
	//這個方法不會被大量併發訪問,不太需要考慮效率,直接進行方法同步就行了
	public synchronized static void start(int port) throws IOException{
		if(server != null) return;
		try{
			//通過建構函式建立ServerSocket
			//如果埠合法且空閒,服務端就監聽成功
			server = new ServerSocket(port);
			System.out.println("PID:"+ Thread.currentThread().getId()+ " 伺服器已啟動,埠號:" + port);
			//通過無限迴圈監聽客戶端連線
			//如果沒有客戶端接入,將阻塞在accept操作上。
			while(true){
				Socket socket = server.accept();
				//當有新的客戶端接入時,會執行下面的程式碼
				//然後建立一個新的執行緒處理這條Socket鏈路
				new ServerHandler(socket).run();
			}
		}finally{
			//一些必要的清理工作
			if(server != null){
				System.out.println("伺服器已關閉。");
				server.close();
				server = null;
			}
		}
	}
	public static void main(String[] args) {
		try {
			start();
			System.out.println("I have been out.");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	
            
           

相關推薦

Java IO 程式設計(BIO、NIO、AIO完整例項程式碼)

      本文會從傳統的BIO到NIO再到AIO自淺至深介紹,並附上程式碼講解。   原始碼地址: https://github.com/kkman2008/java-IO.git     下面程式碼中會使用這樣一個

Java IO程式設計

Java IO       Java有非常豐富的IO介面,從流型別可劃分為位元組流和字元流,從流操作的位置可劃分為網路IO和本地IO。 本地IO 本地IO時,普通IO和BIO

java IO程式設計(一)檔案操作類:File

        學習過程中某個知識點長時間不用老是忘記,在此記錄,下次忘記容易複習。                 在java.io包中,如果要進行檔案自身的操作(例如:建立、刪除等),只能依靠java.io.File類完成。File類中的常用方法在下表中列出 File

[面試要點]java io程式設計

java io 簡介 慣例先祭出一張圖 [1]輸入位元組流InputStream:InputStream 是所有的輸入位元組流的父類,它是一個抽象類;ByteArrayInputStream、StringBufferInputStream、FileInp

Java IO程式設計[轉載]

什麼是IO   IO(Input/Output)是計算機輸出/輸出的介面。Java的核心庫java.io提供了全面的IO介面,包括:檔案讀寫,標準裝置輸出等等。Java中IO是以流為基礎進行輸入輸出的,所有資料被序列化寫入輸出流,或者從輸入流讀入。此外,Java也對塊傳輸

Java IO程式設計——File檔案操作類

   在Java語言裡面提供有對於檔案作業系統操作的支援,而這個支援就在java.io.File類中進行了定義,也就是說在整個java.io包裡面,File類是唯一 一個與檔案本身操作(建立、刪除、重新命名等)有關的類,而如果要想進行File類的操作,必須要提供有完整的路徑,而後可以呼叫相

Java IO程式設計——字元流與位元組流

在java.io包裡面File類是唯一 一個與檔案本身有關的程式處理類,但是File只能夠操作檔案本身而不能夠操作檔案的內容,或者說在實際的開發之中IO操作的核心意義在於:輸入與輸出操作。而對於程式而言,輸入與輸出可能來自於不同的環境,例如:通過電腦連線伺服器上進行瀏覽的時候,實際上此時客戶端發出了一個資訊,

Java 網路IO程式設計

什麼是Socket Socket是應用層與TCP/IP協議族通訊的中間軟體抽象層,它是一組介面。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket介面後面,對使用者來說,一組簡單的介面就是全部,讓Socket去組織資料,以符合指定的協議。 如下

Java基礎篇-File IO程式設計

如果自學時候 對於IO可能會有恐懼感 如果要學好IO 必須清楚抽象類? 為什麼 IO的操作部分,重點掌握兩個程式碼模型 IO核心組成: 五個類: File OutputStream InputStream Writer Reader File類詳解 在java.io當中 File類是唯一一個與檔案本身

33 JAVA程式設計思想——JAVA IO File類

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

JAVA入門到精通-第46講-IO程式設計.記事本開發

IO程式設計-記事本開發 fis.read(bytes) 位元組陣列: 通過fis把檔案裡面的1800個字元,儘可能的讀, 最多讀1024個。記錄一下,0-1024記錄到bytes; 再去讀的首,fis.read試圖1024個位元組,不夠了,

JAVA入門到精通-第45講-IO程式設計

image1=ImageIO.read(new File("bomb_1.gif")); 圖片拷貝: 輸入流和輸出流同時要用的問題: 圖片讀入到記憶體; 寫入,輸出到某個檔案; 二進位制檔案,位元組流完成; FileInputStream fis

JAVA入門到精通-第44講-IO程式設計

//FileOutputStream的使用 準備把它輸出到d:\\ss.txt 檔案, 檔案不存在直接建立; 如果存在,可能會被覆蓋; //位元組流 FileOutputStream fos=null; //輸出-Output-離開記憶體-

Java程式設計思想(五)第18章-Java IO系統

目錄: 1 File類   File(檔案)類這個名字有一定的誤導性;我們可能會認為它指代的是檔案,實際上卻並非如此。它既能代表一個特定檔案的名稱,又能代表一個目錄下的一組檔案的名稱。實際上,FilePath(檔案路徑)對這個類來說是更好的名字。   如果它指的

Java 高階程式設計-IO程式設計,物件序列化&反序列化

1. 物件序列化基本概念 2. 序列化與反序列化 3. transient關鍵字 學習阿里雲大學零基礎學Java系列 Java高階程式設計

Java 高階程式設計-IO操作深入

1. 字元編碼 2. 記憶體操作流 3. 管道流 4. RandomAccessFile隨機儲存類 學習阿里雲大學零基礎學Java系列 Java高階程式設計 1. 字元編碼 在計算機的世界裡面只認

Java 高階程式設計-IO位元組流與字元流

1. 簡介 2. 位元組輸出流OutputStream 3. 位元組輸入流InputStream 4. 字元輸出流Writer 5. 字元輸入流Reader 6. 位元組流與字元流的區別 7. 轉

34 JAVA程式設計思想——JAVA IO 流典型應用

                34.JAVA程式設計思想——JAVA IO 流典型應用儘管庫記憶體在大量IO 流類,可通過多種不同的方式組合到一起,但實際上只有幾種方式才會經常用到。然而,必須小心在意才能得到正確的組合。下面這個相當長的例子展示了典型IO 配置的建立與使用,可在寫自己的程式碼時將其作為一個參

Java 網路IO程式設計總結(BIO、NIO、AIO均含完整例項程式碼)

第一段內容轉載自:http://blog.51cto.com/stevex/1284437 先來個例子理解一下概念,以銀行取款為例: 同步 : 自己親自出馬持銀行卡到銀行取錢(使用同步IO時,Java自己處理IO讀寫)。 非同步

Java基礎:java網路程式設計IO總結(BIO、NIO、AIO)

1.基本概念 在Java網路通訊中,最基本的概念就是Socket程式設計了。Socket又稱“套接字” 向網路發出請求或者應答網路請求。 Socket 和ServerSocket類庫位於 Java.net 包中。ServerSocket用於伺服器端,Socket是建立網路連線時使用的