【问题标题】:Android Reading a large text efficiently in JavaAndroid 在 Java 中高效读取大文本
【发布时间】:2019-10-25 19:04:56
【问题描述】:

我的代码太慢了

如何高效地编写代码?目前代码需要几分钟才能读取文件,这太长了。这可以更快地完成吗?没有堆栈跟踪,因为它可以工作,但是太慢了。 谢谢!

问题代码:

private void list(){
        String strLine2="";
        wwwdf2 = new StringBuffer();

        InputStream fis2 = this.getResources().openRawResource(R.raw.list);
        BufferedReader br2 = new BufferedReader(new InputStreamReader(fis2));
        if(fis2 != null) {
            try {
                LineNumberReader lnr = new LineNumberReader(br2);
                String linenumber = String.valueOf(lnr);
                int i=0;
                while (i!=1) {
                    strLine2 = br2.readLine();
                    wwwdf2.append(strLine2 + "\n");
                    String contains = String.valueOf(wwwdf2);
                    if(contains.contains("itisdonecomplet")){
                       i++;
                    }
                }
              //  Toast.makeText(getApplicationContext(), strLine2, Toast.LENGTH_LONG).show();
                Toast.makeText(getApplicationContext(), wwwdf2, Toast.LENGTH_LONG).show();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
    }

【问题讨论】:

  • if(contains.contains("itisdonecomplet")) 更好:if(strLine2.contains("itisdonecomplet"))。但是你为什么需要那个?那是 ; 最后一行吗?然后删除该检查,因为最后一行 readLine() 将返回 null,
  • @blackapps 有问题。 Readline() 甚至在文件红色完成之前返回 null。
  • 这难以置信。没见过这样的。

标签: java android file android-studio bufferedreader


【解决方案1】:
  1. 使用StringBuilder 而不是StringBuffer

    StringBuffer 已同步,您不需要它。

  2. 不要使用String.valueOf,它构建一个字符串,使用StringBuffer/Builder 否定值。您正在从整个缓冲区构建一个字符串,检查它,丢弃该字符串,然后再次构建几乎相同的字符串。

    改用if (wwwdf2.indexOf("itisdonecomplet") >= 0),这样可以避免创建字符串。

    但这仍然会相当慢,因为虽然您不会构造字符串并搜索所有内容,但您仍在进行搜索。

    您可以通过仅搜索字符串的末尾来加快速度。例如,您可以使用wwwdf2.indexOf("itisdonecomplet", Math.max(0, wwwdf2.length() - strLine2.length() - "itisdonecomplet".length()))

    尽管正如 blackapps 在评论中指出的那样,您可以简单地检查 strLine2 是否包含该字符串。

  3. 不要在对append 的调用中使用字符串连接:进行两个单独的调用。

    wwwdf2.append(strLine2);
    wwwdf2.append("\n");
    
  4. 您不检查是否到达文件末尾。检查strLine2是否为空,如果是则中断循环。

【讨论】:

  • 感谢您的回答。不幸的是,代码并不是真的更快。读取文件仍然需要几分钟。文本文件有超过 100000 行。
【解决方案2】:

我的新创建代码:(我的测试设备是三星 S8)

 private void list(){
            String strLine2="";
            wwwdf2 = new StringBuilder();

            InputStream fis2 = this.getResources().openRawResource(R.raw.list);
            BufferedReader br2 = new BufferedReader(new InputStreamReader(fis2));
            if(fis2 != null) {
                try {
                    LineNumberReader lnr = new LineNumberReader(br2);
                    String linenumber = String.valueOf(lnr);
    int i=0;
                    while (i!=1) {
                        strLine2 = br2.readLine();
                        wwwdf2.append(strLine2);
                        wwwdf2.append("\n");
                        if (wwwdf2.indexOf("itisdonecomplet") >= 0){
                            i++;
                        }


                    }
                  //  Toast.makeText(getApplicationContext(), strLine2, Toast.LENGTH_LONG).show();
                    Toast.makeText(getApplicationContext(), wwwdf2, Toast.LENGTH_LONG).show();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

【讨论】:

  • 不要使用 indexOf()。每次它都必须再次遍历所有行。
  • 我创建了一个包含 100000 行的 4MB 文件。在一台设备上读取时间为 134 毫秒,在小型旧设备上读取时间为 650 毫秒。如果我添加一个 indexOf() 检查它需要几分钟。带有if ( line.contains("itisdonecomplet") 行的代码将花费 156 和 700 毫秒。循环是while ((line = br.readLine()) != null)。仅在读取 100000 行后为空。
  • @blackapps 我相信indexOf(单个参数)比包含要花费更长的时间,并且在这种特定情况下(每次添加换行符并搜索字符串)没有换行符)你会得到strLine2.contains的正确答案。不过,您仍然可以使用 2-arg 版本的 indexOf 来做到这一点,而且速度会很快。
猜你喜欢
  • 2017-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多