1. 程式人生 > 實用技巧 >IO流的基本操作api方法 字元.位元組 輸入輸出的概念

IO流的基本操作api方法 字元.位元組 輸入輸出的概念

IO流

什麼是IO

I input 輸入(讀取) 硬碟向記憶體輸入資料

O output輸出(寫入)記憶體向硬碟寫入資料

流:資料 (位元組/字元)1個字元=2個位元組,1個位元組=8個二進位制位

IO分類

根據資料的流向分為:輸入流和輸出流

  • 輸入流:就是把資料從其他裝置上讀取到記憶體當中.

  • 輸出流,就是把資料從記憶體當中寫入到其他裝置上的流.

根據資料的型別分為:位元組流和字元流

  • 位元組流:以位元組為單位,讀寫資料的流

  • 字元流:以字元為單位,讀寫資料的流

IO流的頂級父類

輸入流輸出流
位元組流 位元組輸入流InputStream 位元組輸出流OutputStream
字元流 字元輸入流Reader 字元輸出流Writer

位元組流

一切皆為位元組

一切檔案資料(文字文件.圖片,視訊等)在儲存時,都是以二進位制數字的形式儲存的,都是一個一個的位元組,那麼資料在進行傳輸的時候也是如此.所以位元組流可以數傳任意檔案資料.在操作流程的時候,我們要明確,無論使用了什麼樣的流物件,底層傳輸的始終為二進位制資料.

位元組輸出流[OutputStream]

java.io.OutputStream此抽象類是表示輸出位元組流的所有類的超類,將指定的位元組資訊寫入到目的地,它定義了位元組輸出流的基本共性的api方法:

  • public void close():關閉此輸出流並釋放與此流相關的其他任何系統資源.

  • public void flush():重新整理此輸出流並強制任何緩衝的輸出位元組資訊被寫入.

  • public void writer(byt[] b):將b.length位元組從指定的自節陣列寫入到此輸出流中.

  • public void write(byte b,int off,int len):將指定的位元組陣列寫入len個位元組,從偏移量off開始輸出到此輸出流中

  • public abstract void write(int b):將指定的位元組輸出到此輸出流中.

備註:colose方法,當完成流的操作時,必須呼叫此方法,釋放系統資源.

FileOutputStream類

java.io.FileOutputStream類是檔案位元組輸出流,用於將資料寫入到檔案中.

構造方法
  • public FilePutStream(File file):建立一個向指定file物件則表示的檔案中寫入資料的檔案輸出流.

  • public FilePutStream(String name):建立檔案輸出流以指定的檔名稱寫入檔案中.

當你建立一個流物件時,必須西安傳遞一個檔案路徑,該路徑下,如果沒有這個檔案,會建立該檔案,如果有這個檔案.會清空這個檔案當中的資料,

FilePutOutStream作用:把記憶體當中的資料寫入到硬碟檔案中. 構造方法

  - public FilePutStream(File file):建立一個向指定file物件則表示的檔案中寫入資料的檔案輸出流.
- public FilePutStream(String name):建立檔案輸出流以指定的檔名稱寫入檔案中.
引數:
File file:目的地是一個檔案
String name:目的地是一個檔案的路徑
構造方法的作用:
1.建立一個FileOutputStream類物件
2.會根據構造方法中傳遞的檔案/檔案路徑(路徑上檔案不存在),建立一個空的檔案.
3.會把FileOutputStream物件指向建立好的檔案.
位元組輸出流的使用步驟:
1.建立一個FileOutPutStream類物件,構造方法中傳遞寫入資料的目的地.
2.呼叫FileOutPutStream物件中的write方法.把資料寫入到檔案中.
3.釋放資源.

備註;任何記事本檔案在被開啟的時候,包括儲存方式都是以位元組的方式,所以讀取的時候採用的是本地字符集,whids系統採用的是GBK.

寫入資料的原理:

java成員-->JVM(java)虛擬機器-->OS(作業系統)-->OS呼叫作業系統中的寫入資料的方法-->把資料寫入到檔案中.

示例程式碼:

