out of memory exception

  • Antworten:4
Michael H
  • Forum-Beiträge: 127

10.10.2012, 16:45:40 via Website

Habe folgendes Problem:
Ich will über einen Socket Files senden. Dabei sollte eine Limite von 10MB/File definiert werden. Wenn ich jetzt aber ein File welches über 4 MB gross ist, byteweise über den Socket schieben will, bekomme ich eine out-of-memory exception. Nun wie würdet ihr mit dem ganzen umgehen? Ich meine z.B. WhattsApp kann ja auch grössere Files schieben...

Hier noch mein Codeschnipsel

1File file = fileHandler.getFileFromInternalStorage(attachment.getNameAnhang()); // File von InternalStorage auslesen
2byte[] fileByteArray = fileHandler.getFileAsByteArray(file); // File in byte-Array wandeln
3this.addByteArray(fileByteArray); // File senden

Das ist die addByteArray-Methode:

[code]
public void addByteArray(byte[] buffer) {
for(int i=0;i<buffer.length;i++) {
attachment.add(buffer[i]);
}
}
[/code]

Antworten
Rafael K.
  • Forum-Beiträge: 2.359

10.10.2012, 22:30:41 via Website

Das Problem ist, dass du den gesamten Inhalt zuerst in den Speicher liest.
Das ist garnicht nötig, denn du kannst doch einfach die Daten aus einem Inputstream in einen Outputstream kopieren.
Entweder nimmst du dazu einen kleinen byte[] als Puffer, oder z.B. die IOUtils von Apache, die spezielle Methoden zum kopieren von Streams anbieten.

Antworten
Michael H
  • Forum-Beiträge: 127

11.10.2012, 15:42:53 via Website

Ach so ist das! :-) Vielen Dank...
Nun habe ich das ganz abgeändert. So dass ich das File nicht mehr in byte[] abfülle. Jetzt kommt das File, welches ca 5MB gross ist ganz gut durch die Socketverbindung. Aufgefallen ist mir nur, dass im LogCat immer Speicher vom GarbageCollector frei gemacht wird:
1GC_CONCURRENT freed 1558K, 21% free 11420K/14279K, paused 1ms+2ms
Ist das normal oder habe ich da noch irgend ein Speicherleck oder so?

Hier mein Code:

1FileHandler fileHandler = new FileHandler(this.context);
2File file = fileHandler.getFileFromInternalStorage(attachment.getNameAnhang());
3try {
4 FileInputStream fisFile = new FileInputStream(file);
5 int readByte = fisFile.read();
6 while(readByte > -1) {
7 this.addByte((byte) readByte);
8 if(this.getBuffer().size() > 99) {
9 this.sendBuffer();
10 this.bufferClear();
11 }
12 readByte = fisFile.read();
13 }
14 fisFile.close();
15} catch (FileNotFoundException e) {
16 // do something
17} catch (IOException e) {
18 // do something
19}

Ich fülle die bytes, welche ich vom FileInputStream lese in einen byte[] (Buffer). Wenn dieser 100 Bytes enthält wird dieser über die Socketverbindung gehauen. Anschliessend wird der Buffer wieder geleert und es folgen die nächsten 100 bytes....

Ich wäre froh um irgendwelche Tipps oder Anmerkungen.

Gruss Michi

Antworten
Rafael K.
  • Forum-Beiträge: 2.359

11.10.2012, 15:45:33 via Website

Das ist schonmal besser.
Die bytes einzeln zu lesen ist jedoch extrem inperformant.

Man macht das idR über einen Puffer, nach dem folgenden Schema:

1int count;
2byte[] buffer = new byte[8192];
3while ((count = in.read(buffer)) > 0)
4 out.write(buffer, 0, count);

Kopiert von: http://stackoverflow.com/questions/3554259/copy-a-stream-via-byte

— geändert am 11.10.2012, 15:47:26

Antworten
Michael H
  • Forum-Beiträge: 127

11.10.2012, 16:26:49 via Website

Ah, sehr schön!
So funktionierts logischerweise auch schneller! Vielen Dank, +1 für dich :)

Antworten