一篇文章帶你深入了解javaIO基礎(chǔ)
一.認(rèn)識(shí)IO
1.IO的分類
(1)BIO:同步阻塞IO
(2)NIO:同步非阻塞IO
(3)AIO:異步阻塞IO
注意: 這里主要介紹BIO
2.IO的方式
IO本質(zhì)就是對(duì)數(shù)據(jù)的操作
(1)網(wǎng)絡(luò)IO
(2)本地IO
3.IO讀寫的方式
4.IO的特性
(1)本質(zhì)上屬于數(shù)據(jù)傳輸
(2)涉及兩個(gè)設(shè)備間的傳輸方向(一般,自己寫java程序的時(shí)候,只關(guān)注自己程序的一方)
(3)數(shù)據(jù)流
(4)java進(jìn)程的IO操作,對(duì)進(jìn)程的影響:
- 1.阻塞IO 會(huì)導(dǎo)致進(jìn)程在運(yùn)行態(tài)和阻塞態(tài)之間轉(zhuǎn)變,由操作系統(tǒng)完成后序的IO操作
- 2.java進(jìn)程,在內(nèi)核態(tài)和用戶態(tài)之間切換:性能會(huì)收到影響(下降)
(5)IO緩沖流
不使用緩沖流:java程序每次都從主機(jī)內(nèi)存讀寫數(shù)據(jù),每次都直接讀取數(shù)據(jù)/發(fā)送數(shù)據(jù)。write()/read()
使用/不使用緩沖區(qū)的區(qū)別:
例如:循環(huán)10000次,每次write1個(gè)字節(jié)數(shù)據(jù)到本地文件
不使用緩沖區(qū):每次循環(huán)都是IO操作,都涉及進(jìn)程狀態(tài)由運(yùn)行態(tài)變?yōu)樽枞麘B(tài),由用戶態(tài)變?yōu)閮?nèi)核態(tài)(10000次影響)
使用緩沖區(qū):每次write復(fù)制數(shù)據(jù)到緩沖區(qū),flush才算IO操作(一定要記得)(一次影響)性能更好
二.文件操作
1.文件的構(gòu)成
(1)文件的頭信息(Metadata)
(2)文件的內(nèi)容
注意: java.io.File 不是對(duì)文件的內(nèi)容操作,知識(shí)對(duì)文件本身或者頭信息操作
2.文件的創(chuàng)建
new操作時(shí)的注意事項(xiàng):
- 1.既可以指定文件,也可以指定文件夾
- 2.通過路徑創(chuàng)建File:可以使用絕對(duì)路徑/相對(duì)路徑
- 3.不管路徑上是否存在這個(gè)文件/文件夾,java都可以創(chuàng)建得到一個(gè)File對(duì)象(但是對(duì)這個(gè)File操作時(shí),可能會(huì)拋出異常)
3.文件操作的API使用
文件操作示例:遍歷某個(gè)目錄下,所有的子文件/子文件夾
public static void main(String[] args) { File file=new File("C:\\Users\\26905\\Desktop\\javaCode"); List<File> list=listDir(file); // for (int i = 0; i <list.size() ; i++) { // System.out.println(list.get(i)); // } //jdk1.8集合框架使用Stream操作,可以使用lambda表達(dá)式打印 list.stream().forEach(System.out::println); }
方法一: 效率不高
public static List<File> listDir(File dir){ List<File> list=new ArrayList<>(); if(dir.isFile()){ list.add(dir);//效率不太好的地方,如果是文件,返回的list只存放一個(gè)元素 }else { File[] children=dir.listFiles(); for(File file:children){ List<File> files=listDir(file); list.addAll(files); } } return list; }
方法二: 效率較高
public static List<File> listDir2(File dir){ List<File> list=new ArrayList<>(); if(dir.isDirectory()){ //獲取目錄下一級(jí)的子文件和子文件夾 File[] children=dir.listFiles(); if(children!=null){ for(File file:children){ if(file.isDirectory()){ //如果子文件還是文件夾,遞歸調(diào)用 list.addAll(listDir2(file)); }else{ list.add(file); } } } } return list; }
三.IO流
1.流的分類
2.流的創(chuàng)建
3.流的使用
<1>輸入流
import java.io.*; public class FileInput { /** * 字節(jié)文件:C:\Users\26905\Desktop\畫圖筆記\JavaWeb\JSON和ajax簡單介紹.png * 字符文件:C:\Users\26905\Desktop\論文,ppt,作業(yè),筆記,圖片等\java筆記.txt * @param args */ public static void main(String[] args) throws IOException { //圖片文件,以二進(jìn)制的方式操作 File file1=new File("C:\\Users\\26905\\Desktop\\畫圖筆記\\JavaWeb\\JSON和ajax簡單介紹"); File file =new File("C:\\Users\\26905\\Desktop\\論文,ppt,作業(yè),筆記,圖片等\\比特草稿本.txt"); //1.文件輸入字節(jié)流 FileInputStream fis=new FileInputStream(file); //不知道文件有多 大,先定義一個(gè)一定大小的字節(jié)數(shù)組,然后不停讀入,每次刷新以下就好 byte[] bytes=new byte[1024*8]; //輸入流讀取的固定寫法:讀取到一個(gè)字節(jié)/字符數(shù)組,定義read的返回值變量,while int len=0; //len表示讀入字節(jié)的長度 //如果不等于-1,說明讀取未結(jié)束 while ((len=fis.read(bytes)) !=-1){ //讀取到的長度,數(shù)組可能讀滿,也可能沒有讀滿 //當(dāng)次讀取,一般使用數(shù)組[0,len]表示讀取內(nèi)容 //字節(jié)數(shù)組轉(zhuǎn)字符串 String str=new String(bytes,0,len); // System.out.println(str); } //一般來說,輸入輸出流使用完,一定要關(guān)閉,關(guān)閉的關(guān)系是反向關(guān)系 //例如:創(chuàng)建的時(shí)候是從里往外創(chuàng)建,則關(guān)閉的時(shí)候就是從外往內(nèi)關(guān)閉 fis.close(); //2.文件的字符輸入流 FileReader fr=new FileReader(file); char []chars=new char[1024]; int lenFr=0; while ((lenFr=fr.read(chars))!=-1){ String strFr=new String(chars,0,lenFr); //System.out.println(strFr); } fr.close(); //3.緩沖流:緩沖字節(jié)輸入,緩沖字符輸入 FileInputStream FIS=new FileInputStream(file);//文件字節(jié)輸入流 //字節(jié)流轉(zhuǎn)字符流一定要經(jīng)過字節(jié)字符轉(zhuǎn)換流來轉(zhuǎn)換,并且還可以指定編碼 InputStreamReader isr=new InputStreamReader(FIS); //緩沖流 BufferedReader br=new BufferedReader(isr); String str; //讀取,當(dāng)字符串為空時(shí),結(jié)束 while ((str=br.readLine()) !=null){ System.out.println(str); } br.close(); isr.close(); FIS.close(); } }
<2>輸出流
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; public class FileOutput { public static void main(String[] args) throws IOException { /** * D:\java代碼\1.txt */ //路徑上沒有該文件,new File不會(huì)報(bào)錯(cuò),但是在操作輸出流會(huì)拋出FileNotFoundException File file2=new File("D:\\java代碼\\1.txt"); //把a(bǔ)-z換行輸出到某個(gè)文件,需要考慮文件是否存在的問題 if(!file2.exists()){ file2.createNewFile(); } //new FileWriter() 文件的不帶緩沖的字符輸出 //new FileWriter() 文件的不帶緩沖的字節(jié)輸出 //new BufferedWriter() 帶緩沖的字符輸出 //new PrintWriter() 打印輸出流 //緩沖的字符輸出 // BufferedWriter bw=new BufferedWriter(new FileWriter(file2)); // bw.write("\n"); //打印輸出流 //PrintWriter pw=new PrintWriter(new FileWriter(file)); PrintWriter pw =new PrintWriter(new FileOutputStream(file2)); //快速打印a-z for (int i = 'a'; i <='z' ; i++) { pw.println((char)i); } pw.flush(); } }
<3>實(shí)例:文件的復(fù)制
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class FileCopy { public static void main(String[] args) throws IOException { //文件復(fù)制 File input=new File("D:\\java代碼\\1.txt"); File output=new File("D:\\java代碼\\2.txt"); if(!output.exists()){ output.createNewFile(); } //定義輸入輸出流 //輸入流 FileInputStream fis=new FileInputStream(input); // 輸出流 FileOutputStream fos=new FileOutputStream(output); byte[]bytes=new byte[1024*8]; int len; while ((len=fis.read(bytes))!=-1){//每次從輸入流讀取到byte[]的內(nèi)容,直接輸出到某個(gè)文件,就是復(fù)制 //bytes可能沒存滿,需要指定長度 fos.write(bytes,0,len); } fis.close(); fos.close(); } }
總結(jié)
本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Java實(shí)現(xiàn)多用戶注冊登錄的幸運(yùn)抽獎(jiǎng)
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)多用戶注冊登錄的幸運(yùn)抽獎(jiǎng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11SpringBoot 圖書管理系統(tǒng)(刪除、強(qiáng)制登錄、更新圖書)詳細(xì)代碼
在企業(yè)開發(fā)中,通常不采用delete語句進(jìn)行物理刪除,而是使用邏輯刪除,邏輯刪除通過修改標(biāo)識(shí)字段來表示數(shù)據(jù)已被刪除,方便數(shù)據(jù)恢復(fù),本文給大家介紹SpringBoot 圖書管理系統(tǒng)實(shí)例代碼,感興趣的朋友跟隨小編一起看看吧2024-09-09SpringBoot應(yīng)用啟動(dòng)內(nèi)置Tomcat的過程源碼分析
這篇文章主要介紹了SpringBoot應(yīng)用啟動(dòng)內(nèi)置Tomcat的過程分析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-07-07Java集合框架之List ArrayList LinkedList使用詳解刨析
早在 Java 2 中之前,Java 就提供了特設(shè)類。比如:Dictionary, Vector, Stack, 和 Properties 這些類用來存儲(chǔ)和操作對(duì)象組。雖然這些類都非常有用,但是它們?nèi)鄙僖粋€(gè)核心的,統(tǒng)一的主題。由于這個(gè)原因,使用 Vector 類的方式和使用 Properties 類的方式有著很大不同2021-10-10詳解Java動(dòng)態(tài)代理的實(shí)現(xiàn)機(jī)制
這篇文章主要為大家詳細(xì)介紹了Java動(dòng)態(tài)代理的實(shí)現(xiàn)機(jī)制,感興趣的小伙伴們可以參考一下2016-03-03JAVA CountDownLatch(倒計(jì)時(shí)計(jì)數(shù)器)用法實(shí)例
這篇文章主要介紹了JAVA CountDownLatch(倒計(jì)時(shí)計(jì)數(shù)器)用法實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10詳解mall整合SpringBoot+MyBatis搭建基本骨架
這篇文章主要介紹了詳解mall整合SpringBoot+MyBatis搭建基本骨架,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Java中BigInteger類的使用方法詳解(全網(wǎng)最新)
這篇文章主要介紹了Java中BigInteger類的使用方法詳解,常用最全系列,本章作為筆記使用,內(nèi)容比較全面,但常用的只有:構(gòu)造函數(shù),基本運(yùn)算以及compareTo(),intValue(),setBit(),testBit()方法,需要的朋友可以參考下2023-05-05