//1.建立一個FileOutPutStream類物件,構造方法中傳遞寫入資料的目的地.
FileOutputStream fos = new FileOutputStream("day28_IO\\a.txt");
//2.呼叫FileOutPutStream物件中的write方法.把資料寫入到檔案中.
fos.write(97);
//3.釋放資源
fos.close();

UTF-8 一個漢字佔三個位元組,GBK 一個漢字佔兩個位元組

資料的追加續寫

如何在保留目標檔案中的資料,還能繼續新增新的資料到目標檔案中?

  • public FileOutPutStream(File file,boolean append): 建立檔案輸出流以以寫入指定的File物件表示的檔案中.

  • public FileOutputStream(String name,boolean append):建立檔案輸出流以指定的名稱寫入檔案中.

這兩個構造方法,引數都需要傳入一個boolean型別的值,'true'表示追加資料 , 'false'表示清空原有資料.在這樣的情況下建立輸出流物件,就可以指定是否需要在檔案的末尾新增.

寫入換行

Windows系統裡面,換行符號是''\r\n'.把以指定是否需要追加續寫換行

Linux系統裡,換行符號是''/n'

mac系統裡,換行符號是'/r'

Unix系統裡,每行結尾只有換行,即\n

回車符\r和換行符\n

  • 回車符:回到一行的開頭

  • 換行符:下一行

系統中的換行:

  • Windows系統中,每行結尾是"回車+換行".即\r\n.

  • Unix系統中,每行的結尾只有換行,即\n

  • Mac系統中,每行的結尾是'回車',即\r

//1.建立物件
FileOutputStream fo = new FileOutputStream("day28_IO\\c.txt", true);
//實現資料換行
fo.write("\n".getBytes());
//2.呼叫write()方法
fo.write("HelloWord".getBytes());
//3.關閉流物件
fo.close();

位元組輸入流

java.io.unputStream此抽象類是表示位元組輸入流的所有類的超類,可以讀取位元組資訊到記憶體中,他定義了位元組輸入流的基本你的共性的api方法

  • public void close():關閉此輸入流並釋放與此流相關的其他的任何系統資源

  • public abstract int read():從輸入流中讀取資料的下一個位元組.

  • public int read(byte[] b):從輸入流中讀取一些位元組數,並將它們儲存到位元組陣列b當中

備註:close方法,當完成流的相關操作後,需要呼叫此方法關閉輸入流,釋放系統資源.

FileInputStream類

java.io.FileInputStream類是檔案輸入流,從檔案中讀取位元組.

構造方法
  • FileinputStream(Filoe file):通過開啟與實際檔案的連線來建立一個FileInputStream,該檔案有檔案系統中的File物件file命名.

  • FileInputStream(String name):通過開啟與實際檔案的連線來建立一個FileinputStream該檔案有檔案系統中的路徑名name命名. 引數: 讀取檔案的資料來源 String name: 檔案的路徑 File file: 檔案 構造方法的作用有兩個: 1.會建立一個FileInputStream類物件 2.會把FileInputStream類物件指定構造方法中要讀取的檔案 位元組輸入流的使用步驟: 1.建立一個FileInputStream類物件,構造方法中繫結要讀取的資料 2.使用FileInputStream類物件中方法read(),讀取檔案中的資料 3.釋放資源,關閉流物件

當你建立一個流物件時,必須穿入一個檔案路徑,該路徑下,如果沒有該檔案,會丟擲FileNotFoundException異常

使用read()方法讀取檔案中的位元組

int len=0;//表示記錄讀取到的位元組
while ((len=fi.read())!=-1)
System.out.print((char)len);

可以使用字元陣列來讀取資料:read(byte[] b):從輸入流中讀取多個位元組,並且將其儲存到緩衝區陣列b中,當讀取到檔案的末尾時,返回一個-1.

程式碼演示:

int len3=0;//記錄讀取到的有效位元組個數
byte[] bytes=new byte[1024];//2^10 1024b=1kb
while ((len3=fr.read(bytes))!=-1){
//byte[] 轉換成String
//String(byte[]byte,int offset,int length)
// System.out.println(new String(bytes, 0, len3));
System.out.println(new String(bytes));
}

