我的程序在一個目錄上迭代並使用以下函數從我的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的最大大小
文件有多大?千字節?兆?千兆字節?爲什麼你需要充分閱讀它們,這看起來非常浪費,你可以嘗試將它們作爲一個流處理(即讀一點,寫一點,...)。最後但並非最不重要的一點是:如果您只是在不修復頭文件的情況下「重新編碼」一個XML文件,那麼它很容易變得不正常:如果頭文件提到的編碼不同於實際使用的編碼,那麼確認XML解析器*必須*一個錯誤(如果它可以檢測到)。 –
大部分是Kb,一些在幾MB,但由於某種原因,有一個300Mb的pom.xml,很奇怪。我只是爲了方便閱讀整個文件,還沒有找到一個文件流,我可以使用編碼,任何建議?我目前正在用eclipse上的XML文件替換編碼,但我打算很快將它放入代碼中。謝謝! –