中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java-IO操作簡介

發布時間:2020-07-12 04:34:44 來源:網絡 閱讀:336 作者:棲木之地 欄目:編程語言

流:字節流和字符流
字節流:處理二進制數據,用于處理原始數據,不應該用來處理文本內容
字符流:處理字符數據,自動轉換本地字符集
行尾結束符: \r\n 或者\r 或者\n
對象流:處理對象二進制數據
需要對流進行關閉:
字符流操作:Reader,Writer
字節流操作:InputStream,OutputStream
Channel,GatheringByteChannel,InterruptibleChannel
ReadableByteChannel,ScatteringByteChannel,WritableByteChannel
Channels, DatagramChannel,FileChannel,FileLock,Pipe
SelectableChannel,SelectionKey,Selector,ServerSocketChannel,SocketChannel

中文兩個字節,英文1個字節,一個字節8bit,高位補零
字節流不會使用內存緩沖,文件本身直接操作
字符流操作使用內存緩沖,用緩沖操作文件,字符流在輸出前將內容保存在內容中

主要有四類操作:
1:字節操作:InputStream和OutputStream
2:字符操作:Reader和Writer
3:磁盤操作:File
4:網絡操作:Socket

無論是網絡還是磁盤,存儲單元都是字節,字符是在字節的基礎上進行了轉換:
InputStreamReader
拿到字節數據后,要指定編碼字符集,否則采用的是系統默認的字符集

磁盤IO機制:
系統在內核空間中加入了緩存機制,如果用戶訪問的是同一磁盤地址的空間數據,那么會從緩存中返回
標準訪問方式:
調用read時,操作系統檢查內核緩存中有沒有數據,如果沒有則從磁盤讀取并緩存到內核緩存
調用write時:先復制到緩存中,對于用戶來說操作已經完成,什么時候寫入磁盤由操作系統決定
直接IO方式:
應用直接訪問磁盤,不經過系統內核數據緩存區,通常使用在數據庫管理系統中
同步訪問方式:讀取和寫入都是同步操作,寫入經過高速緩存然后進入磁盤,讀取經過磁盤到高速緩存
異步訪問方式:發起讀寫請求后,線程去處理其他的,等待高速緩存從磁盤讀取回來后再操作
內存映射方式:把內存的一塊區域和文件關聯起來,文件的數據就是內存中的數據

FileInputStream會創建一個FileDescriptor對象,這個對象是真正代表一個存在的文件對象的描述
可以通過getFD犯法獲取真正操作與底層操作系統相關的文件的描述

傳入文件名時,創建一個File對象。讀取File對象內容時,創建一個FileDescriptor操作,使用StreamDecoder類將byte解碼成char格式。然后返回char數據

Java序列化技術:java序列化就是將一個對象轉換成一串二進制字節數組。這樣,對象就能保存和傳輸,進行持久化。對象需要實現Serializable接口
序列化的二進制數組主要包含5個部分內容:
1:序列化文件頭:使用的序列化協議,序列化協議,該數組的類型(比如說是一個對象)
2:序列化類的描述,比如是Serialize類。包含一個類聲明,class名字長度,完整類名,序列化ID,如果沒有指定則生成一個8字節的ID,還有該類的字段個數
3:對象中各個屬性項的描述
4:該對象的父類信息描述
5:該對象的屬性項的實際值。

序列化的復雜情況:
1:父類實現Serializable接口時,所有子類都可以被序列化
2:子類實現Serializable接口,而父類沒有實現,則父類屬性不能被序列化,不報錯,數據丟失,子類仍然能序列化。
3:如果序列化的對象的屬性也是對象,那么子對象也需要實現序列化接口,否則報錯
4:反序列化時,對象的屬性有修改或刪減,則修改部分的屬性會丟失,但不會報錯
5:反序列化時,如果serialVersionUID被修改,則反序列化時會失敗