備註:使用陣列讀取,每次可以讀取多個位元組,減少了系統間的IO操作次數,從而提高了讀取的效率,建議使用.

練習:圖片複製

通過位元組流實現圖片複製

實現從說面的G1.ipeq圖片複製到另一個目錄下

原理:從已知的檔案中讀取位元組,再把讀取到的位元組寫入到另一個檔案中.

   //1.建立一個位元組輸入流物件FileInputStream,構造方法中繫結需要讀取的圖片路徑
FileInputStream fi = new FileInputStream("C:\\Users\\Administrator\\Desktop\\筆記\\Collection介面和Map介面概述.png");
//2.把檔案讀取出來
byte[] bytes = new byte[10240000];
// fi.read(bytes);
//建立位元組輸出流物件,FileOutPutStream,指向資料複製的目的地檔案地址
FileOutputStream f = new FileOutputStream("day28_IO\\c.png");
//方法1,直接放入整個byte陣列
// f.write(bytes);
//方法2
int len=0;
while ((len=fi.read(bytes))!=-1){
f.write(bytes,0,len);
}
f.close();
fi.close();
}

備註:流的關閉順序:先開後關,後開先關.

字元流

當使用位元組流讀取文字檔案的時候,肯能會引發一點小問題,如果你遇到中文字元時,可能不會顯示完整的字元.拿就是因為一箇中文字元可能佔用多個位元組儲存,所以java提供了一些字元流類,以字元為單位讀寫資料,專門用於處理文字文件檔案.

字元輸入流[Reader]讀取

java.io.Reader抽象類是表示用於讀取字元流的所有類的茶類,可以讀取字元資訊到記憶體當中,它定義了字元輸入流的基本共性的api方法:

  • public void close():關閉此輸入流並且釋放與此流相關的其他系統資源

  • public int read():從輸入流中讀取一個字元.

  • public int read(char[] ahuf):從輸入流中一次讀取多個字元,並將它們儲存到字元陣列chuf當中.

FileReader類

java.io.FileReader類主要是用於讀取字元檔案的便捷類.構造方法使用時的編碼字符集和預設的位元組緩衝區.

備註:

1.字元編碼:位元組與字元的對應規則.在windows系統中的中文編碼預設是GBK,idea中採用UTF-8

2.位元組緩衝去:一個自節陣列,用來臨時儲存位元組資料.

構造方法

  • FileReader(File file):建立一個新的FileReader物件,給定的指定的需要讀取的File物件.

  • FileReader(String filename):建立一個新的FileReader物件,指定需要讀取的檔名稱.

當你建立一個流物件時,必須闖入一個檔案路徑,類似於FileinputStream.

使用字元陣列讀取資料:read(char[] chuf),每次讀取chuf的長度個字元到陣列當中,返回讀取到有效字元的個數.當他讀取到末尾時,返回-1.

程式碼例項:

 //建立物件,構造方法中繫結資料來源
FileReader fi = new FileReader("day28_IO\\c.txt");
//2.呼叫read方法
char[] chuf = new char[1024];
int len=0;//記錄的是每次轉換的有效的字元個數
while ((len=fi.read(chuf))!=-1){
//字元陣列轉換成字串
//String static valueOf()
System.out.println(new String(chuf,0,len));
}
//3.釋放資源
fi.colse();

字元輸出流[Wruter]

java.io.Writer抽象類是表示用於寫入(輸出)字元流的所有類的超類.將指定的字元資訊寫入到目的地中.他同時定義了字元輸出流的基本共性的API方法:

  • void write(int c):寫入單個字元

  • void write(char[] chuf):寫入字元陣列

  • abstract void write(char[] chuf,int off,int len):寫入char陣列的一部分從off(起始索引值)開始,寫入len個字元個數.

  • void write(String str):寫入字串.

  • void write(String str,int off,int len):寫入字串的一部分,從字串的起始索引off開始,寫入len個字元

  • void flush():重新整理

  • void close():關閉此流,但是需要先重新整理它.

FileWriter類

