1. 程式人生 > >java IO 位元組流、字元流操作總結一之File類

java IO 位元組流、字元流操作總結一之File類

這篇文章將介紹有關java IO輸入輸出流的知識。首先說說字元編碼的問題,比較常用的編碼有gbk,utf-8等。

1.gbk 編碼中文佔用2個位元組,英文佔用1個位元組。

2、utf-8編碼中文佔用3個位元組,英文佔用1個位元組。

Java是雙位元組編碼,utf-16be編碼。即char佔用2個位元組。注意:當你的位元組序列是某種編碼時,這個時候想把位元組序列變成字串,也需要用這種編碼方式。否則會出現亂碼。文字檔案就是位元組序列,可以是任意編碼的位元組序列。但是通常我們在中文的機器上直接建立檔案,那麼該檔案只認識ANSI編碼。


首先,介紹IO常用的第一個類File類(普通檔案類)。

1、File類常用的API介紹

Java.IO.File類用於表示檔案(目錄),File類只用於表示檔案(目錄)的資訊(大小,名稱)等,不能用於檔案內容的訪問。常用的API如下:

boolean exists();判斷檔案是否存在
File file=new File(String path);<span style="font-family: Arial, Helvetica, sans-serif;">建立File物件,</span>這裡path就是檔案的絕對位置,如:c:\\file\\dooc 或者c:/file/dooc.txt都可以。
file.mkdir();建立目錄
file.isDirectory();測試此抽象路徑名錶示的檔案是否是一個目錄。
file.isfile();測試此抽象路徑名錶示的檔案是否是一個檔案。
file.delete();刪除這個檔案或者目錄
file.creatNewFile();建立新檔案
file.getName();獲取檔名或者目錄的名稱
file.getAbsolutepath();獲取絕對路徑
file.getParent();獲取父級路徑,如果沒有則返回null
String[] list();返回一個字串陣列,這些字串指定此抽象路徑名錶示的目錄中的檔案和目錄。
File[] listfiles();返回一個抽象路徑名陣列,這些路徑名錶示此抽象路徑名錶示的目錄中的檔案。
File類中的list()方法用於列出當前的目錄下的子目錄和檔案,返回的是字串陣列。直接列出子目錄的檔案,但不包含子目錄的檔案內容。

程式碼如下:

//實現一個遍歷File物件的指定檔案目錄下的所有檔案

public static void listDirectory(File dir) throws IOException{
		//判斷dir目錄存不存在
		try {
			if(dir.exists()){
				System.out.println("該目錄存在");
			}else{
				throw new IllegalArgumentException("這個目錄不存在");
			}
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println(e);
		}
		//判斷目錄下是否有檔案
		try {
			if(dir.isDirectory()){
				System.out.println("該目錄存在資料夾");
			}else{
				throw new IllegalArgumentException("該目錄不存在檔案");
			}
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println(e);
		}
		
		//方法一是呼叫list()方法來遍歷,該方法返回的是一個字串型別的陣列
		//我們依次遍歷看看看結果
//		String[] strs=dir.list();//返回的是路徑名字串陣列
//		//使用foreach語句來遍歷
//		for (String string : strs) {
//			System.out.println(dir+"\\"+string);//加上根目錄顯示
//		}
//		
//		System.out.println("上面的方法只能顯示到子檔案型別,既不能顯示具體"
//				+ "的檔名稱,也不能顯示子檔案下的檔案");
		System.out.println("");
		//下面呼叫listFile()方法,該方法返回的是File物件的陣列。同時可以直接獲取file下的所有檔案
		File[] files=dir.listFiles();//返回的是檔案物件陣列
		if(files!=null && files.length>0){//獲取的陣列即不為空,也不為0長度陣列
			for (File file : files) {//遍歷每一個檔案
				
				if(file.isDirectory()){//檢視是否還有檔案在下面
					listDirectory(file);//遞迴呼叫,直到沒有子檔案為止
				}
				else{
					System.out.println(file);
				}
			}
		}
	}

總結:上面的測試類中包裝了一些File的常用操作,例如過濾和遍歷等:

1、列出指定目錄下的(包含子目錄)的所有檔案。(這裡是通過獲取檔案陣列、遍歷檔案和遞迴呼叫實現的)

如果傳進來的目錄不存在或者不是資料夾,則應該丟擲異常。這時我們需要用到判斷語句。

2、file.list()方法;該方法返回當前目錄下的檔名的字串陣列,但是不包含子目錄下的檔案和目錄。

3、File[] files=file.listFile();可以直接獲取file檔案下的所有檔案或者目錄物件。然後以File物件陣列的形式返回。然後可以呼叫遞迴就可以把所有的目錄下的檔案路徑讀出來,或者獲取檔案。

 

2、任意操作的檔案類,RandomAccessFile類介紹。  

RandomAccessFile類對檔案進行訪問讀寫檔案。隨機訪問檔案即指在檔案的任意的位置上都可以。java檔案模型在硬碟上的檔案時,是以(位元組)byte byte byte儲存的,是資料的集合。