TCP連接:
TCP狀態:
CLOSED:
LISTEN:等待連接狀態
SYN-SENT:客戶端發起連接,發送SYN給服務器,如果接受不到則直接進入CLOSED
SYN-RCVD:服務器接收請求,返回ACK響應
ESTABLISHED:服務器端和客戶端在完成3次握手后進入該狀態,說明可以傳輸數據了
FIN-WAIT-1:發送FIN給對方
FIN-WAIT-2:接收FIN ACK數據
CLOSE-WAIT:
LAST-ACK:發起關閉請求
CLOSING
TIME-WAIT:

closed--->listen :被動打開
closed--->syn-send:主動打開,發送SYN
listen->syn-received:收到syn,發送syn-ack
syn-send->syn-received:同時打開,收到syn,發送syn-ack
syn-received-------->established:收到ack
syn-send---------->established:收到syn-ack,發送ack
established-------->FIN-WAIT1:關閉,發送FIN
FIN-WAIT1-------->FIN-WAIT2:收到對FIN的ACK
FIN-WAIT2------->TIME-WAIT:收到FIN,發送ACK
FIN-WAIT1------>CLOSING:收到FIN,發送ACK,同時關閉
CLOSING------->TIME-WAIT:收到對FIN的應答
ESTABLISHED-------->CLOSE-WAIT:收到FIN,發送ACK
CLOSE-WAIT--------->LAST-ACK:等待應用程序關閉,發送FIN
LAST-ACK------------>CLOSED:收到對FIN的ACK

影響網絡傳輸因素:
1:帶寬:1秒傳輸最大比特數
2:傳輸距離:光纖的折射率導致有傳輸延遲。
3:TCP擁堵:停-等-停-等

NIO工作方式:非阻塞IO
一旦發生阻塞,線程就會失去CPU的使用權,在大規模訪問下是不能允許的。

工作過程:
0:創建一個ByteBuffer來獲取數據
ByteBuffer buffer = ByteBuffer.allocate(1024);
1:Selector靜態工廠方法創建一個選擇器selector
Selector selecotr = Selector.open();
2:創建一個服務器端的Channel,然后綁定到一個Socket對象,并注冊到selector上
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);//非阻塞模式
ssc.socket.bind(new InetSocketAddress(8080));
ssc.register(selector,SelectionKey.OP_ACCEPT);//注冊監聽事件
3:調用selector的selectedKeys方法來檢查是否有事件發生,如果有事件發生則返回SelectionKey,通過這個對象的Channel方法獲得通信信道對象:
Set selectedKeys = selector.selectedKeys();
SelectionKey key = 遍歷selectedKeys
if(key.readOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT){
ServerSocketChannel ssChannel = (ServerSocketChannel) key.channel();
SocketChannel sc = ssChannel.accept();//
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ)
} else if((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
SocketChannel sc = (SocketChannel) key.channel();
sc.read(buffer);
buffer.flip();
}

RAID策略:
RAID0:數據被平均寫入多個磁盤陣列,寫數據和讀數據都是并行的,所以磁盤的IOPS可以提高一倍
RAID1:將一份數據復制到多個磁盤陣列中,不能提高IOPS,但能提高安全性
RAID5:前兩種方式的折中。將數據平均寫到所有磁盤陣列總數減1的磁盤中,往另外一個磁盤中寫入這份數據的奇偶校驗信息。如果其中一個磁盤數據損壞,可以通過其他磁盤的數據和這個數據的奇偶校驗信息來恢復這份數據。
RAID0+1:根據數據的備份情況進行分組,一份數據同時寫入多個備份磁盤分組中,同時多個分組也會進行并行讀寫。

java中操作字符的Reader和Writer中有StreamDecoder,StreamEncoder,負責字符和字節的轉換。
內存中的編碼:在內存中進行從字符到字節的轉換。String類提供了getBytes(字符集)來轉換
和new String(bytes, 字符集);
已經廢棄的ByteToCharConverter和CharToByteConverter,使用Charset取代,Charset提供encode和decode方法
還有一個ByteBuffer類,提供char和byte的軟交換,他們之間的轉換不需要編碼,僅僅只是把一個16bit的char拆分成2個8bit的byte表示。

java內存編碼使用的是utf-16編碼,效率高,但不利于網絡之前傳輸。
因為網絡傳輸容易損壞字節流,字節流損壞將很難恢復,所以相比較utf-8更適合網絡傳輸。
utf-8對ascii字符使用單字節存儲,另外單個字符損壞也不會影響后面的其他字符。是理想的編碼方式。

大多數IO都是沒有緩沖的,這意味著每個讀寫請求都是底層OS直接處理的。這讓程序比較低效,因為每次請求都會觸發磁盤訪問,網絡活動或一些相對昂貴的操作
為了減少這種類型的開銷,java平臺實現緩沖IO stream。緩沖的輸入流從內存區域讀取數據作為buffer,僅當buffer為空的時候,才會調用原生輸入api。類似的,緩沖的輸出流寫入數據到一個buffer,當buffer滿了的時候原生輸出api才會被調用。
flush緩沖流:在關鍵點寫出緩沖區而不需要等它填充是有意義的。這個被稱為flush
一些緩沖輸出類支持自動flush,通過構造參數指定一個選項。當自動刷新開啟,特定關鍵事件會導致緩沖會被flush

NIO:
標準IO是面向字節流和字符流的,而NIO是面向通道和緩沖區的,數據總是從通道中讀到buffer緩沖區內,或者從buffer寫入通道
核心組件:
Channels:Buffer的數據從Channel中讀取或寫入
FileChannel,DatagramChannel,SocketChannel,ServerSocketChannel
Buffers:實際就是一個塊內存,有三個主要屬性:capacity容量,position位置,limit限制
ByteBuffer,CharBuffer,DoubleBuffer,FloatBuffer,IntBuffer,LongBuffer,ShortBuffer

Selectors:選擇器允許單線程操作多個通道,Channel需要注冊到Selector上

RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
FileChannel inChannel = aFile.getChannel();
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf);
buf.flip(); //make buffer ready for read
while(buf.hasRemaining()){
System.out.print((char) buf.get()); // read 1 byte at a time
}
buf.clear(); //make buffer ready for writing
bytesRead = inChannel.read(buf);