'java.io.FileWriter'類是用於寫入字元到檔案中,構造方法使用系統預設的字元編碼和預設的位元組緩衝區.

構造方法

  • FileWriter(File file):建立一個新的FileWriter,指定寫入的file物件

  • FileWriter(String name):建立一個新的FileWriter,指定需要寫入的檔案的名稱.

當你建立一個流物件時,必須傳入一個檔案路徑,類似於FileOutputStream.

示例:
  FileWriter fi = new FileWriter("day28_IO\\b.txt");
//2.使用FileWriter賭俠凝重的方法Write.把資料寫入到記憶體緩衝區中(字元轉換為位元組的過程)
//void write(int c)寫入單個字元
fi.write(107);//J
//3.使用FileWriter物件的中的方法flush,把記憶體緩衝區中的資料重新整理到檔案中.
// fi.flush();
//4.釋放資源(會先把記憶體緩衝區中的資料重新整理到檔案中)
fi.close();

關閉和重新整理

因為內建緩衝區的原因,如果不關閉輸出流,無法寫入字元到檔案中.但是關閉流物件,是無法繼續寫入資料到檔案中.如果既想寫入資料到檔案中,又想繼續使用流物件,那麼就需要flush方法.

  • flush:重新整理緩衝區的資料,流物件可以繼續使用

  • close:先重新整理緩衝區,然後會通知系統釋放資源,關閉流物件,流物件不可以再使用

程式碼

    //1.建立物件
FileWriter fi = new FileWriter("day28_IO\\e.txt");
//2.呼叫write方法.
fi.write(97);//a
//3.重新整理緩衝區
fi.flush();//把緩衝區的資料重新整理到檔案中
//重新整理之後流還可以繼續使用
fi.write(98);
//4.關閉流物件
fi.close();
//close方法之後,流已經關閉了,從記憶體中消失了,流不能再使用了,如果還用會異常
//java.io.IOException: Stream closed
fi.write(99);

寫入字元陣列:'write(char[] chuf)和write(char[] chuf,int off,ing len)',每次可以寫入一個字元陣列

用法類似FileOutputSrearm

續寫和換行:操作類似於FileOutPutStream

//1.new
FileWriter fi = new FileWriter("day28_IO\\g.txt", true);
//write
char[] chars =new char[50];
for (int i = 0; i < 50; i++) {
chars[i]=(char)(8140+i);
fi.write(chars[i]+"\r\n");//
}
//flush
fi.flush();
//關閉流
fi.close();

}

備註:字元流,只能操作文字檔案,不能操作圖片,視訊等非文字檔案.

所以當我們單純的就是想操作文字檔案,就是用字元流,其他情況一律使用位元組流.

IO異常的處理

JDK1.7之前的處理,
 FileWriter fw=null;
try {
//可能會產生異常
fw = new FileWriter("day28_IO\\g.txt", true);
//2.write
fw.write(97);
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}
//重新整理
finally {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}

之後可以把流的操作放入try的小擴號裡面 新特性,try後面可以跟進一個小括號,並且放入小括號的流會在try catch結束後自動釋放流

在JDK1.7之前使用try...catch...finally 處理流中的異常 格式: try{ //可能會發生的異常 }catch(異常型別 一場變數名){ 異常的處理邏輯}finally{ //釋放系統資源 並且finally語句塊一定會被執行 }

JDK7新特性

.可以使用try-with-resource語句,該語句確保了每個資源在語句結束時關閉,所謂的資源(resource)是指在程式完成後,必須要關閉的物件.

格式:

try(建立流物件語句,如果多個,請用";"隔開){
//可能會產生異常的程式碼
}catch(異常型別 一場變數名){
//異常處理邏輯
}

程式碼如下:

 try (  //1.1new
FileOutputStream fi = new FileOutputStream("day28_IO\\g.txt");
//1.2new
final FileInputStream fw = new FileInputStream("day28_IO\\a.txt"))
{ //2. write
int len=0;
while ((len=fw.read())!=-1){
fi.write(len);
}
}catch (IOException e){
//異常的處理邏輯
e.printStackTrace();
}