總結JAVA----IO流中的位元組流
對於IO流中位元組流的總結
位元組流 的概念
由於應用程式,經常需要和檔案打交道,所以Inputstream專門提供了讀寫檔案的子類:FileInputStream和FileOutputStream類,如果程式對於檔案的操作較為簡單,就比如說只是順序的讀寫檔案,那麼就可以使用位元組流進行操作.並且我們都知道,所有檔案的最底層資料型別都是位元組,所以說,位元組流的應用範圍是十分廣的,當然,它也有相應的缺點,只能處理簡單的資料文字,一旦資料多了,其處理速度慢的弊端也就顯現了出來.
子父類關係
通過超級父類InputStream延伸出的很多派系,並且一些派系完美的解決了,位元組流速度慢的問題(位元組緩衝流)
編碼方式
查閱了挺久資料的,發現在編碼方式這塊,由於我還沒有接觸計算機原理這門課,所以對於這塊的概念十分的模糊,從昨天到今天也查閱了許多資料,但還是無法很系統的整理出一些真正有用的東西,所以對於編碼方式這裡,我會在以後認真的總結一番。
其與字元流的不同
1.
位元組流傳輸的最基本單位是位元組
字元流傳輸的最基本單位是字元
2.
編碼方式不同
3.
字元流在傳輸方面上,由於計算機的傳輸本質都是位元組,而一個字元由多個位元組組成,轉成位元組之前先要去查錶轉成位元組,所以傳輸時有時候會使用緩衝區。
位元組流傳輸時不會用到緩衝區,是通過直接訪問IO裝置的方式來完成傳輸。
4.
位元組流適用於圖片,文字,視訊等等格式的資料.
字元流適用於文字,並且最好是中文文字,處理速度超快.
位元組流的輸入\輸出流
構造方法(1)
構造方法(2)
構造方法(3)
這三種構造方法都要求在物件建立之前便給出檔名。
對於一個檔案進行的輸入輸出操作的程式碼
import java.io.*; import java.util.Scanner; /* * 該類用於做一個檔案位元組流的例子 */ public class Demo1 { public static void main(String[] args) throws IOException{ File file=function(); choice(file); } public static File function() throws IOException{//該方法用於建立一個檔案物件 File file=new File("C:\\Users\\Lenovo\\Desktop\\Demo.txt"); //建立一個檔案物件 if(!file.exists()) { file.createNewFile();//若檔案不存在則建立一個文字檔案 } return file; } public static void choice(File file) throws IOException{//該類用於進行選擇輸入方式(是覆蓋還是從檔案末尾寫) int a = 0; System.out.println("a=="); Scanner sc=new Scanner(System.in); a=sc.nextInt(); switch(a) { case 1:function1(file);function3(file);break;//這是覆蓋式寫入 case 2:function2(file);function3(file);break;//這是從檔案末尾寫入 default:System.out.println("無該索引"); } sc.close(); } publicstatic void function1(File file) throws IOException{ FileOutputStreamfos=newFileOutputStream(file); System.out.println("請輸入您想要寫入的資訊"); Scanner sc=new Scanner(System.in); String s=sc.nextLine(); byte[] b=s.getBytes();//將字串轉換為位元組陣列 fos.write(b); fos.close(); sc.close(); } public static void function2(File file) throws IOException{//該方法是從末尾開始寫 FileOutputStreamfos=newFileOutputStream(file,true); System.out.println("請輸入您想要寫入的資訊"); Scanner sc=new Scanner(System.in); String s=sc.nextLine(); byte[] b=s.getBytes(); fos.write(b); fos.close(); sc.close(); } public static void function3(File file) throws IOException{ FileInputStream fis=newFileInputStream(file); byte[] b=new byte[(int) file.length()]; //運用File類關於檔案屬性的方法,但是返回值是long型資料,需要強轉。 fis.read(b); System.out.println(new String(b)); fis.close(); } }
第一次鍵入a=1,輸入"啊哈哈"
第二次鍵入a=1,輸入"嘿嘿嘿” 會發現檔案中只剩下"嘿嘿嘿”
第三次鍵入a=1,輸入"啊哈哈"
第二次鍵入a=2,輸入"嘿嘿嘿” 會發現檔案中是"啊哈哈嘿嘿嘿”
位元組緩衝流
BufferedInputStream&BufferedOutputStream
這兩種類為IO提供了帶緩衝區的操作,一般開啟檔案進行寫入或讀取操作時,都會加上緩衝,這樣提高了IO的效能。
對於IO的抽象理解
如果我們要將一缸水轉到另一缸水中
FileOutputStream&FileInputStream相當於把水一滴一滴的轉移
DataOutputStream&DateaInputStream相當於把水一瓢一瓢的轉移
BufferedOutputStream&BufferdeInputStream相當於先把水全部放入一缸水中,然後在將這一缸水倒入目標缸中。
所以說帶緩衝區的位元組緩衝流是很好使的。
我們用位元組緩衝流程式碼實現一下檔案的複製
import java.io.*; /* * 用位元組緩衝流完成對於檔案的複製 */ public class Dmeo2 { public static void main(String[] args) throws IOException{ byte[] b=function(); function1(b); } public static byte[] function() throws IOException { InputStream is=new FileInputStream("C:\\Users\\Lenovo\\Desktop\\Demo.txt"); BufferedInputStream bis=new BufferedInputStream(is);//構造方法引數為InputStream型別 byte[] b=new byte["C:\\Users\\Lenovo\\Desktop\\Demo.txt".length()]; bis.read(b);//將資訊轉換為位元組陣列 bis.close(); return b;//將位元組陣列返回 } public static void function1(byte[] b) throws IOException { OutputStream os=new FileOutputStream("C:\\Users\\Lenovo\\Desktop\\Demo1.txt"); BufferedOutputStream bos=new BufferedOutputStream(os); bos.write(b); bos.flush();//此處一定要記得重新整理緩衝區,這樣資訊才能流入檔案 bos.close();//若是我們手動關閉的話,系統會幫我們自動重新整理緩衝區 /*所以說fluse()方法與close()方法寫一個就行,但這只是理論上的 * 但是為了程式的可讀性還是都寫好一點 */ } }
這裡的Demo檔案是我們上個程式碼也就是位元組流中所建立的檔案。
位元組陣列流
位元組陣列流在功能方面屬於位元組流,屬於直接作用於目標裝置的一種流類.經常而言我們都是針對檔案的操作,然後帶上緩衝的節點流進行處理,但有時候為了提升效率,我們發現頻繁的讀寫檔案並不是太好,那麼於是出現了位元組陣列流,即存放在記憶體中,因此又稱之為記憶體流.(這裡是直接copy別人的).其實也就是將我們的目標放在了緩衝區之上,而不再是檔案了.
ByteOtputArrayStream(位元組陣列輸出流)
構造方法:
第一個是有初始長度但可以增加,第二個是自己設定長度
這裡我感覺我們不可以將其理解為陣列,總感覺它和集合真的好像,因為他的屬性單位也是以size()方法來檢視的,並且他和集合一樣長度是可變的。
特殊方法:
這個無效close最先真的搞得我一頭霧水,後來才反應過來這裡我們操作的物件是緩衝區,緩衝區是無法關閉的,或者說關閉了會出很大的問題,所以這裡他應該是無效的,並且作為子類,我們從父類中所拿到的方法並不全是有用的,畢竟子類與父類是不同的兩個單獨存在的個體。
關於緩衝區屬性的一個方法
這兩個方法都是write方法,這裡的處理方式其實和父類中的write方法基本一致吧,只是目標有所變化。
ByteInputArrayStream\位元組輸入流
構造方法
這裡最關鍵的是buf的選擇,作為輸入流我們若是想從緩衝區得到資料的話,buf應該是輸入流.toByteArray()方法得到的陣列,在我看來輸入流就代表著那一塊我們正存放資料的緩衝區,這樣轉換成數組合情合理
完成一個簡單讀寫操作
import java.io.*; public class Demo3 { public static void main(String[] args) throws IOException{ function(); } public static void function() throws IOException{//該方法用於輸出流的存入 ByteArrayOutputStreambos=new ByteArrayOutputStream();//使用預設構造方法 String s="我是哈哈哈"; byte[] b=s.getBytes(); bos.write(b); //這裡不要像上文給出的write(byte[] b,int off,int len)因為這樣的話我們還要 //計算一下位元組個數,很麻煩,還容易出錯,當然也有其它方法知道準確位元組數但是程式碼量會多 function1(bos.size(),bos); } public static void function1(int a,ByteArrayOutputStream bos) throws IOException{ ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray()); //如上文所說,以輸出流所轉化成的陣列為引數建立一個物件 byte[] b=new byte[a]; bis.read(b);//把位元組存到b陣列中 System.out.println(new String(b)); } }
位元組資料流
DataInputStream和DataOutputStream類建立的物件稱為資料輸入流和資料輸出流.這兩個流是很有用的流,他們允許程式按著及其無關的的風格讀取JAVA原始資料.也就是說,當讀取一個數值時,不必再關心這個數值應該是多少個位元組(而且有些資料型別long,double資料型別真的很難轉成位元組),它們屬於處理流,即程式通過一個間接流類去呼叫節點流類,以達到更加靈活方便地讀寫各種型別的資料,這個間接流類就是處理流 。
構造方法
也就是說他們的引數是節點流。並且這裡我們可以很好的利用多型的概念,FileInputStream。。。。等等都可以作為引數
讀寫方法writexxx,readxxx。
程式碼完成簡單的讀取操作
import java.io.*; public class Demo4 { static String file="C:\\Users\\Lenovo\\Desktop\\李xx.txt"; public static void main(String[] args) throws IOException{ function(); function1(); } public static void function() throws IOException{//該方法用於存 DataOutputStream dos=new DataOutputStream(new FileOutputStream(Demo4.file)); dos.writeInt(1); dos.writeInt(2); dos.writeInt(3); dos.writeInt(4); dos.writeUTF("你是真滴6"); dos.close(); } public static void function1() throws IOException{ DataInputStreamdis=new DataInputStream(new FileInputStream(file)); System.out.println(dis.readInt()); System.out.println(dis.readInt()); System.out.println(dis.readInt()); System.out.println(dis.readInt()); System.out.println(dis.readUTF()); } }
但是我發現數據流中讀取時指標的跳轉過於笨拙,也就是說我們必須知道下個數據型別是啥,才能將其準確讀取出來,並且前一個讀不出來的話,後一個也是無法讀取的。