FileChannel類型可以把數據直接傳輸到另一個channel上:
兩個都是FileChannel:
aChannel.transferFrom(bChannel);
aChannel.transferTo(bChannel);

注冊selector:
Selector selector = Selector.open();
channel.configureBlocking(false);
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);

Unrecognized Windows Sockets error: 0: recv failed:
socket連接中有數據未處理

=================
編寫Socket服務器:
只需要返回http協議中的內容即可
BufferedOutputStream outputStream = new BufferedOutputStream(socket.getOutputStream());
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
writer.write("HTTP/1.1 200 OK");
writer.newLine();
writer.write("Server: Apache-Coyote/1.1");
writer.newLine();
writer.write("Content-Type: text/html;charset=UTF-8");
writer.newLine();
String body = "<html><head></head><body>1234</body></html>";
writer.write("Content-Length: " + body.length());
writer.newLine();
writer.write("Date: Mon, 03 Nov 2014 06:37:28 GMT");
writer.newLine();
writer.write("\n" + body);
writer.flush();
writer.close();
在body處需要\n,否則瀏覽器不能正確識別響應實體
在讀取請求的數據時,只能判斷最后的內容為空字符串,不能判斷為null
ServerSocket serverSocket = new ServerSocket(1099);
Socket socket = serverSocket.accept();
BufferedInputStream inputStream = new BufferedInputStream(socket.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String lineStr = null;
while (!(lineStr=reader.readLine()).equals("")){
System.out.println(lineStr);
}

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

保定市| 鹤峰县| 蓬莱市| 沁源县| 潢川县| 湖南省| 滁州市| 密山市| 卢龙县| 织金县| 巫溪县| 通化县| 贞丰县| 泉州市| 贡山| 炎陵县| 和田县| 东兰县| 大连市| 铜梁县| 霍林郭勒市| 中西区| 济南市| 四川省| 威宁| 深泽县| 建阳市| 营山县| 南川市| 江永县| 公安县| 泌阳县| 桓台县| 大石桥市| 兴义市| 汶上县| 瑞金市| 长春市| 喀什市| 桂平市| 商都县|