Моя программа выполняет итерацию по каталогу и использует следующую функцию из моего класса Recoder для чтения файла с использованием FileUtils.readFileToString
по кодировке и перезаписывает он использует FileUtils.write
на другой кодировке.«java.lang.OutOfMemoryError: Java heap space» При вызове FileUtils.readFileToString в xml-файлах
Однако, когда он пытается сделать это с помощью xml-файла, я получаю исключение в заголовке, в противном случае он отлично работает (я тестировал в каталоге с .java, .js, .css, .html, .jsp ...).
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();
}
}
Things отметить:
- Я использую следующие параметры виртуальной машины на Eclipse, -Xms1024m -Xmx2048m
- JDK версии 1.7. 0_75
- Я экспериментировал с некоторыми System.gc(), но безрезультатно
- Это происходит только тогда, когда основной работает рекурсивно (
decArgs.recursive=true
), тот же файл, который генерирует исключение, перекодируется плавно, когда - Уже проверено кодирование файла на bash и жестко закодировано для теста, и удачи там нет.
Любые идеи о том, почему это происходит?
Заранее благодарен!
EDIT: Использование Recoder.recodeToUTF
метод вместо Recoder.recodeFile
вызывает не OutOfMemory не быть выброшен. Возможно, попытка открыть с неправильной кодировкой вызывает утечку памяти.
Анализ созданного .hprof файла (messed up) 300Mb xml использовал около 500 Мб кучи. Тем не менее, куча установлена на максимальный размер 2Gb
Насколько велики файлы? Килобайт? Мегабайт? Гигабайт? Зачем вам читать их полностью, что кажется очень расточительным, вы можете попробовать обработать их как поток (читайте немного, напишите немного, ...). И последнее, но не менее важное: если вы просто «перекодируете» файл XML без исправления заголовка, то он может легко закончиться неверно: если заголовок упоминает другую кодировку, чем то, что на самом деле используется, подтверждающий синтаксический анализатор XML * должен * сообщить об этом как ошибка (если она может обнаружить это). –
большинство находится в Кб, некоторые в нескольких Мб, но по какой-то причине был pom.xml с 300 МБ, очень странный. Я читаю весь файл сразу только для удобства, пока не нашел Файловый поток, где я мог бы играть с кодировками, любыми предложениями? Я в настоящее время заменяю кодировку из XML-файлов на eclipse, но я планирую вставить ее в код очень скоро. Благодаря! –