2016-04-19 2 views
2

в моей программе я хочу, чтобы прочитать файл PLSQL и удалять комментарии, которые начинаются с -
я кладу каждый комментарий в своей собственной линии, так что я мог бы удалить эту конкретную строку (иногда у меня есть код и комментарии в той же строке, что я делаю «\ n--»).
я экспортировать свою программу в файл банка, и он прекрасно работает на моем рабочем столе, но на другом компьютере (чтение различных файлов PLSQL) это дает мне Java ошибку кучи пространства, даже когда я пытаюсьJava ошибка кучи, когда добавить к StringBuilder

ява -Xmx256m -jar myjar .jar

ошибка:

Exception in thread "main" java.lang.reflect.InvocationTargetException 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58) 

Caused by: java.lang.OutOfMemoryError: Java heap space 
    at java.util.Arrays.copyOf(Unknown Source) 
    at java.lang.AbstractStringBuilder.expandCapacity(Unknown Source) 
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(Unknown Source) 
    at java.lang.AbstractStringBuilder.append(Unknown Source) 
    at java.lang.StringBuffer.append(Unknown Source) 
    at ParserDB.ScriptNoComment(ParserDB.java:142) 
    at ParserDB.GetTheName(ParserDB.java:54) 
    at Rapport.SearchCcInDB(Rapport.java:189) 
    at Rapport.listDB(Rapport.java:77) 
    at Rapport.main(Rapport.java:472) 
    ... 5 more 

мой код:

public static String ScriptNoComment(String fileName){ 
    String result = null ;  
    try{ 
     FileInputStream fstream = new FileInputStream(fileName); 
     DataInputStream in = new DataInputStream(fstream); 
     BufferedReader br = new BufferedReader(new InputStreamReader(in)); 
     StringBuffer strOut = new StringBuffer(); 
     StringBuilder Out = new StringBuilder(); 
     String strLine; 

     while ((strLine = br.readLine()) != null) { 

      if(strLine.contains("--")){ 
       strLine = strLine.replaceAll("--","\n--"); 
      } 
      strOut.append(strLine+"\n"); 
     } 

     in.close(); 
     //delete comment 
     String[] lines = strOut.toString().split("\\n"); 
     for(String s: lines){ 
      if(s.contains("--")){ 
       s=""; 
      } 
      Out.append(s+"\n"); 
     } 

     result = Out.toString(); 
     result = result.toUpperCase();  
     result = result.replaceAll("\"", ""); 
     result = result.replaceAll("\\r\\n|\\r|\\n", " "); 
     result = result.replaceAll("\\s+", " "); 

     }catch (Exception e){   
     System.err.println("Error: " + e.getMessage()); 
     } 

    return result ; 

} 

есть в любом случае, чтобы оптимизировать свой код, заранее спасибо

EDIT
1) я проверил размер кучи в другом компьютере с помощью команды:

Java -XX: + PrintFlagsFinal -version | Findstr/я "HeapSize PermSize ThreadStackSize"

результат был: мин: 16M и MaxSize: 256M поэтому я должен ленты в Java -jar: -Xmx512m вместо -Xms256m

2-) я удалил (только для теста) строковый конструктор и все replaceAll и по-прежнему получил ту же ошибку, потому что мой файл был слишком большим.

так, что я сделал это, чтобы подсчитать строки для каждого файла, что я читаю и стараюсь (в зависимости от линий) читать только 50 первых строк, например, и применять свои методы только этой 50 линий

спасибо всем за ответы

+0

Может быть, просто дайте ему больше кучи? -Xmx2g, например. –

+0

Лучше использовать подход Stream. Если ваш текст большой, он будет потреблять много памяти, потому что каждая операция выделяет 'new String()'. Если у вас возникли проблемы при чтении файла, у вас возникнут большие проблемы с операциями regexp. – gaborsch

+2

Эта программа является сложной задачей. В конце у вас есть StringBuffer, содержащий вход, массив строк с тем же содержимым и StringBuilder, который также содержит все, кроме комментариев. Это в три раза больше потребности в памяти. Вместо этого вы можете просто прочитать файл по строкам, проверить, содержит ли строка комментарий (или представляет собой контент) и опустить/укоротить его, если это так. Вы также можете делать замены на линии, поэтому вам не нужны они в результате. При этом ваше требование к памяти будет значительно уменьшено. –

ответ

1

Если у вас есть Java 8, вы можете попробовать этот код для встроенного редактирования строк, как вы обрабатываете их

public static String scriptNoComment(String fileName) { 

    Path filePath = Paths.get(fileName); 
    try (Stream<String> stream = Files.lines(filePath)) { 

    List<String> linesWithNoComments = new ArrayList<String>(); 

    stream.forEach(line -> { 

     if (line.startsWith("--")) { 
     return; 
     } 

     String currentLine = line; 

     int commentStartIndex = line.indexOf("--"); 
     if (commentStartIndex != -1) { 
     currentLine = line.substring(0, commentStartIndex); 
     } 

     currentLine = currentLine.toUpperCase(); 
     currentLine = currentLine.replaceAll("\"", ""); 
     currentLine = currentLine.replaceAll("\\r\\n|\\r|\\n", " "); 
     currentLine = currentLine.replaceAll("\\s+", " ").trim(); 

     if (currentLine.isEmpty()) { 
     return; 
     } 

     linesWithNoComments.add(currentLine); 

    }); 

    return String.join("\n", linesWithNoComments); 

    } catch (IOException e) { 
    e.printStackTrace(System.out); 
    return ""; 
    } 
} 

Если Java-не вариант, то вы можете использовать Apache StringUtils::join и FileUtils::LineIterator для достижения тот же результат. Надеюсь, это решает проблему.

РЕДАКТИРОВАТЬ

После Nicolas Filotto предположения я добавил записи в файл после того, как определенное количество обработанных строк (число было выбрано совершенно случайно). Я тестировал оба метода, и первый из них не работает с файлами, размер которых близок к размеру кучи (объединение строк в строке имеет ту же проблему, что и код OP). При втором подходе, который я тестировал с файлом 2 ГБ, и после выполнения 2 мин, у меня был файл ${fileName}_noComments рядом с входным файлом.

public static int LINES_BATCH = 10000; 

private static void scriptNoComment(String fileName) { 

    Path filePath = Paths.get(fileName); 
    try (Stream<String> stream = Files.lines(filePath); BufferedWriter fileOut = getFileOutWriter(fileName)) { 

    List<String> linesWithNoComments = new ArrayList<String>(); 

    stream.forEach(line -> { 

     if (line.startsWith("--")) { 
     return; 
     } 

     String currentLine = line; 

     int commentStartIndex = line.indexOf("--"); 
     if (commentStartIndex != -1) { 
     currentLine = line.substring(0, commentStartIndex); 
     } 

     currentLine = currentLine.toUpperCase(); 
     currentLine = currentLine.replaceAll("\"", ""); 
     currentLine = currentLine.replaceAll("\\r\\n|\\r|\\n", " "); 
     currentLine = currentLine.replaceAll("\\s+", " ").trim(); 

     if (currentLine.isEmpty()) { 
     return; 
     } 

     linesWithNoComments.add(currentLine); 

     if (linesWithNoComments.size() >= LINES_BATCH) { 
     writeCurrentBatchToFile(fileOut, linesWithNoComments); 
     } 

    }); 

    } catch (IOException e) { 
    e.printStackTrace(System.err); 
    } 
} 

private static BufferedWriter getFileOutWriter(String fileName) { 
    BufferedWriter fileOut; 
    try { 
    fileOut = new BufferedWriter(new FileWriter(fileName + "_noComments", false)); 
    return fileOut; 
    } catch (IOException e) { 
    throw new RuntimeException("Error while creating out writer", e); 
    } 
} 

private static void writeCurrentBatchToFile(BufferedWriter fileOut, List<String> linesWithNoComments) { 
    try { 

    for (String line : linesWithNoComments) { 
     fileOut.write(line + " "); 
    } 

    linesWithNoComments.clear(); 
    } catch(IOException e) { 
    throw new RuntimeException("Unable to write lines to file", e); 
    } 
} 
+0

'ArrayList' не лучше, чем' StringBuilder'. Лучше использовать [StringWriter] (https://docs.oracle.com/javase/7/docs/api/java/io/StringWriter.html) с начальной емкостью файла. – gaborsch

1

вы используете:

strLine = strLine.replaceAll("--","\n--"); 

, а затем вы пишете в строку буфера затем в строку Builder.

Поскольку вы просто хотите, чтобы удалить эти комментарии, заменить

if(strLine.contains("--")){ 
     strLine = strLine.replaceAll("--","\n--"); 
    } 
    strOut.append(strLine+"\n"); 

с

int chk=strLine.indexOf("--"); 
     if(chk!=-1) 
     strLine = strLine.subtring(0,chk); 
    Out.append(strLine +"\n"); 

Надеемся, что это решает проблему, как вы не будете с помощью StringBuffer и использование меньшего объема памяти.

+0

thank u Это было действительно полезно – maryam

2

Предполагая, что ваш файл PLSQL является огромный, ваша проблема здесь, вероятно, связано с тем, что Вы загружаете the entire file into memory, который не является хорошим подходом в этом случае, вы должны read его построчно и write результат в temporary file вместо того, чтобы возвращать содержимое как String.

Это немного сложнее написать, но это гораздо более масштабируемый подход, действительно, предположим, что сегодня вы увеличиваете размер кучи до 4Go, завтра файл будет вдвое больше, вы удвоите размер своей кучи?

Смежные вопросы