java IO之字節流

1、IO(Input Output)流的概述

1、io的概念及其特點

    流是一組有順序的,有起點和終點的字節集合,是對數據傳輸的總稱或抽象。即數據在兩設備間的傳輸稱爲流.

    宏觀上io有以下特點

    ·        IO流用來處理設備之間的數據傳輸。

    ·        Java對數據的操作是通過流(系統資源)的方式。

    ·        Java用於操作流的對象都在java.io包中。

    ·        流按操作數據分爲兩種:字節流與字符流。

    ·        流按流向分爲:輸入流,輸出流。

2、io的體系結構


2、IO中常用的類

    1. File(文件特徵與管理):用於文件或者目錄的描述信息,例如生成新目錄,修改文件名,刪除文件,判斷文件所在路徑等。

     2. InputStream(二進制格式操作):抽象類,基於字節的輸入操作,是所有輸入流的父類。定義了所有輸入流都具有的共同特徵。

     3.OutputStream(二進制格式操作):抽象類。基於字節的輸出操作。是所有輸出流的父類。定義了所有輸出流都具有的共同特徵。

     4.Reader(文件格式操作):抽象類,基於字符的輸入操作。

     5. Writer(文件格式操作):抽象類,基於字符的輸出操作。

     6. RandomAccessFile(隨機文件操作):一個獨立的類,直接繼承至Object.它的功能豐富,可以從文件的任意位置進行存取(輸入輸出)操作。

3、File詳解

        1、File(文件特徵與管理)

            用來將文件或者文件夾封裝成對象。

            方便對文件與文件夾的屬性信息進行操作。

            File對象可以作爲參數傳遞給流的構造函數。

        2、File API

package com.xyq.file;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;

public class FileTest {

	public static void main(String[] args) throws IOException {

//		method_1();
//		method_2();
//		method_3();
//		method_4();
//		method_5();
//		method_6();
//		method_7();
		File file = new File("E:\\test");
		FilesFilter(file);
	}
	
    /*
     *  file類的四個靜態常量
     *  public static String separator 與系統有關的目錄分隔符 Windows中 :\ 
     *  public static char separatorChar Linux中: /
     *  public static String pathSeparator 與系統有關的路徑分隔符 Windows中  ; 分號
     *  public static char pathSeparatorChar Linux中  : 冒號
     */
	public static void method_1(){
		File file = new File("E:\\");
		String s = file.separator;
		System.out.println(s);
		s = file.pathSeparator;
		System.out.println(s);
	}
	
	 /*
     * file 類的構造方法
     * 1. File(String pathName)
     * 2. File(String parent, String child)
     * 3. File(File parent, String child)
     */	
	public static void method_2(){
		
		File file = new File("E:\\KeCheng");
		File file2 = new File("E:\\","KeCheng");
		File file3 = new File(file, "");
		System.out.println(file);
		System.out.println(file2);
		System.out.println(file3);
	}
	
	 /* File類的創建方法 ,目標文件或者路徑存在時,均會返回false
     *  1. boolean createNewFile() 創建文件,成功返回true
     *  2. boolean mkdir() 創建文件夾,成功返回true,只能創建一級目錄
     *  3. boolean mkdirs() 創建多級文件夾
     */
	public static void method_3()throws IOException{
		File file = new File("E:\\text.txt");
		System.out.println(file.createNewFile());
		File file2 = new File("E:\\test\\test\\test");
		System.out.println(file2.mkdirs());
	}
	
	 /* File類的刪除方法
     * 1. boolean delete() 刪除指定目錄或者文件,成功返回true,注意此刪除不走回收站,文件夾不爲空時沒有辦法刪除
     * 2. void deleteOnExit() jvm退出前刪除,
     */
	public static void method_4()throws IOException{
		File file = new File("E:\\test.txt");
		System.out.println(file.createNewFile());
		System.out.println(file.delete());
	}
	
