Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Mär 28, 2024 15:12

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 25 Beiträge ]  Gehe zu Seite Vorherige  1, 2
Autor Nachricht
BeitragVerfasst: Mi Jun 10, 2015 07:49 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Nov 08, 2010 18:41
Beiträge: 769
Programmiersprache: Gestern
mathias hat geschrieben:
Oder kann ich wenigsten irgendwie die Grösse der Datei ermitteln ?
Bei einer Datei eines öffentlichen Ornder kann ich die Grösse mit folgendem Code ermitteln.
Code:
  1.             File file = new File("test.txt");
  2.             System.out.println(file.length());

Da sich die Daten aber im Assets befinden, geht dies leider nicht.


Genau aber egal ob offentliche Datei, Sandbox, Download usw., du kriegst hierbei immer direkt, oder eine Ableitung von, InputStream. Diesen
kannst du dann ganz leicht in ein entsprechendes Format umwandeln.

Code:
  1.  
  2. public byte[] readBytes(InputStream inputStream) throws IOException {
  3.   int bufferSize = 1024;
  4.   byte[] buffer = new byte[bufferSize];
  5.   int len = 0;
  6.   while ((len = inputStream.read(buffer)) != -1) {
  7.     byteBuffer.write(buffer, 0, len);
  8.   }
  9.   return byteBuffer.toByteArray();
  10. }
  11.  
  12. public float[] convertFloats(byte[] arr) {
  13.   ByteBuffer bs =ByteBuffer.wrap(arr)
  14.   FloatBuffer fs = bs.asFloatBuffer().
  15.   float[] cfs = new float[fs.array().length]; //.array ist final also eine kopie erzeugen sonst knallt es
  16.   System.arraycopy(fs.array(),0,cfs,0,cfs.length);
  17.   return cfs;
  18. }
  19.  


Stell dir Streams einfach als bessere Form von Arrays vor.
- Du kannst alles moegliche reinpacken.
- Sie funktionieren Asynchron.
- Du brauchst kein Resize.
- Du kannst Call-By-Need Pattern benutzen.
- uvm..

_________________
Meine Homepage


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Jun 10, 2015 17:11 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Ich habe meinen Code durch deinen ersetzt und kleinere Änderungen vorgenommen.
Code:
  1.     static public byte[] readByteArrayBin(final String file) {
  2.         byte[] buffer = null;
  3.         try {
  4.             InputStream inputStream = MyGLSurfaceView.mContext.getAssets().open(file);
  5.  
  6.             ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
  7.             buffer = new byte[1024];
  8.             int len = 0;
  9.             while ((len = inputStream.read(buffer)) != -1) {
  10.                 byteBuffer.write(buffer, 0, len);
  11.             }
  12.             inputStream.close();
  13.             buffer = byteBuffer.toByteArray();
  14.         } catch (IOException ioe) {
  15.             Log.d("Fehler", "Datei IO Fehler : " + ioe);
  16.         }
  17.         return buffer;
  18.     }


Der Umweg über die Float-Array kann ich mir sparen, ich kann direkt die Byte-Array verwende.
So nebenbei entfällt dadurch das Big/Little-Endian Problem zwischen Java und Lazarus.

Vielleicht könnte man den InputSteam direkt in den ByteBuffer schreiben ?

Code:
  1.     public void loadFromFile(final String file) {
  2.         byte[] vectoren = MyFileUtil.readByteArrayBin(file);
  3.  
  4.         ByteBuffer bb = ByteBuffer.allocateDirect(vectoren.length);
  5.         bb.order(ByteOrder.nativeOrder());
  6.         bb.put(vectoren);
  7.         bb.position(0);
  8.  
  9.         vectorenSize = vectoren.length / 4;
  10.  
  11.         GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVBOid[0]);
  12.         GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vectoren.length, bb, GLES20.GL_STATIC_DRAW);
  13.     }


PS: Bei deinem Floatkonverter sind zwei ";" verloren gegangen.

