首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 批量處理指定目錄下文件讀寫操作實戰:國際化插件自動化改造

     編輯:Java 程式設計入門

項目背景

項目包含 100+ 插件需進行國際化改造,純手工修改工作量巨大。編寫自動化工具掃描 .java 文件,識別硬編碼中文字符串,自動插入 //$NON-NLS-n$ 標記供 Eclipse 國際化向導識別,大幅降低人工成本。

核心模塊實現

1. 文件讀取(指定 GBK 編碼)

public static String readFile(String path) throws IOException {
    File f = new File(path);
    StringBuilder res = new StringBuilder();
    try (FileInputStream fis = new FileInputStream(f);
         InputStreamReader isr = new InputStreamReader(fis, Charset.forName("GBK"));
         BufferedReader br = new BufferedReader(isr, 8192 * 8)) {
        String line;
        while ((line = br.readLine()) != null) {
            res.append(line).append("\r\n");
        }
    }
    return res.toString();
}

2. 文件寫入(保持 GBK 編碼)

public static boolean writeFile(String content, String path) {
    try (OutputStreamWriter writer = new OutputStreamWriter(
            new FileOutputStream(path), "GBK")) {
        writer.write(content);
        return true;
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
}

3. 遞歸掃描目錄(FileFilter 過濾 .java 文件)

private static final FileFilter JAVA_FILTER = pathname -> 
    pathname.isDirectory() || pathname.getName().toLowerCase().endsWith(".java");

public static void findFile(File f) throws IOException {
    if (!f.exists()) return;
    if (f.isDirectory()) {
        for (File sub : f.listFiles(JAVA_FILTER)) {
            findFile(sub);
        }
    } else {
        updateFile(f);
    }
}

4. 行級處理與標記插入邏輯


private static void updateFile(File f) throws IOException {
    StringBuilder res = new StringBuilder();
    int modifiedLines = 0;
    
    try (BufferedReader br = new BufferedReader(
            new InputStreamReader(new FileInputStream(f), Charset.forName("GBK")), 8192 * 8)) {
        String line;
        while ((line = br.readLine()) != null) {
            String updated = updateLine(line);
            res.append(updated).append("\r\n");
            if (!line.trim().equals(updated.trim())) modifiedLines++;
        }
    }
    
    if (modifiedLines > 0) {
        System.out.printf("文件修改: %s, 修改行數: %d%n", f.getPath(), modifiedLines);
        writeFile(res.toString(), f.getPath());
    }
}

private static String updateLine(String line) {
    if (shouldSkip(line) || countChineseChars(line) == 0) return line;
    
    int chineseCount = countChineseChars(line);
    StringBuilder markers = new StringBuilder();
    for (int i = 1; i <= chineseCount / 2; i++) {
        markers.append(" //$NON-NLS-").append(i).append("$");
    }
    return line + markers;
}

// 過濾條件:import/package/class/註釋/註解/純英文/空行 等
private static boolean shouldSkip(String line) {
    String trimmed = line.trim();
    return trimmed.startsWith("import ") 
        || trimmed.startsWith("package ")
        || trimmed.contains(" class ")
        || trimmed.contains("//$NON-NLS")
        || trimmed.startsWith("//")
        || trimmed.startsWith("/*")
        || trimmed.contains("*")
        || trimmed.startsWith("@")
        || !line.contains("\"")
        || trimmed.isEmpty()
        || containsChinese(trimmed); // 原邏輯似有誤,此處按意圖修正
}

private static boolean containsChinese(String str) {
    return Pattern.compile("[\u4E00-\u9FA0]").matcher(str).find();
}

private static int countChineseChars(String str) {
    Matcher m = Pattern.compile("[\u4E00-\u9FA0]").matcher(str);
    int count = 0;
    while (m.find()) count++;
    return count;
}

關鍵技術點總結

  • 編碼一致性:讀寫均指定 GBK,避免中文亂碼
  • 緩衝區優化:BufferedReader(..., 64KB) 提升大文件讀取性能
  • 流式處理:逐行讀取處理,內存佔用恆定
  • 正則識別中文:Unicode 範圍 \u4E00-\u9FA0 覆蓋常用漢字
  • 冪等性設計:已含標記行跳過,可重複執行

工程化建議

  1. 引入參數化配置:源目錄、目標編碼、標記格式
  2. 增加備份機制:修改前複製原文件至 .bak
  3. 接入版本控制:自動提交變更或生成 Patch 文件
  4. 並行處理:使用 ForkJoinPool 或線程池加速大項目掃描
  5. 單元測試覆蓋:驗證各類邊界情況(混合中英、轉義字符、多行字符串等)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved