1. 程式人生 > >java程式 一次改變指定目錄下所有檔案編碼(包括子目錄中的檔案)

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("輸出流關閉錯誤");
                    }
                 }
            }

         }
     }
 }

}