java程式 一次改變指定目錄下所有檔案編碼(包括子目錄中的檔案)
package transCoding;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class TransCoding {
//需要轉編碼的目錄
private static String path = “d:/action”;
//定義另存目錄。若不賦值(但此屬性的值必須為字串,如”“,不能為null)
//即當前目錄下檔案轉變編碼後會覆蓋,包括子目錄及其檔案
private static String directory = “d:/abc”;
//定義要轉的檔案型別。若不賦值(但此屬性的值必須為字串,如”“,不能為null)
//即轉變當前目錄下所有型別檔案,包括子目錄及其檔案。
private static String typeName = “”;
//要轉的檔案當前編碼,預設GBK。因為一般硬碟檔案預設ANSI,在中國即是GBK編碼。
private static String codeBefore = “GBK”;
//要轉的檔案轉後編碼,預設UTF-8。
//需要注意的是如果被編碼的檔案是全英文的,沒有漢字,那麼即使下面指定UTF-8,
//有些計算機也不能生成UTF-8檔案,可能與windows的轉碼有關,但全英文不影響效能。
private static String codeAfter = “UTF-8”;
public static void main(String[] args){ File dir = new File(path); File dirPath = new File(directory); change(dir,dirPath,typeName); } public static void change(File dir,File dirPath,final String typeName){ BufferedReader bufferedReader = null; BufferedWriter bufferedWriter =null; //獲得當前目錄下的所有符合條件的物件,包括目錄。 File[] files = dir.listFiles(new FilenameFilter(){ public boolean accept(File dir,String name){ //如果是目錄,直接返回true,意味著可以直接加入listFiles方法裡的集合中。 if(new File(dir,name).isDirectory()){ return true; }; return name.endsWith(typeName); } }); for (File file : files) { //如果沒有指定另存目錄名,此為當前目錄的絕對路徑 String pathAbsolute = null; //如果沒有指定另存目錄名,此為當前檔案編碼後的絕對路徑 File fileModify = null; //定義另存目錄物件 File createDir = null; //定義另存目錄中的檔案物件 File createFile = null; //如果當前file物件是一個目錄,再呼叫此方法,遞迴。 if(file.isDirectory()){ //獲取此目錄絕對路徑 String path = file.getAbsolutePath(); //截掉當前目錄 String path2 = path.substring(0,path.lastIndexOf("\\")); //獲取到上級目錄 String path3 = path2.substring(path2.lastIndexOf("\\")); //封裝成物件方便傳遞。 File file2 =null; if(dirPath.getName()==null||dirPath.getName().trim()==""){ change(file,dirPath,typeName); }else{ file2 = new File(dirPath,path3); change(file,file2,typeName); } }else{//不是目錄,直接轉碼 try { //讀取目錄下檔案,並按指定編碼讀取。 bufferedReader = new BufferedReader(new InputStreamReader( new FileInputStream(file.getAbsolutePath()),codeBefore)); //如果另存目錄為空,表示存放到當前目錄。 if(dirPath.getName()==null||dirPath.getName()==""){ //絕對路徑名 如 D:\action\1.txt pathAbsolute = file.getAbsolutePath(); //擷取後的路徑 如D:\action\ String path1 = pathAbsolute.substring(0, pathAbsolute.lastIndexOf(file.getName())); //新路徑 如 D:\action\11.txt String pathModify = path1+"1"+file.getName(); fileModify = new File(pathModify); bufferedWriter = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(fileModify),codeAfter)); }else{//否則,將轉碼後的檔案寫入指定的目錄 String path = file.getAbsolutePath(); String fileName = file.getName(); //獲取檔案所在的絕對路徑目錄 String path2 = file.getAbsolutePath().substring(0, path.lastIndexOf(fileName)-1); //獲取檔案所在的上一級目錄 String path3 = path2.substring(path2.lastIndexOf("\\")); //建立另存目錄 createDir = new File(dirPath,path3); //這裡是建立多級目錄,防止條件轉碼時(例如字尾名為.java或.txt), //符合條件的檔案太深,造成目錄建立失敗,導致IO寫入異常。 createDir.mkdirs(); createFile = new File(createDir,fileName); bufferedWriter = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(createFile),codeAfter)); } String line = null; while((line=bufferedReader.readLine())!=null){ bufferedWriter.write(line); bufferedWriter.newLine(); } //我覺得這裡寫不寫都一樣,最終關閉流的時候也會重新整理。 //如果寫入while迴圈裡會降低效率,每行都要重新整理。 //因為那樣寫入磁碟的次數就增多了 bufferedWriter.flush(); } catch (Exception e) { if(createDir!=null) createDir.deleteOnExit(); if(createFile!=null) createFile.deleteOnExit(); throw new RuntimeException("讀寫錯誤"+e); } finally{ if(bufferedReader!=null){ try { bufferedReader.close(); } catch (IOException e) { throw new RuntimeException("輸入流關閉錯誤"); } } if(bufferedWriter!=null){ try { bufferedWriter.close(); if(fileModify!=null){ //將原檔案刪除 file.delete(); //建立一個和原檔案同名的File物件 File file3 = new File(pathAbsolute); //將編碼後的檔名改成原檔名 fileModify.renameTo(file3); } } catch (IOException e) { throw new RuntimeException("輸出流關閉錯誤"); } } } } } }
}