_________________
OpenGL


Zuletzt geändert von mathias am Do Jun 11, 2015 21:56, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Jun 10, 2015 19:12 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Nov 08, 2010 18:41
Beiträge: 769
Programmiersprache: Gestern
Hehe ja sorry, habs nicht getestet :)

Und ja theoretisch kannst du es direkt in den ByteBuffer reinschreiben. Auf den ersten Blick würde ich aber behaupten das du damit
der Runtime etwas mehr Arbeit zumutest. Ich weiß ja nicht wie gut die aktuelle IDE ist, aber vielleicht gibt es ja mittlerweile nen brauchbaren
Profiler (gibt dir Ausführungszeit, Ram, CPU-Last usw. für die einzelnen Methoden). Damit könntest du nachschauen welche Variante für dich besser ist.

Du könntest natürlich auch Array mit einer bestimmten Max-Größe aufsetzen. Also zum Beispiel:
Solange die Datei kleiner als 2 mb dann schreibs direkt rein, wenn nicht dann nutz den Buffer. Oder so.

Ansonsten:
Solange es keine Probleme macht, einfach so lassen. Optimieren kann man immer noch später :)

_________________
Meine Homepage


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Do Jun 11, 2015 22:10 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Ich habe unterdessen mit Lazarus und TStreams experimentiert.
So wie es aussieht, sind Streams eine moderne Art um Daten zu speichern und zu lesen.

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Fr Jun 12, 2015 19:54 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Lazarusseite habe ich meine Speicherroutine von "file of" auf "TStream" abgeändert.
Als positiver Nebeneffekt, ist TStream zig mal schneller.

Code:
  1. // alt
  2. procedure TJavaVector.WriteVector(const Vector: TFace3DArray; Name: string);
  3. var
  4.   i, j, k: integer;
  5.   f: file of single;
  6.   Datei: string;
  7.  
  8. begin
  9.   Datei := JavaPfad + '\assets' + Name + '.bin';
  10.  
  11.   AssignFile(f, Datei);
  12.   ReWrite(f);
  13.  
  14.   for i := 0 to Length(Vector) - 1 do begin
  15.     for j := 0 to 2 do begin
  16.       for k := 0 to 2 do begin
  17.         Write(f, Vector[i, j, k]);
  18.       end;
  19.     end;
  20.   end;
  21.   CloseFile(f);
  22. end;
  23.  
  24. // neu
  25. procedure TJavaVector.WriteVector(const FaceArray: TFace3DArray; Name: string);
  26. var
  27.   Datei: string;
  28.   stream: TFileStream;
  29. begin
  30.   Datei := JavaPfad + '\assets' + Name + '.bin';
  31.   stream := TFileStream.Create(Datei, fmCreate);
  32.   try
  33.     stream.Write(Pointer(FaceArray)^, Length(FaceArray) * SizeOf(Tmat3x3));
  34.   finally
  35.     stream.Free;
  36.   end;
  37. end;    


Würde es etwas bringen, wen ich als erster Stelle noch die Längenangabe der Array speichern würde, das ich in Android nicht bis EOF auslesen müsste ?

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Jun 15, 2015 17:27 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Wie gefährlich ist dies, kann diese Methode bei zu grossen Dateien zu Problemen führen ?
Die ersten 4 Bytes des Streams gibt die Länge der Byte-Array an.

Die Idee dahinter, das ich Position, Normal und Color in eine Datei speichern kann.
Color ist eine einfache vec4 Variable.