	/* File類的判斷方法
     * boolean exists() 判斷構造方法中封裝的路徑或者文件是否存在
     * boolean isAbsolute() 判斷構造方法中封裝的路徑是不是絕對路徑,是返回真
     * boolean isDirectory() 判斷是不是路徑,是返回true
     * boolean isFile() 判斷是不是文件,是返回true
     * boolean isHidden() 判斷封裝的路徑(包括文件)是不是隱藏屬性是返回true
     */
	public static void method_5(){
		File file = new File("E:\\abcde");
		System.out.println(file.exists());
		System.out.println(file.isAbsolute());
	}
	
	/*
     * File類的獲取方法
     * 1.String getName() 獲取封裝路徑最後部分的名字,此方法不會判斷路徑是否存在,使用之前最好判斷
     * 2.String getParent() 返回封裝路徑的父路徑
     * 3.File getParentFile() 返回封裝路徑的父路徑的File對象
     * 4.String getAbsolutePath() 返回封裝路徑的絕對路徑
     * 5.File getAbsoluteFile() 返回封裝路徑的絕對路徑的File對象
     */
	
	public static void method_6(){
		File file = new File("scr");
		System.out.println(file.getAbsoluteFile().getParent());
	}
	
	 /*
     * File的list方法
     * 1. static File[] listRoots() 靜態的方法,列出系統所以的根,光驅和移動設備存儲也會算進去
     * 2. String[] list()返回File構造方法封裝的路徑下的所有文件和文件夾
     * 3. File[] listFiles()返回File構造方法封裝的路徑下的所有文件和文件夾,返回的Filed對象,帶全路徑
     */
	public static void method_7(){
		File []roots = File.listRoots();
		for(File file:roots){
			System.out.println(file);
		}
	}
	
	//遞歸過濾方法的實現,選出目錄下的*.java文件
    //直接使用匿名內部內實現了FileFilter接口
	public static void FilesFilter(File file){
		
		File []files = file.listFiles(new FileFilter() {
			
			@Override
			public boolean accept(File pathname) {
				if (pathname.getName().endsWith(".java") || pathname.isDirectory()) {
					return true;
				} else {
					return false;
				}
			}
		});
		
		if(files != null){
			for(File file2:files){
				if(file2.isFile()){
					System.out.println(file2);
				}else {
					FilesFilter(file2);
				}
			}
		}
	}
}

4、IO流常用基類

  • 字節流的抽象基類: 
    • InputStream 讀取一個文本文件中的數據
    • OutputStream 向一個文本文件中寫入數據
    • 用輸出流還是輸入流 參考標準是內存
  • 字符流的抽象基類:

    • Reader
    • Writer

    比較常用的字節流

  • FileInputStream
  • FileOutputStream
  • BufferedInputStream
  • BufferedOutputStream

    4.1字節輸出流——FileOutputStream

        注意 在創建字節輸出流對象用於操作文件,在對象初始化時必須明確數據存儲的目的地,輸出流所關聯的目的地,如果不存在,則會自動創建;如果存在,則會覆蓋。

具體用法  例  向一個文本文件中寫入數據

package com.xyq.outputstream;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamTest {
	/*
     * 將數據寫入到文件中。
     * 使用字節輸出流。FileOutputStream。
     */
	public static void main(String[] args) throws IOException{
		
		//1、創建文件夾
		File dir = new File("tempFile");
		if(!dir.exists()){
			dir.mkdir();
		}
		//顯示創建文件的路徑
		System.out.println(dir.getAbsoluteFile().getParent());
		 // 2、創建字節輸出流對象,用於操作文件,在對象初始化時必須明確數據存儲的目的地。
         // 輸出流所關聯的目的地,如果不存在,會自動創建。如果存在,則覆蓋。
		FileOutputStream fos = new FileOutputStream("tempFile\\test.txt");
		
		 // 3、調用輸出流的寫功能。
		fos.write("abcd".getBytes());
		
		//4、釋放資源
		fos.close();
		
	}

}

    4.2字節輸入流——FileInputStream

        具體用法  例  讀取一個文本文件中的數據

        4.2.1 read():一個一個字節的讀

