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的位元組流。