--開啟檔案

RandomAccessFile類,在開啟檔案時有2種模式可以開啟檔案:rw 讀寫模式和r只讀模式。

如:RandomAccessFile  raf=new RandomAccessFile(file,”rw”);

這裡file的初始化如下:File file=new File(String path);

其中在讀寫檔案時會有檔案指標的存在,開啟檔案時檔案的指標在開頭,即pointer=0;

--寫方法

raf.write(int);當寫一個int型資料時只寫一個位元組(即最後8位,注意這裡是一個位元組一個位元組的寫。所以一個int型資料要分4次寫進),同時檔案指標pointer指向下一個位置準備再次寫入。

--讀方法

 raf.seek(0);//將檔案指標指向最開始的頭部

 byte[] buf=new byte[(int)raf.length()];//讀取指定長度的位元組內容

 raf.read(buf);//讀取指定長度的位元組內容,並將內容儲存在buf陣列中

 //讀取一個位元組

 raf.seek(0);//將檔案指標指向最開始的頭部

 int b=raf.read();//只讀取一個位元組

檔案讀寫完畢後,一定要記得關閉檔案

raf.close(); 

程式碼如下:

package com.ll.iofile;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;

/**
 * 此方法用來測試RandomAccessFile類,用於讀寫檔案
 * @author LULEI
 *
 */
public class testRandomAccessFile {

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		
		File file=new File("Demo");//判斷相對路徑中是否存在指定的目錄
		if(!file.exists()){
			file.mkdir();//新建一個Demo目錄
		}
		File file2=new File(file,"wq.bat");//將指定的檔案例項化給file2物件
		if(!file2.exists()){
			file2.createNewFile();//新建一個wq.bat檔案
		}
		
		//建立一個從中讀取和向裡面寫入的一個隨機訪問的檔案流.該檔案要有指定的名稱
		RandomAccessFile raf=new RandomAccessFile(file2,"rw");//設定為讀寫模式
		//首先觀察一下檔案指標的位置
		System.out.println("檔案指標的初始化位置在:"+raf.getFilePointer());
		
		//向檔案流中進行寫,注意一次只寫一個位元組
		raf.write('A');//注意char型字元佔兩個位元組
		System.out.println("檔案指標的位置在:"+raf.getFilePointer());
		String s="中";
		byte[] sTObyte=s.getBytes("gbk");//設定為國標
		raf.write(sTObyte);
		System.out.println("新增中文後的檔案指標的位置:"+raf.getFilePointer());
		
		int iNum=89;//Int型資料要分4次寫入到檔案中,一次一個byte
		raf.write(iNum>>>24);
		raf.write(iNum>>>16);
		raf.write(iNum>>>8);
		raf.write(iNum>>>0);
		System.out.println("普通方法新增int型資料後的檔案指標的位置:"+raf.getFilePointer());
		byte[] bt={1,2,3,4};
		//可以寫陣列
		raf.write(bt);
		System.out.println("新增byte陣列後的檔案指標的位置:"+raf.getFilePointer());
		//可以直接寫一個Int型別的資料
		raf.writeInt(20);//int佔4個位元組
		System.out.println("新增int型資料後的檔案指標的位置:"+raf.getFilePointer());
		
		/*
		 * 向檔案流進行讀操作
		 */
		//一次只讀一個位元組的內容
		
		raf.seek(0);//讀取資料之前一定要將檔案指標指向頭部
		int num=raf.read();
		System.out.println("只讀一個位元組返回的內容:"+Integer.toString(num));
		int num2=raf.read();
		System.out.println("只讀一個位元組返回的內容(十六進位制顯示):"+Integer.toHexString(num2&0xff));
		
		/*讀取一定長度的位元組的內容
		 * 讀取檔案前,一定要把檔案指標指向開頭
		 */
		raf.seek(0);
		int n=(int)raf.length();//獲取檔案流中內容的位元組長度
		//建立一個同樣長度大小的byte陣列
		byte[] buf=new byte[n];
		raf.read(buf);//讀取指定長度的位元組內容,並將內容複製到buf陣列中
		System.out.println("讀取一定長度返回的內容");
		System.out.println(Arrays.toString(buf));
		for (byte b : buf) {
			System.out.print(Integer.toHexString(b & 0xff)+" ");
		}
		
		/*
		 * 最後關掉檔案
		 */
		raf.close();
	}

}

這篇就先介紹到這裡。其實我在寫這句程式碼時(如下):

RandomAccessFile  raf=new RandomAccessFile(file,”rw”);
不知道有沒有想到設計模式。是的,這裡實際上就是一個裝飾器模式。RandomAccessFile類是裝飾器類,而File類是被裝飾器類。通過包裝,我們將原來的File類擴充套件為RandomAccessFile類。所以功能也就大大的提高了,其實在Java的整個IO框架中都大量的使用了裝飾器模式。

這一篇就介紹到這裡,下一篇將介紹Java 中IO的位元組流。