我有一个大文本文件(大约2000万行),其中包含以下格式的行:
<string1>, <string2>
现在这些字符串可能有尾随或前导空格,我想在读取文件时将其删除。
我目前正在使用trim()
来实现此目的,但由于Java中的String是不可变的,trim()
正在为每个trim操作创建一个新对象。
这导致了太多的内存浪费。
我怎样才能做得更好?
答案 0 :(得分:2)
如果不可变的String
类导致问题,我会感到惊讶; JVM非常高效,是多年工程工作的结果。
也就是说,Java确实为操作名为StringBuilder
的字符串提供了一个可变类。您可以阅读文档here。
如果您正在跨线程工作,consider using StringBuffer
。
答案 1 :(得分:0)
您可以将字符串作为字符串读取,并记录要解析的每个标记的开始和结束位置。
这仍然会为每个标记创建一个对象,但如果您的标记相对较长,则对象将包含的两个int
字段比相应的字符串小得多。
但是在你开始这段旅程之前,你应该确保你没有把修剪好的琴弦放在比需要更长的时间。
答案 2 :(得分:0)
假设您有String
包含<string1>, <string2>
,并且您只是想拆分它而不修剪部分:
String trimmedBetween(String str, int start, int end) {
while (start < end && Character.isWhitespace(str.charAt(start)) {
++start;
}
while (start < end && Character.isWhitespace(str.charAt(end - 1)) {
--end;
}
return str.substring(start, end);
}
(请注意,这基本上是String.trim()
的实施方式,仅使用start
和end
代替0
和length
)
然后打电话给:
int commaPos = str.indexOf(',');
String firstString = trimmedBetween(str, 0, commaPos);
String secondString = trimmedBetween(str, commaPos + 1, str.length());
答案 3 :(得分:0)
正如您已经注意到的,字符串是不可变的。所以解决方案是不使用String,而是使用可变的东西。 StringBuffer
是一个合适的班级。
但是,StringBuffer不包含trim方法,因此您可以使用类似:
的内容void trim(StringBuffer sb) {
int start = 0;
while (sb.length() > start && Character.isWhitespace(sb.charAt(0))) {
start++;
}
sb.delete(0, start - 1);
int end = 0;
while (sb.length() > end && Character.isWhitespace(sb.charAt(sb.length() - 1))) {
end++;
}
sb.delete(sb.length() - end, sb.length() - 1);
}
答案 4 :(得分:0)
如果您想避免使用String
,则必须使用char
和StringBuilder
自行处理,如下所示:
public class Test {
public static void main(String... args) throws Exception {
InputStreamReader in = new InputStreamReader(new FileInputStream("<testfile>"), "UTF-8");
char[] buffer = new char[32768];
int read = -1;
int index;
StringBuilder content = new StringBuilder();
while ((read = in.read(buffer)) > -1) {
content.append(buffer, 0, read);
index = 0;
while (index > -1) {
index = content.indexOf("\n");
if (index > -1) {
char[] temp = new char[index];
content.getChars(0, index, temp, 0);
handleLine(temp);
content.replace(0, index + 1, "");
}
}
}
in.close();
}
private static void handleLine(char[] line) {
StringBuilder content = new StringBuilder().append(line);
int start = 0;
int end = content.length();
if (end > 0) {
char ch = content.charAt(0);
while (Character.isWhitespace(content.charAt(start))) {
start++;
if (end <= start) {
break;
}
}
if (start < end) {
while (Character.isWhitespace(content.charAt(end - 1))) {
end--;
if (end <= start) {
break;
}
}
}
}
System.out.println("***" + content.subSequence(start, end) + "***");
}
}
答案 5 :(得分:0)
我们可以通过Regex处理。
{
String str = "abcd, efgh";
String [] result = str.split("(,\\s)|,");
Arrays.asList(result).forEach(s -> System.out.println(s));
}
答案 6 :(得分:-1)
我认为您可以直接将结果数据写入新文件。
String originStr = " xxxxyyyy";
for (int i = 0; i < originStr.length(); i++) {
if (' ' == originStr.charAt(i)) {
continue;
}
NewFileOutPutStream.write(originStr.charAt(i));
}