I/O流
I 是 input 輸入, O 是output輸出。
BIO
輸入輸出
CPU有輸入輸出、記憶體有輸入輸出、硬碟輸入輸出、網卡有輸入輸出…
每一個硬體都是以自己為基準。
JVM是一個程式,程式又都運作于記憶體之上。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI2EzX4xSZz91ZsAzNfRHLGZkRGZkRfJ3bs92YsAjMfVmepNHLldlN1QTayVzYTFWNMlmN1cVe3UTQClGVF5UMR9Fd4VGdsATNfd3bkFGazxycykFaKdkYzZUbapXNXlleSdVY2pESa9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLlJTO1QGNmRjN5ATZyMjZhJWN1QTZ0cDZjhDO5gTYzE2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
檔案操作
Java中需要使用 File 類來進行檔案的CURD操作。
File file = new File(檔案位址);
建立檔案
public static void create() throws IOException {
File file = new File(位址);
file.createNewFile();
}
删除檔案
public static void del() {
File file = new File(檔案位址);
file.delete();
}
擷取檔案夾下的檔案
public void show() {
File files =new File("C:\\Users\\xing\\Desktop\\210901班級事宜");
for(File file : files.listFiles()) {
System.out.println("file:"+file.getName());
}
}
輸入位元組流
第一步
打開一個檔案。
File file_read =new File(位址);
第二步
把檔案的内容輸入到記憶體。
InputStream fileInputStream = new FileInputStream(file_read);
第三步
建構一個數組,準備使用這個資料擷取輸入流中的資訊。
byte bytes[] = new byte[(int) file_read.length()];//拿到檔案的長度并且建立一個字元串
第四步
使用剛才準備的數組擷取輸入流的資料。
fileInputStream.read(bytes);//使用剛才的位元組組擷取檔案内容
第五步
輸出到控制台。
String str =new String(bytes);//把字元組轉換成String
System.out.println(str);
第六步
關閉。
fileInputStream.close();
案例
public void show1() throws Exception{
File file = new File("C:\\Users\\0924\\wenben.txt");
FileInputStream fileInputStream = new FileInputStream(file);
byte bytes[] = new byte[(int) file.length()];
fileInputStream.read(bytes);
String str =new String(bytes);//把字元組轉換成String
System.out.println(str);
fileInputStream.close();
}
輸出位元組流
第一步
打開一個檔案。
File file = new File("C:\\Users\\xing\\0924\\wenben.txt");
第二步
建立一個輸出流,輸出至剛才的檔案。
FileOutputStream fileOutputStream = new FileOutputStream(file);
第三步
輸出内容至檔案。
String str = "輸出這麼一句話!";
fileOutputStream.write(str.getBytes());
第四步
關閉
fileOutputStream.close();
System.out.println("輸出完畢!");
案例
public void show5() throws Exception{
File file = new File("C:\\Users\\xing\\0924\\wenben.txt");
FileOutputStream fileOutputStream = new FileOutputStream(file);
String str = "輸出這麼一句話!";
fileOutputStream.write(str.getBytes());
fileOutputStream.close();
System.out.println("輸出完畢!");
}
拷貝檔案
第一步
下載下傳一個圖檔存在一個檔案夾。
第二步
建立一個File,使用這個 File 去讀取存放的檔案。
File file = new File("檔案存放位址");
第三步
擷取檔案的位元組輸入流。
InputStream fileInputStream = new FileInputStream(file);
第四步
建立一個數組使用數組擷取資料流的内容。
byte bytes[] = new byte[1024];
fileInputStream.read(bytes);
第五步
建立一個新的空的檔案。
File file_write =new File(具體檔案位址和名字);
注:同一個檔案夾下不能有同名的檔案
第六步
建立一個輸出流,并且準備把剛才讀取的資料輸出出去。
OutputStream outputStream = new FileOutputStream(file_write);//
outputStream.write(bytes);//使用剛才已經有内容的位元組組輸出
第七步
關閉
outputStream.close();
fileInputStream.close();
注:先開後關
字元流
字元流操作與位元組流類似。把位元組的操作換成字元的類即可,流程步驟都是位元組流的操作步驟。
public static void main(String[] args) throws Exception {
InputStream inpu;
char ch[] = new char[1024];
Reader reader = new FileReader("C:\\Users\\0924\\wenjian");
reader.read(ch);
Writer writer =new FileWriter("C:\\Users\\0924\\wenjian0");
writer.write(ch);
writer.close();
reader.close();
}
基本緩沖操作
基礎
BufferedReader 是輸入緩沖字元流。
BufferedInputStream 是輸入緩沖位元組流。
BufferedWriter 是輸出緩沖字元流。
BufferedOutputStream 是輸出緩沖位元組流。
需要把對應的輸入\輸出流放到緩沖的構造方法中:
BufferedReader br = new BufferedReader(reader);
案例
/**
* @time: 2021年9月26日上午9:59:30
* @auth: xing
* @return:void
* @description:讀取緩沖
*/
public static void main(String[] args) throws Exception {
Reader reader = new FileReader("C:\\Users\\0924\\wenjian");
BufferedReader br = new BufferedReader(reader);
String str = br.readLine();
System.out.println(str);
str = br.readLine();
System.out.println(str);
br.close();
reader.close();
//InputStream fileInputStream = new FileInputStream("C:\\Users\0924\\wenjian");
//BufferedInputStream bi = new BufferedInputStream(fileInputStream);
}
NIO
概念
NIO是New I/O的簡稱,與舊式的基于流的I/O方法相對,從名字看,它表示新的一套Java I/O标 準。它是在Java 1.4中被納入到JDK中的,并具有以下特性:
- NIO是基于塊(Block)的,它以塊為基本機關處理資料 (硬碟上存儲的機關也是按Block來存儲,這樣性能上比基于流的方式要好一些)
- 為所有的原始類型提供(Buffer)緩存支援
- 增加通道(Channel)對象,作為新的原始 I/O 抽象
- 支援鎖(我們在平時使用時經常能看到會出現一些.lock的檔案,這說明有線程正在使用這把鎖,當線程釋放鎖時,會把這個檔案删除掉,這樣其他線程才能繼續拿到這把鎖)和記憶體映射檔案的檔案通路接口
- 提供了基于Selector的異步網絡I/O
操作
- 得到Channel(管道)
- 申請Buffer(緩存空間)
- 建立Channel和Buffer的讀/寫關系
- 關閉
管道案例
使用50MB記憶體操作5G的檔案。
public static void main(String[] args) throws Exception {
FileInputStream fin = new FileInputStream("D:\\迅雷下載下傳\\shipin.mkv");
FileChannel fch = fin.getChannel();
FileOutputStream fou = new FileOutputStream("C:\\Users\\xing\\Desktop\\222.mkv");
FileChannel foh =fou.getChannel();
ByteBuffer bf = ByteBuffer.allocateDirect(102400);
int i = 0;
while(true) {
bf.clear();
int r = fch.read(bf);
bf.flip();
if(r<0) {
break;
}
foh.write(bf);
Thread.sleep(1000);
System.out.println("第:"+(++i));
}
fou.close();
fin.close();
}
緩存的三個辨別
public static void main(String[] args) throws Exception {
//讀取檔案
FileInputStream fin = new FileInputStream("C:\\Users\\xing\\Desktop\\建立文本文檔.txt");
//建立通道
FileChannel fch = fin.getChannel();
//建立一個容器10個長度
ByteBuffer bf = ByteBuffer.allocate(10);
output( "1", bf);
//讀取
fch.read(bf);
output( "2", bf);
//開始
bf.flip();
output( "3", bf);
//判斷是否還有資料可以讀取
System.out.println("b:"+new String(bf.array()));
output("4",bf);
//清空
bf.clear();
output("5",bf);
//關閉
fin.close();
}
AIO
AIO的特點:
- 讀完了再通知我
- 不會加快IO,隻是在讀完後進行通知
- 使用回調函數,進行業務處理
AIO的相關代碼:
AsynchronousServerSocketChannel
server = AsynchronousServerSocketChannel.open().bind( new InetSocketAddress (PORT));
使用server上的accept方法
server.accept(null,
new CompletionHandler<AsynchronousSocketChannel, Object>() {
final ByteBuffer buffer = ByteBuffer.allocate(1024);
public void completed(AsynchronousSocketChannel result,
Object attachment) {
System.out.println(Thread.currentThread().getName());
Future<Integer> writeResult = null;
try {
buffer.clear();
result.read(buffer).get(100, TimeUnit.SECONDS);
buffer.flip();
writeResult = result.write(buffer);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} finally {
try {
server.accept(null, this);
writeResult.get();
result.close();
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
@Override
public void failed(Throwable exc, Object attachment) {
System.out.println("failed: " + exc);
}
});
補充
注:由于LINUX對AIO的支援不好,是以AIO的使用并不多,大多數使用AIO的情況都是被Netty所替代。