package com.xyq.outputstream;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class FileInputStreamTest {

	public static void main(String[] args) throws IOException{
		
		//1、爲了確保文件一定在讀之前是存在的,將字符串路徑封裝成File對象。
		File file = new File("tempFile\\test.txt");
		//2、判斷文件是否存在
		if(!file.exists()){
			throw new RuntimeException("要讀取的文件不存在");
		}
		
		//3、創建文件字節讀取流對象時,必須明確與之關聯的數據源。
		FileInputStream fis = new FileInputStream(file);
		
		//4、調用讀方法
		int by = 0;
		while ((by = fis.read()) != -1) {
			System.out.println(by);
		}
		
		//5、關閉資源
		fis.close();
	}

}

        4.2.2read(byte[] buf):先把字節存入到緩衝區字節數組中,一下讀一個數組(常用)

package com.xyq.outputstream;

import java.io.FileInputStream;
import java.io.IOException;

public class FileInputStreamTest2 {
	
	//1、定義緩衝區的大小可以是1024的整數倍
	private static final int SIZE = 1024;

	public static void main(String[] args) {
		
		//2、創建文件字節讀取流對象。
		FileInputStream fis = null;
		try {
			fis = new FileInputStream("tempFile\\test.txt");
			//3、創建一個字節數組。
			byte [] buf = new byte[SIZE];
			//4、調用讀方法
			int len = 0;// len記錄的是往字節數組裏存儲的字節個數。
			while((len = fis.read(buf)) != -1){
				// 將字節數組轉成字符串,打印並看一下效果。
				System.out.println(new String(buf, 0, len));
			}
		} catch (IOException e) {
			// 將異常信息寫入到日誌文件中以進行記錄。
		}finally {
			//5、關閉資源
			if(fis != null){
				try {
					fis.close();
				} catch (IOException e) {
					// 一般可以throw RuntimeException異常,或者將異常信息寫入到日誌文件中以進行記錄。
					e.printStackTrace();
				}
			}
		}
		
	}

}

    4.3緩衝流-BufferedInputStream、BufferedOutputStream

        4.3.1有了InputStream和OutputStream爲什麼還要有BufferedInputStream和BufferedOutputStream?

因爲不帶緩衝的操作,每讀一個字節就要寫入一個字節,由於涉及磁盤的IO操作相比內存的操作要慢很多,所以不帶緩衝的流效率很低。帶緩衝的流,可以一次讀很多字節,但不向磁盤中寫入,只是先放到內存裏。等湊夠了緩衝區大小的時候一次性寫入磁盤,這種方式可以減少磁盤操作次數,速度就會提高很多! 

同時正因爲它們實現了緩衝功能,所以要注意在使用BufferedOutputStream寫完數據後,要調用flush()方法或close()方法,強行將緩衝區中的數據寫出。否則可能無法寫出數據。

        4.3.2 BufferedInputStream和BufferedOutputStream的具體用法

例 圖片的複製
package com.xyq.outputstream;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyPicBufferTest {
	
	//1、定義緩衝區的大小可以是1024的整數倍
	private static final int SIZE = 1024;
	
	public static void main(String[] args) {
		
		File oldFile = new File("tempFile\\1.jpg");
		
		File newFile = new File("tempFile\\abc.jpg");
		
		copyFile(oldFile, newFile);
	}
	
	public static void copyFile(File oldFile, File newFile){
		
		//2、創建流
		FileInputStream fis = null;
		BufferedInputStream bis = null;
		FileOutputStream fos = null;
		BufferedOutputStream bos = null;
		
		try {
			
			fis = new FileInputStream(oldFile);
			bis = new BufferedInputStream(fis);
			fos = new FileOutputStream(newFile);
			bos = new BufferedOutputStream(fos);
			
			//3、進行讀寫操作
			byte []byf = new byte[SIZE];
			int len = 0;// len記錄的是往字節數組裏存儲的字節個數。
			//先讀後寫
			while((len = bis.read(byf)) != -1){
				bos.write(byf, 0, len);
			}
			bos.flush();//沖刷沒有達到緩存限度的數據,確保數據全部寫完
			System.out.println("複製完成。。。");
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//4、關閉資源
			if(fis != null){
				try {
					fis.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(bis != null){
				try {
					bis.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(fos != null){
				try {
					fos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(bos != null){
				try {
					bos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
	}
	
}


發佈了33 篇原創文章 · 獲贊 15 · 訪問量 9817
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章