Java中IO流,輸入輸出流概述與總結
轉自:https://www.cnblogs.com/biehongli/p/6074713.html
1:Java語言定義了許多類專門負責各種方式的輸入或者輸出,這些類都被放在java.io包中。其中,
所有輸入流類都是抽象類InputStream(字節輸入流),或者抽象類Reader(字符輸入流)的子類;
而所有輸出流都是抽象類OutputStream(字節輸出流)或者Writer(字符輸出流)的子類。
【首先需要明白的是:流是幹什麽的???(為了永久性的保存數據)
根據數據流向的不同分為輸入流和輸出流;
根據處理數據類型的不同分為字符流和字節流;
】
【然後需要明白的是輸入模式和輸出模式是誰流向誰:
InputStream(字節輸入流)和Reader(字符輸入流)通俗的理解都是讀(read)的。
OutputStream(字節輸出流)和Writer(字符輸出流)通俗的理解都是寫(writer)的。
】
最後下面搞清楚各種流的類型的該怎麽用,誰包含誰,理清思路。
2:InputStream類是字節輸入流的抽象類,是所有字節輸入流的父類,InputStream類具有層次結構如下圖所示;
3:java中的字符是Unicode編碼的,是雙字節的。InputStream是用來處理字節的,在處理字符文本時很不方便。Java為字符文本的輸入提供了專門的一套類Reader。Reader類是字符輸入流的抽象類,所有字符輸入流的實現都是它的子類。
4:輸出流OutputStream類是字節輸入流的抽象類,此抽象類表示輸出字節流的所有類的超類。
5:Writer類是字符輸出流的抽象類,所有字符輸出類的實現都是它的子類。
6:File類是IO包中唯一代表磁盤文件本身的對象。通過File來創建,刪除,重命名文件。File類對象的主要作用就是用來獲取文本本身的一些信息。如文本的所在的目錄,文件的長度,讀寫權限等等。(有的需要記憶,比如isFile(),isDirectory(),exits();有的了解即可。使用的時候查看API)
詳細如下: File類(File類的概述和構造方法) A:File類的概述 File更應該叫做一個路徑File類(File類的獲取功能) A:獲取功能 public String getAbsolutePath():獲取絕對路徑 public String getPath():獲取路徑 public String getName():獲取名稱 public long length():獲取長度。字節數 public long lastModified():獲取最後一次的修改時間,毫秒值 public String[] list():獲取指定目錄下的所有文件或者文件夾的名稱數組 public File[] listFiles():獲取指定目錄下的所有文件或者文件夾的File數組 File類(文件名稱過濾器的概述及使用) A:文件名稱過濾器的概述 public String[] list(FilenameFilter filter) public File[] listFiles(FileFilter filter)
1 package com.ningmeng; 2 3 import java.io.File; 4 5 public class Test { 6 7 public static void main(String[] args) throws Exception{ 8 // TODO Auto-generated method stub 9 File file=new File("aa.txt");//文件默認就創建在你創建的項目下面,刷新即可看到 10 System.out.println(file.exists());//判斷文件是否存在 11 file.createNewFile();//創建文件,不是文件夾 12 System.out.println(file.exists());//再次判斷是否存在 13 System.out.println(file.getName());//獲取文件的名字 14 System.out.println(file.getAbsolutePath());//獲取文件的絕對路徑 15 System.out.println(file.getPath());//獲取文件的相對路徑 16 System.out.println(file.getParent());//獲取文件的父路徑 17 System.out.println(file.canRead());//文件是否可讀 18 System.out.println(file.canWrite());//文件是否可寫 19 System.out.println(file.length());//文件的長度 20 System.out.println(file.lastModified());//文件最後一次修改的時間 21 System.out.println(file.isDirectory());//判斷文件是否是一個目錄 22 System.out.println(file.isHidden());//文件是否隱藏 23 System.out.println(file.isFile());//判斷文件是否存在 24 } 25 26 }
public String[] list():獲取指定目錄下的所有文件或者文件夾的名稱數組
public File[] listFiles():獲取指定目錄下的所有文件或者文件夾的File數組list()獲取某個目錄下所有的文件或者文件夾:
1 package com.ningmeng; 2 3 import java.io.File; 4 5 public class FileTest { 6 7 public static void main(String[] args){ 8 File file=new File("D:/");//指定文件目錄 9 String[] str=file.list();//獲取指定目錄下的所有文件或者文件夾的名稱數組 10 for(String s : str){//加強for循環遍歷輸出 11 System.out.println(s); 12 } 13 14 } 15 }
1 package com.ningmeng; 2 3 import java.io.File; 4 5 public class FileTest { 6 7 public static void main(String[] args){ 8 File file=new File("D:/");//指定文件路徑 9 File[] f=file.listFiles();//獲取指定目錄下的所有文件或者文件夾的File數組 10 for(File fi : f){//加強for循環遍歷輸出 11 System.out.println(fi); 12 } 13 14 } 15 }
案例演示:
獲取某種格式的文件比如獲取某種後綴的圖片,並輸出文件名:
1 package com.ningmeng; 2 3 import java.io.File; 4 5 public class FileTest { 6 7 public static void main(String[] args){ 8 File file=new File("C:\\Users\\biehongli\\Pictures\\xuniji"); 9 String[] str=file.list(); 10 11 for(String s : str){ 12 if(s.endsWith(".jpg") || s.endsWith(".png")){//如果後綴是這種格式的就輸出 13 System.out.println(s); 14 } 15 } 16 17 18 } 19 }
下面演示獲取文件夾下面子目錄裏面的文件獲取(並沒有完全獲取子目錄的子目錄等等,僅僅獲取了子一級目錄):
1 package com.ningmeng; 2 3 import java.io.File; 4 5 public class FileTest { 6 7 public static void main(String[] args){ 8 File file=new File("C:\\Users\\biehongli\\Pictures\\Camera Roll"); 9 10 File[] f=file.listFiles(); 11 12 for(File fi : f){ 13 if(fi.isDirectory()){//判斷如果是一個目錄 14 String[] s=fi.list(); 15 for(String str : s){ 16 if(str.endsWith(".jpg")){ 17 System.out.println(str); 18 } 19 } 20 } 21 } 22 } 23 }
A:文件名稱過濾器的概述
public String[] list(FilenameFilter filter) public File[] listFiles(FileFilter filter)1 package com.ningmeng; 2 3 import java.io.File; 4 import java.io.FilenameFilter; 5 6 public class FileTest { 7 8 public static void main(String[] args){ 9 File file=new File("C:\\Users\\biehongli\\Pictures\\Camera Roll"); 10 11 String[] str=file.list(new FilenameFilter() {//過濾器,匿名內部類 12 13 @Override 14 public boolean accept(File dir, String name) { 15 // TODO Auto-generated method stub 16 //System.out.println(dir);//獲取文件的路徑 17 //System.out.println(name);//獲取文件的名字 18 File f=new File(dir,name); 19 return f.isFile() && f.getName().endsWith(".jpg"); 20 } 21 }); 22 for(String s : str){ 23 System.out.println(s); 24 } 25 26 } 27 }
7:下面以一些字節輸入輸出流具體的案例操作(操作的時候認清自己使用的是字節流還是字符流):
註意:read()方法讀取的是一個字節,為什麽返回是int,而不是byte 字節輸入流可以操作任意類型的文件,比如圖片音頻等,這些文件底層都是以二進制形式的存儲的,如果每次讀取都返回byte,有可能在讀到中間的時候遇到111111111;那麽這11111111是byte類型的-1,我們的程序是遇到-1就會停止不讀了,後面的數據就讀不到了,所以在讀取的時候用int類型接收,如果11111111會在其前面補上;24個0湊足4個字節,那麽byte類型的-1就變成int類型的255了這樣可以保證整個數據讀完,而結束標記的-1就是int類型FileInputStream的單個字節讀取:
FileOutputStream的單個字節寫入:
1 package com.ningmeng; 2 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 6 public class FileTest { 7 8 public static void main(String[] args) throws Exception{ 9 FileInputStream fis=new FileInputStream("aaa.txt"); 10 FileOutputStream fos=new FileOutputStream("bbb.txt",true); 11 //FileOutputStream()後面加true指文件後面可追加 12 13 int a=fis.read();//read()一次讀取一個字節 14 System.out.println(a);//讀取的一個字節輸出 15 16 fos.write(101);//write()一次寫一個字節 17 fis.close();//一定記得關閉流,養成好習慣 18 fos.close(); 19 } 20 }
FileInputStream和FileOutputStream進行拷貝文本或者圖片或者歌曲:
1 package com.ningmeng; 2 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 6 public class FileTest { 7 8 public static void main(String[] args) throws Exception{ 9 FileInputStream fis=new FileInputStream("aaa.txt"); 10 FileOutputStream fos=new FileOutputStream("bbb.txt"); 11 //如果沒有bbb.txt,會創建出一個 12 13 int b; 14 while((b=fis.read())!=-1){ 15 fos.write(b); 16 } 17 fis.close(); 18 fos.close(); 19 } 20 }
FileInputStream和FileOutputStream定義小數組進行讀寫操作:
1 package com.ningmeng; 2 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 6 public class FileTest { 7 8 public static void main(String[] args) throws Exception{ 9 FileInputStream fis = new FileInputStream("aaa.txt"); 10 FileOutputStream fos = new FileOutputStream("bbb.txt"); 11 int len; 12 byte[] arr = new byte[1024 * 8];//自定義字節數組 13 14 while((len = fis.read(arr)) != -1) { 15 //fos.write(arr); 16 fos.write(arr, 0, len);//寫出字節數組寫出有效個字節個數 17 } 18 //IO流(定義小數組) 19 //write(byte[] b) 20 //write(byte[] b, int off, int len)寫出有效的字節個數 21 22 fis.close(); 23 fos.close(); 24 } 25 }
IO流(BufferedInputStream和BufferOutputStream拷貝)
* A:緩沖思想 * 字節流一次讀寫一個數組的速度明顯比一次讀寫一個字節的速度快很多, * 這是加入了數組這樣的緩沖區效果,java本身在設計的時候, * 也考慮到了這樣的設計思想,所以提供了字節緩沖區流 * B.BufferedInputStream * BufferedInputStream內置了一個緩沖區(數組) * 從BufferedInputStream中讀取一個字節時 * BufferedInputStream會一次性從文件中讀取8192個, 存在緩沖區中, 返回給程序一個 * 程序再次讀取時, 就不用找文件了, 直接從緩沖區中獲取 * 直到緩沖區中所有的都被使用過, 才重新從文件中讀取8192個 * C.BufferedOutputStream * BufferedOutputStream也內置了一個緩沖區(數組) * 程序向流中寫出字節時, 不會直接寫到文件, 先寫到緩沖區中 * 直到緩沖區寫滿, BufferedOutputStream才會把緩沖區中的數據一次性寫到文件裏1 package com.ningmeng; 2 3 import java.io.BufferedInputStream; 4 import java.io.BufferedOutputStream; 5 import java.io.FileInputStream; 6 import java.io.FileOutputStream; 7 8 public class FileTest { 9 10 public static void main(String[] args) throws Exception{ 11 FileInputStream fis = new FileInputStream("aaa.txt"); 12 FileOutputStream fos = new FileOutputStream("bbb.txt"); 13 14 BufferedInputStream bis=new BufferedInputStream(fis); 15 //使用裝飾模式,把fis裝飾進去bis中。使用緩沖讀取速度變快 16 BufferedOutputStream bos=new BufferedOutputStream(fos); 17 18 int b; 19 while((b=bis.read())!=-1){ 20 bos.write(b); 21 } 22 bis.close(); 23 bos.close(); 24 } 25 }
面試題:小數組的讀寫和帶Buffered的讀取哪個更快?
* 定義小數組如果是8192個字節大小和Buffered比較的話 * 定義小數組會略勝一籌,因為讀和寫操作的是同一個數組 * 而Buffered操作的是兩個數組 IO流(flush和close方法的區別) flush()方法: 用來刷新緩沖區的,刷新後可以再次寫出(字節緩沖流內置緩沖區,如果沒有讀取出來,可以使用flush()刷新來) close()方法:用來關閉流釋放資源的的,如果是帶緩沖區的流對象的close()方法,不但會關閉流,還會再關閉流之前刷新緩沖區,關閉後不能再寫出 8:字符流FileReader和FileWriter 字符流是什麽 * 字符流是可以直接讀寫字符的IO流 * 字符流讀取字符, 就要先讀取到字節數據, 然後轉為字符. 如果要寫出字符, 需要把字符轉為字節再寫出. IO流(什麽情況下使用字符流) * 字符流也可以拷貝文本文件, 但不推薦使用. 因為讀取時會把字節轉為字符, 寫出時還要把字符轉回字節. * 程序需要讀取一段文本, 或者需要寫出一段文本的時候可以使用字符流 * 讀取的時候是按照字符的大小讀取的,不會出現半個中文 * 寫出的時候可以直接將字符串寫出,不用轉換為字節數組 IO流(字符流是否可以拷貝非純文本的文件) * 不可以拷貝非純文本的文件 * 因為在讀的時候會將字節轉換為字符,在轉換過程中,可能找不到對應的字符,就會用?代替,寫出的時候會將字符轉換成字節寫出去 * 如果是?,直接寫出,這樣寫出之後的文件就亂了,看不了了1 package com.ningmeng; 2 3 import java.io.FileReader; 4 import java.io.FileWriter; 5 6 public class FileTest { 7 8 public static void main(String[] args) throws Exception{ 9 //FileReader類的read()方法可以按照字符大小讀取 10 FileReader fr=new FileReader("aaa.txt"); 11 int b; 12 while((b=fr.read())!=-1){ 13 System.out.println((char)b);//int類型轉為字符型 14 } 15 fr.close(); 16 17 //FileWriter類的write()方法可以自動把字符轉為字節寫出 18 FileWriter fw = new FileWriter("aaa.txt",true); 19 fw.write("aaa"); 20 fw.close(); 21 22 //字符流的拷貝 23 FileReader fr2 = new FileReader("aaa.txt"); 24 FileWriter fw2 = new FileWriter("bbb.txt"); 25 26 int ch; 27 while((ch = fr2.read()) != -1) { 28 fw2.write(ch); 29 } 30 31 fr2.close(); 32 fw2.close(); 33 } 34 }
1 package com.ningmeng; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.FileReader; 6 import java.io.FileWriter; 7 8 public class FileTest { 9 10 public static void main(String[] args) throws Exception{ 11 BufferedReader br=new BufferedReader(new FileReader("aaa.txt")); 12 BufferedWriter bw=new BufferedWriter(new FileWriter("bbb.txt")); 13 //BufferedReader和BufferedWriter的使用: 14 int b; 15 while((b=br.read())!=-1){ 16 bw.write((char)b); 17 } 18 br.close(); 19 bw.close(); 20 } 21 }
先寫到這裏吧,內容比較多,以後有時間再總結,也方便自己腦補
Java中IO流,輸入輸出流概述與總結