附加到stringBuilder时发生java堆错误
在我的程序中,我想读取一个PLSQL文件 并删除以--附加到stringBuilder时发生java堆错误,java,regex,stringbuilder,heap-memory,Java,Regex,Stringbuilder,Heap Memory,在我的程序中,我想读取一个PLSQL文件 并删除以-- 我将每个注释都放在它自己的行中,这样我就可以删除特定的行(有时我将代码和注释放在同一行中,这是我执行“\n--”的方式)。 我将我的程序导出到一个jar文件,它在我的桌面上运行良好,但在另一台计算机上(读取不同的PLSQL文件),即使我尝试,它也会给我Java堆空间错误 java-Xmx256m-jar myjar.jar 错误: Exception in thread "main" java.lang.reflect.Invocation
我将每个注释都放在它自己的行中,这样我就可以删除特定的行(有时我将代码和注释放在同一行中,这是我执行“\n--”的方式)。
我将我的程序导出到一个jar文件,它在我的桌面上运行良好,但在另一台计算机上(读取不同的PLSQL文件),即使我尝试,它也会给我Java堆空间错误 java-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 ;
}
是否有任何优化我的代码,提前感谢
编辑1-) 我使用以下命令检查了另一台计算机中的堆大小: java-XX:+PrintFlagsFinal-version | findstr/i“HeapSize PermSize ThreadStackSize” 结果是:最小值为16米,最大值为256米 所以我应该在java-jar中使用-Xmx512m而不是-Xms256m 2-) 我删除了(只是为了测试)stringbuilder和所有replaceAll,但仍然得到了相同的错误,因为我的文件太大了 因此,我所做的是计算我正在读取的每个文件的行数,并尝试(根据行数)仅读取前50行,例如,将我的方法仅应用于这50行 感谢大家的回答您正在使用:
strLine = strLine.replaceAll("--","\n--");
然后写入字符串缓冲区,然后写入字符串生成器
因为您只想删除这些评论,
替换
与
希望这能解决您的问题,因为您不会使用StringBuffer并占用更少的内存。如果您有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 "";
}
}
假设您的
PLSQL
文件是巨大的,您这里的问题可能是因为您将整个文件加载到内存中
,这不是本例中的好方法,您应该逐行读取
并将结果写入临时文件
,而不是将内容作为字符串
返回
写起来有点复杂,但它是一种更具可伸缩性的方法。比如说,今天您将堆大小增加到4Go,明天文件将增加两倍,您会将堆大小增加一倍吗?也许可以给它更多的堆空间-Xmx2g例如,最好使用流方法。如果文本较大,则会消耗大量内存,因为每个操作都会分配一个新字符串()
。如果你在读取文件时遇到麻烦,你将在regexp操作中遇到更大的麻烦。这个程序非常复杂。最后,您有一个包含输入的StringBuffer、一个具有相同内容的字符串数组和一个StringBuilder,它还包含除注释以外的所有内容。这是内存需求的三倍。相反,您可以逐行读取文件,检查该行是否包含注释(或内容),如果是,则省略/缩短它。您也可以在线进行替换,因此结果中不需要它们。这样做,您的内存需求将大大降低。@uWealner使用-Xmx2g是否有任何损坏,我的意思是这个java-Xmx2g-jar myjar.jar是否可以阻止我的计算机?@ammoQ是的,但有时我的代码和注释与我的做法相同“\n-”ArrayList
并不比StringBuilder
好。最好使用初始容量为文件大小的。
int chk=strLine.indexOf("--");
if(chk!=-1)
strLine = strLine.subtring(0,chk);
Out.append(strLine +"\n");
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 "";
}
}
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);
}
}