Code:
  1.     public static int readIntFrom(InputStream in) throws IOException {
  2.         int ch1 = in.read();
  3.         int ch2 = in.read();
  4.         int ch3 = in.read();
  5.         int ch4 = in.read();
  6.         return ((ch1 << 0) + (ch2 << 8) + (ch3 << 16) + (ch4 << 24)); // Vertauscht!
  7.     }
  8.  
  9.     static public byte[] readByteArrayBin(final String file) {
  10.         byte[] buffer = null;
  11.         try {
  12.             InputStream inputStream = MyGLSurfaceView.mContext.getAssets().open(file);
  13.             int len = readIntFrom(inputStream);
  14.            
  15.             buffer = new byte[len];
  16.             inputStream.read(buffer);
  17.             inputStream.close();
  18.         } catch (IOException ioe) {
  19.             Log.d("Fehler", "Datei IO Fehler : " + ioe);
  20.         }
  21.         return buffer;
  22.     }

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Jun 15, 2015 21:46 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Nov 08, 2010 18:41
Beiträge: 769
Programmiersprache: Gestern
Gefährlich ist es nicht wirklich. Du musst halt nur im Hinterkopf behalten wie viel Speicher du deiner Zielgruppe zumuten willst. Wenn du allerdings
wirklich große Datenmengen hast, solltest du dir ein Format überlegen mit dem du die Datei aufteilst. Dann kannst du ganz leicht Stück für Stück nachladen.

Du kannst dir ja mal solche Sachen wie Rx oder Linq aus der .NET Welt anschauen. Das sind ganz einfache Systeme die dir erlauben deine
eigentliche Arbeit so zu Wrappen das Sie nur ausgeführt wenn du sie auch wirklich brauchst. Und Obendrein kann man solche Systeme ganz
leicht so umbauen das im Hintergrund vorgeladen wird und all solche Sachen :)

Wie gesagt, die sind sehr einfach, es sollte also kein Problem werden diese Sachen zu portieren.

_________________
Meine Homepage


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mo Jun 15, 2015 22:22 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Zitat:
Gefährlich ist es nicht wirklich. Du musst halt nur im Hinterkopf behalten wie viel Speicher du deiner Zielgruppe zumuten willst.


Es liest nur die Vertex-Daten aus, welche ich dann mit
Code:
  1. GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vectoren.length, bb, GLES20.GL_STATIC_DRAW);

der GPU übergebe.
Ich hoffe das ich damit nicht die Zielgruppe überfordere. :wink:
Die Daten sind unter 1 MByte.

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Jun 16, 2015 07:34 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Nov 08, 2010 18:41
Beiträge: 769
Programmiersprache: Gestern
ja das sollte absolut gar kein Problem dann sein. Bei einer Begleitapp fuer einen Kunden hauen wir ein paar hundert MB durch :)

_________________
Meine Homepage


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Di Jun 16, 2015 16:48 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Mai 31, 2002 19:41
Beiträge: 1276
Wohnort: Bäretswil (Schweiz)
Programmiersprache: Pascal
Ich habe gerade den Quellen von Java angeguckt:
Code:
  1.     public int read(byte[] buffer) throws IOException {
  2.         return read(buffer, 0, buffer.length);
  3.     }
  4.  
  5.     public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
  6.         Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
  7.         for (int i = 0; i < byteCount; ++i) {  // Die for-to Schleife
  8.             int c;
  9.             try {
  10.                 if ((c = read()) == -1) {
  11.                     return i == 0 ? -1 : i;
  12.                 }
  13.             } catch (IOException e) {
  14.                 if (i != 0) {
  15.                     return i;
  16.                 }
  17.                 throw e;
  18.             }
  19.             buffer[byteOffset + i] = (byte) c;
  20.         }
  21.         return byteCount;
  22.     }


Dort wird die Byte-Array mit einer banalen for-to-Schleife eingelesen.

Somit ist es sogar effizienter, wen ich meine Daten selbst direkt mit eine for-to-Schleife einlese.
Code:
  1.             buffer = new byte[len];
  2.             for (int i = 0; i < len; i++) {
  3.                 buffer[i] = (byte) inputStream.read();
  4.             }

Somit kann ich die if-Abfragen umgehen.

_________________
OpenGL


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 25 Beiträge ]  Gehe zu Seite Vorherige  1, 2
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 19 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.098s | 17 Queries | GZIP : On ]