2015-05-13 25 views
1

我的程序在一個目錄上迭代並使用以下函數從我的Recoder類讀取一個文件,使用FileUtils.readFileToString編碼並覆蓋它使用另一種編碼方式使用FileUtils.write。但是,當它試圖用xml文件做到這一點時,我在標題處得到異常,否則,它工作正常(我已經在.java,.js,.css,.html, .JSP ...)。「java.lang.OutOfMemoryError:Java heap space」當在xml文件上調用FileUtils.readFileToString

public class Recoder { 
    private static Charset fromCharset; 
    private static Charset toCharset; 

    public static void recodeToUTF(File f, boolean verbose){ 
     try{ 
      if(verbose){ 
       System.out.println("Convertendo "+f.getAbsolutePath()+" para UTF-8"); 
      } 
      toCharset = Charset.forName("UTF-8"); 
      String content = FileUtils.readFileToString(f); 
      FileUtils.write(f,content, toCharset); 
     }catch(Exception e){  
     } 
    } 

    public static void recodeFile(File f, String de, String para, boolean verbose){ 
     try{ 
      if(verbose){ 
       System.out.println("Convertendo "+f.getAbsolutePath()+" de "+ de + " para "+ para); 
      } 
//   CharsetDetector cd= new CharsetDetector(); 
//   FileInputStream fis = new FileInputStream(f); 
//   cd.setText(fis); 
//   fis.close(); 
//   CharsetMatch cm = cd.detect(); 

//   if(cm!=null){ 
//    fromCharset = Charset.forName(cm.getName()); 
//   }else{ fromCharset = Charset.forName(de);} 
      fromCharset = Charset.forName(de); 
      toCharset = Charset.forName(para); 
      String content = FileUtils.readFileToString(f,fromCharset); 
      FileUtils.write(f,content,toCharset); 
      content=null; 
     }catch(Exception e){  
     } 
    } 

    public static String removeAcentos(String str) { 
     str = Normalizer.normalize(str, Normalizer.Form.NFD); 
     str = str.replaceAll("[^\\p{ASCII}]", ""); 
     return str; 
    } 

} 

的CharsetDetector東西是從ICU4J,以及由於某種原因,當調用cd.detect(),因此,現在,我剛剛離開它的意見掛起。

這是調用它的主:

public static void main(String[] args){ 
     DecoderArguments decArgs = new DecoderArguments(); 
     JCommander jc = new JCommander(decArgs, args); 
     try { 
      if(args.length>0){ 
       for(String s : decArgs.files){ 
        File file; 
        if (decArgs.recursive){ 
         System.out.println("Executando Recursivamente em: "+ s); 
         file = new File(s); 
         if(file.isDirectory()){ 
          Collection<File> files = FileUtils.listFiles(file,FileFileFilter.FILE, DirectoryFileFilter.DIRECTORY); 
          for (File f : files){ 
           boolean exec=true; 
           for(String excl : decArgs.excludes){ 
            if (f.getAbsolutePath().contains(excl)) exec=false; 
           } 
           if (file.exists() && exec){ 
            if("".equals(decArgs.fromEncoding)){ 
             Recoder.recodeToUTF(f, decArgs.verbose); 
            }else { 
             Recoder.recodeFile(f, decArgs.fromEncoding, decArgs.toEncoding, decArgs.verbose); 
            } 
            System.gc(); 
           }       
          } 
         }else{ 
          System.out.println("Por favor, informe um diretorio para ler recursivamente.\n" 
            + "Uso: java -jar decoder.jar <-r> Caminho|Arquivo"); 
         }  
        }else{ 
         System.out.println("Convertendo arquivo: "+ s); 
         file = new File(s); 
         boolean exec=true; 
         for(String excl : decArgs.excludes){ 
          if (file.getAbsolutePath().contains(excl)) exec=false; 
         } 
         if (file.exists() && exec){ 
          if("".equals(decArgs.fromEncoding)){ 
           Recoder.recodeToUTF(file, decArgs.verbose); 
          }else { 
           Recoder.recodeFile(file, decArgs.fromEncoding, decArgs.toEncoding, decArgs.verbose); 
          } 
         } 
        } 
       } 
      }else if (args.length==0){ 
       System.out.println("Sintaxe incorreta.\n"); 
       jc.usage(); 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

注意事項:

  • 我使用Eclipse的-Xms1024m -Xmx2048m
  • JDK 1.7版本以下的VM參數。 0_75
  • 我試過一些System.gc()但沒有效果
  • 它只發生在main遞歸運行(decArgs.recursive=true),拋出異常的相同文件在
  • 中順利重新編碼。已在bash上檢查文件編碼並對其進行硬編碼以進行測試,但也沒有運氣。

關於爲什麼會發生這種情況的任何想法?

在此先感謝!

編輯: 使用​​方法代替Recoder.recodeFile不會引起內存不足的拋出。也許試圖用錯誤的編碼打開導致內存泄漏。

分析生成的.hprof,(搞砸的)300Mb xml文件使用大約500Mb的堆。但是,堆設置爲2Gb的最大大小

+0

文件有多大?千字節?兆?千兆字節?爲什麼你需要充分閱讀它們,這看起來非常浪費,你可以嘗試將它們作爲一個流處理(即讀一點,寫一點,...)。最後但並非最不重要的一點是:如果您只是在不修復頭文件的情況下「重新編碼」一個XML文件,那麼它很容易變得不正常:如果頭文件提到的編碼不同於實際使用的編碼,那麼確認XML解析器*必須*一個錯誤(如果它可以檢測到)。 –

+0

大部分是Kb,一些在幾MB,但由於某種原因,有一個300Mb的pom.xml,很奇怪。我只是爲了方便閱讀整個文件,還沒有找到一個文件流,我可以使用編碼,任何建議?我目前正在用eclipse上的XML文件替換編碼,但我打算很快將它放入代碼中。謝謝! –

回答

1

您的內存正在泄漏,因此爲了檢查問題,您可以使用這些參數 配置您的JVM -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/dump。當OutOfMemoryError被拋出時,會在/path/to/dump中創建轉儲。然後,您可以使用Eclipse Memory Analyzer進行分析,並查找泄漏您的記憶的對象。 不錯的教程here

+0

謝謝,我會努力的。(可以注意投票) –

相關問題