简体   繁体   English

读取内部存储文件在Android中花费太多时间

[英]Reading internal storage file is taking too much time in Android

I have a large JSON data around 20 MB (I create this data using JSON.stringify from JavaScript code).我有一个大约 20 MB 的大型 JSON 数据(我使用 JavaScript 代码中的JSON.stringify创建此数据)。 I 'm writing this JSON data to an internal storage file on Android Device and reading it later.我正在将此 JSON 数据写入 Android 设备上的内部存储文件并稍后读取。 So When I read the file it's taking too much time, I don't know whether its reading or not.所以当我阅读文件时,它花费了太多时间,我不知道它是否正在阅读。 One more thing I need to Read in the Main thread only.我只需要在主线程中阅读的另一件事。

The below code works fine if I pass data value "Hello World" in WriteFile method, But it fails with the large JSON如果我在WriteFile方法中传递数据值“Hello World”,下面的代码工作正常,但它因大 JSON 而失败

public String ReadFile()
{
    StringBuffer text = new StringBuffer();
    String FILE_NAME = "file.txt";
    try {
        BufferedReader bReader = new BufferedReader(new InputStreamReader(openFileInput(FILE_NAME)));
        String line;
        int count = 0;
        while ((line = bReader.readLine()) != null) {
            text.append(line + "\n");
            alert("Reading File: " + ++count);
        }

    } 
    catch (Exception e) {
        alert(e.toString());
    }

    return text.toString();
}

public String WriteFile(String data)
{
    String FILE_NAME = "file.txt";
    String result = "";
  try {
      FileOutputStream fos = openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
      fos.write(data.toString().getBytes());
      result = "Success";
      fos.close();
    }
    catch (Exception e) {
        e.printStackTrace();
        result="Error";
   }

    return result;
}

I have added one alert in while loop also, but I cannot see any alert message.我也在 while loop添加了一个警报,但我看不到任何警报消息。 I have not seen even the Exception message also.我什至还没有看到Exception消息。

so there can be two problems.所以可能有两个问题。

  1. There is something wrong in writing to file (But I don't know how to verify this? because I don't think there is any way to view internal storage file).写入文件有问题(但我不知道如何验证?因为我认为没有任何方法可以查看内部存储文件)。

  2. Something wrong in my reading code.我的阅读代码有问题。

Update1:更新1:

If let's say I cannot read so large file in Java native code, then Is there any way to read an internal storage Android file from WebView JavaScript code?如果假设我无法在 Java 本机代码中读取如此大的文件,那么有什么方法可以从 WebView JavaScript 代码中读取内部存储的 Android 文件?

============================================================================ ================================================== ==========================

Application Requirement申请要求

I have an Android application, In which I have a WebView.我有一个 Android 应用程序,其中有一个 WebView。 I have copied the full javascript code (js and HTML files) to assets folder of the app.我已将完整的 javascript 代码(js 和 HTML 文件)复制到应用程序的资产文件夹中。 I'm writing to file from java native code and reading from java native code.我正在从 java 本机代码写入文件并从 java 本机代码读取。 I am getting all data from the server on app launch.我在应用程序启动时从服务器获取所有数据。 My client has a very slow internet connection and its disconnected many times.我的客户的互联网连接速度非常慢,并且多次断开连接。 So they want this app to be run in offline mode.所以他们希望这个应用程序在离线模式下运行。 Means app will get all the data at launch and We will store it somewhere and then read it throughout the app.意味着应用程序将在启动时获取所有数据,我们将其存储在某处,然后在整个应用程序中读取它。 If a user launches the app again it will get the old existing data.如果用户再次启动应用程序,它将获得旧的现有数据。 Actually, this data is very big so I'm storing it to the internal storage file.实际上,这个数据非常大,所以我将它存储到内部存储文件中。

First of all, the only way to be really sure why your code is taking a long time is to profile it.首先,真正确定为什么您的代码需要很长时间的唯一方法是对其进行分析。 We can't do that for you.我们不能为你这样做。

But here are some performance tips relevant to your code:但这里有一些与您的代码相关的性能提示:

  1. Don't read the entire 20MB JSON file into the Java heap / RAM memory unless you really need to do it.不要将整个 20MB JSON 文件读入 Java 堆/RAM 内存,除非您确实需要这样做。 (I am finding it difficult to understand why you are doing this. For example, a typical JSON parser will happily 1 read input directly from a file. Or if you are reading this so that you can send this to a client on the other end of an HTTP connection, you should be able to stream the data.) (我发现很难理解您为什么要这样做。例如,典型的 JSON 解析器会很高兴地1直接从文件中读取输入。或者,如果您正在阅读此内容,以便将其发送给另一端的客户端的 HTTP 连接,您应该能够流式传输数据。)

  2. Reading a file a line at a time and then stitching the lines back together is unnecessary.一次读取一个文件,然后将这些行重新拼接在一起是不必要的。 It generates unnecessary garbage.它会产生不必要的垃圾。 Extra garbage means more work for the GC, which slows you down.额外的垃圾意味着 GC 需要做更多的工作,这会减慢您的速度。 If the lines are long, you have the added performance "hit" of using a internal StringBuilder to build each line.如果行很长,则使用内部StringBuilder构建每行会增加性能“命中”。

    Reading to a recycled char[] , then appending the char[] content to the StringBuilder will be faster than appending lines.读取到回收的char[] ,然后将char[]内容附加到StringBuilder将比附加行更快。

  3. Your StringBuilder will repeatedly "grow" its backing character array to accommodate the characters as you append them.您的StringBuilder将反复“增长”其支持字符数组,以在您追加字符时容纳这些字符。 This generates garbage and leads to unnecessary copying.这会产生垃圾并导致不必要的复制。 (Implementations typically "grow" the array exponentially to avoid O(N^2) behavior. However the expansions still affect performance, and can result in up to 3 times the peak memory usage than is actually required.) (实现通常以指数方式“增长”数组以避免O(N^2)行为。但是扩展仍然会影响性能,并且可能导致峰值内存使用量是实际需要的 3 倍。)

    One way to avoid this is to get an initial estimate of the number of characters you are going to add and set the StringBuilder "capacity" accordingly.避免这种情况的一种方法是对要添加的字符数进行初步估计,并相应地设置StringBuilder “容量”。 You may be able to estimate the number of characters from the file size.您或许可以根据文件大小估计字符数。 (It depends on the encoding.) (这取决于编码。)

  4. Look for a way to do it using existing standard Java libraries;寻找使用现有标准 Java 库的方法; eg Files.copy and ByteArrayOutputStream , or Files.readAllBytesFiles.copyByteArrayOutputStream ,或Files.readAllBytes

  5. Look for an existing 3rd-party library method;寻找现有的第 3 方库方法; eg Apache Commons IO has an IOUtils.toString(Reader) method.例如,Apache Commons IO 有一个IOUtils.toString(Reader)方法。 The chances are that they will have spent a lot of time figuring out how to do this efficiently .很有可能他们会花费大量时间来弄清楚如何有效地做到这一点。 Reusing a well engineered, well maintained library is likely to saves you time.重用设计良好、维护良好的库可能会节省您的时间。

  6. Don't put a trace print (I assume that is what alert is ...) in the middle of a loop that could be called millions of times.不要在可以被调用数百万次的循环中间放置跟踪打印(我认为这就是alert ......)。 (Duh!) (呸!)


1 - Parser are cheerful once you get to know them :-) 1 - 一旦你了解他们,解析器就会很高兴:-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM