0

我正在阅读一个文件以供稍后解析。该文件的大小不可能超过 MB,因此在现阶段这对我来说可能不是一个关键问题。但出于最佳实践的原因,我想知道何时是执行操作的最佳时间。

例子:

使用我从http://www.dzone.com/snippets/java-read-file-string粘贴的方法,我正在将缓冲区读入字符串。我现在想删除所有空格。我的方法目前是这样的:

private String listRaw;

public boolean readList(String filePath) throws java.io.IOException {
    StringBuffer fileData = new StringBuffer(1024);
    BufferedReader reader = new BufferedReader(
            new FileReader(filePath));
    char[] buf = new char[1024];
    int numRead=0;
    while((numRead=reader.read(buf)) != -1){
        String readData = String.valueOf(buf, 0, numRead);
        fileData.append(readData);
        buf = new char[1024];
    }
    reader.close();
    listRaw = fileData.toString().replaceAll("\\s","");
    return true;
}

因此,我在将字符串完整存储到类变量时从字符串中删除了所有空格。

对我来说,这意味着更少的处理,但更多的内存使用。出于最佳实践原因,在将变量附加到变量时,我是否会更好地对其进行replaceAll()操作?使用更多处理但避免传递多余的空白。readDatafileData

我想这对像我正在处理的小文件这样的小文件影响不大,但如果它是一个 200MB 的日志文件呢?

它完全取决于案例,还是有一个我最好遵循的共识?


感谢大家的投入。我相信您已经帮助我将思维定势指向了编写 Java 的正确方向。

我已经更新了我的代码以考虑提出的观点。包括 Don Roby 的建议,即在某些时候,我可能想保留空格。希望现在情况更好!

private String listRaw;

public boolean readList(String filePath) throws java.io.IOException {
    StringBuilder fileData = new StringBuilder(51200);
    BufferedReader reader = new BufferedReader(new FileReader(filePath));
    char[] buf = new char[51200];
    boolean spaced = false;
    while(reader.read(buf) != -1){
        for(int i=0;i<buf.length;i++) {
            char c = buf[i];
            if (c != '\t' && c != '\r' && c != '\n') {
                if (c == ' ') {
                    if (spaced) {
                        continue;
                    }
                    spaced = true;
                } else {
                    spaced = false;
                }

                fileData.append(c);
            }
        }
    }
    reader.close();
    listRaw = fileData.toString().trim();
    return true;
}
4

3 回答 3

7

您最好在最后只创建和应用一次正则表达式替换。但你会获得更多

  • 以合理的大小初始化 StringBuilder
  • 避免在循环内创建字符串,并将读取的字符直接附加到 StringBuilder
  • 避免在每次迭代时实例化一个新的 char 缓冲区。

为避免不必要的长临时字符串创建,您可以逐个字符地读取字符,并且仅将字符附加到 StringBuilder (如果它不是空格)。最后, StringBuilder 将只包含好的字符,您不需要任何replaceAll()调用。

于 2012-07-28T17:20:31.290 回答
4

在这段代码中实际上有几个非常低效的地方,你必须先修复它们,然后再担心你提出的相对不那么重要的问题。

首先,不要buf在循环的每次迭代中创建一个新对象——使用同一个!这样做没有问题 - 新数据会覆盖旧数据,并且您可以节省对象分配(这是您可以执行的更昂贵的操作之一。)

其次,同样,不要创建一个String来调用append()——使用它的形式,append它需要一个char数组和一个偏移量(在这种情况下为 0)和长度(numRead在这种情况下)。同样,每次循环迭代都会少创建一个对象.

最后,要回答您实际提出的问题:在循环中执行此操作会在每次迭代中创建一个 String 对象,但是通过我们刚刚完成的调整,您每次迭代创建个对象 - 因此删除循环结束是明显的赢家!

于 2012-07-28T17:18:18.240 回答
1

根据您要进行的解析,您最好不要在单独的步骤中删除空格,而在解析期间忽略它们。

想要删除所有空格也是相当罕见的。您确定不想用单个空格替换多个空格吗?

于 2012-07-28T17:24:41.683 回答