2016-07-22 30 views
0
public String loadJSONFromAsset(String path) { 
    String json = null; 
    try { 
     InputStream is = this.getAssets().open(path); 
     int size = is.available(); 
     Log.d("Size: ", "" +size); 
     byte[] buffer = new byte[size]; 
     is.read(buffer); 
     is.close(); 
     json = new String(buffer, "UTF-8"); 
    } catch (IOException ex) { 
     ex.printStackTrace(); 
    } 
    return json; 
} 

Dies ist Code, der die Datei in JSON-Datendatei konvertieren. Es funktioniert wörtlich, es erstellt JSON-Datei, aber die Größe von "ist" ist appr. 8MBInputStream und OutOfMemory Fehler

D/Size:: 7827533 

und OutOfMemory Fehler tritt bei den meisten Geräten wie

java.lang.OutOfMemoryError 
at java.lang.String.<init>(String.java:255) 
at java.lang.String.<init>(String.java:228) 
at com.example.fkn.projecttr.List.loadJSONFromAsset(List.java:255) 

Wie kann ich damit umgehen? Wie kann es effizienter codiert werden? Es hat kein Problem mit der Laufzeit, aber es verbraucht zu viel Speicher auf dem Gerät. Wenn der Gerätespeicher keine Kapazität mehr hat, stürzt das Programm ab.

+0

Nicht in Bezug auf Ihr Problem, aber nicht aus einem 'catch' Block zurückkehren. – bradimus

+0

Danke für Ihren Rat! – user139518

+0

Dies geschieht möglicherweise nicht durch das, was Sie hier tun: Objekte, die mit anderem Code erstellt wurden, können den größten Teil Ihres verfügbaren Speichers belegen. –

Antwort

1

Ich bemerkte dies:

int size = is.available(); 

und dachte, es ein wenig seltsam war. Also ging ich und sah the JavaDoc for InputStream.available und das ist, was es zu sagen hatte:

Beachten Sie, dass während einige Implementierungen von Input die Gesamtzahl der Bytes im Stream zurück, viele nicht. Es ist niemals richtig, den Rückgabewert dieser Methode zu verwenden, um einen Puffer zuzuordnen, der alle Daten in diesem Stream enthalten soll.

So haben Sie eine von zwei Bedingungen:

  1. Ihre Dateigröße ist eigentlich 8MB.

    Wenn Sie wirklich so viel JSON haben, müssen Sie überdenken, was drin ist und wofür Sie es verwenden. Eine Option, die ich von vielen Entwicklern nicht verwende, ist JsonReader, mit der Sie den JSON analysieren können, ohne zuerst den gesamten Stream in den Speicher zu laden.

  2. Ihre Dateigröße ist viel kleiner als 8 MB

    einfach die Datei anders lesen, sehen How do I create a Java string from the contents of a file?

0

die Bytes halten komprimiert, ein GZipOutputStream auf einem ByteArrayOutputStream (oder ein gzip komprimiert Vermögenswert).

Dann immer das, für die Ausgabe, Analyse oder was auch immer, mit einem GZipInputStream verarbeiten.

Das wäre mindestens ein Faktor 20 sicher (10 Komprimierung, ~ 3 mal weniger Overhead).

Für eine weniger invasive Änderung (und mehr Speicherverbrauch): jetzt gibt es eine 8 MB Byte-Array und eine 16 MB String. Die Zeichenfolge könnte sofort zu einem DOM, also JSON, analysiert werden. Verwerfen des Whitespace und gleiche String-Werte, die einer String-Instanz zugeordnet sind (z. B. durch eine Map<String, String> idmap). Es kommt darauf an, ob sich die Daten stark wiederholen.