Struktur aus Datei lesen [C++] -> [Java]

sisela

Erfahrenes Mitglied
Hallo Leute,
beschäftige mich erst seit kurzem mit Java und habe nun folgendes Problem!

folgendes mache ich in C++.
Code:
file.Read(&Struktur, sizeof(Struktur));
Und mit dieser einfachen Zeile habe ich mein komplette Struktur, bestehend aus mehreren int´s und char Arrays gelesen.

Das versuche ich nun auch in Java. Erstes Problem: Es gibt keine Strukturen! OK, man nehme eine Klasse und definiert dort alle Variablen. Nun kann ich aber nicht
sizeof() machen zumal es das ja in Java nicht gibt.

Ich habe nun folgendes:
Code:
JFileChooser fc = new JFileChooser();
fc.showOpenDialog(MyApp.this);
File file = fc.getSelectedFile();
try 
{
  FileInputStream in = new FileInputStream(file);
  MyStrukturClass struktur = new MyStrukturClass();
                  
  byte[] buf = new byte[4096];
  int len;
  while ((len = in.read(buf)) > 0) 
  {
    // hier was Struktur beschreiben
  }
  in.close();
}
catch (IOException ec) 
{
  System.err.println(ec.toString());
}

Wie bekomme ich jetzt am komfortabelsten meine Variablen der Strukturklasse beschrieben. Ich muss doch nicht etwa jedesmal, je nach Datentyp eine bestimmte Anzahl an Bytes lesen :rolleyes:

Vielleicht kann mir ja jemand von Euch einen Tipp geben (vielleicht mit Beispiel). Nehmen wir an ich will eine Struktur{int alter, char Info[30], usw.} auslesen.
mfg
 
Hallo!

In Java muss man sich um solche Dinge (im Normalfall) nicht mehr kümmern, dafür gibts Serialisierung:

Beispiel:

Code:
package de.tutorials;

import java.io.Serializable;

class Struct implements Serializable {
	public int x;

	public int y;

	public char c;

	public boolean b = false;
}

Code:
package de.tutorials;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Test06 {

	public static void main(String[] args) {
		new Test06().doIt();
	}

	private void doIt() {
		Struct s = new Struct();
		s.b = true;
		s.x = 2313;
		s.y = 34231414;
		s.c = 'A';
		
		try {
			ObjectOutputStream oos = new ObjectOutputStream(
					new FileOutputStream("c:/out.ser"));
			oos.writeObject(s);
			oos.flush();
			oos.close();

			Struct s0 = null;

			ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
					"c:/out.ser"));

			s0 = (Struct) ois.readObject();
			System.out.println(s0.b);
			System.out.println(s0.x);
			System.out.println(s0.y);
			System.out.println(s0.c);

			ois.close();

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}

	}
}

Gruß Tom
 
Hi Tom,

man ist ja gar nicht mal so schlecht dieses Java, Steige gerade von C++ in die Java Programmiertechnik ein und habe mir den Umstieg leichter vorgestellt.

Auf jeden Fall danke nochmal, denn das macht die Sache doch wesentlich einfacher.

:) Gruß Christian
 
Hallo Tom,

ich glaube ich habe mich zu früh gefreut! Kann es sein, dass ich nur so lesen kann, wenn ich es auch mittels eines Streams geschrieben habe? Denn ich habe die Datei, fertig dazuliegen (wird von einem anderen System geliefert) und schreibe daher nicht mit
Code:
ObjectOutputStream oos = new ObjectOutputStream(
  new FileOutputStream("c:/out.ser"));
  oos.writeObject(s);
  oos.flush();
  oos.close();
Denn nun bekomme ich nämlich beim lesen aus der vorhandenen Datei eine Exception "invalid stream header". Kannst du dir das erklären und hättest du einen anderen Vorschlag?

Hier mein Code:
Code:
if (e.getActionCommand() == "File open")
            {
                JFileChooser fc = new JFileChooser();
                fc.showOpenDialog(MyApp.this);
                File file = fc.getSelectedFile();
                try 
                {
                    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
                    init = (InitStruct) ois.readObject();
                    
                    System.out.println("Info: "+ init.lpszInfo.toString());
                    System.out.println("Flags: "+init.flags);
                    System.out.println("AppType: "+init.nAppTyp);
                    System.out.println("ProtoType: "+init.nPrototyp);
                    System.out.println("Size: "+init.nSize);
                    System.out.println("Version: "+init.nVersion);
                    
                    ois.close();
                
                } 
                catch (FileNotFoundException event) 
                {
                    event.printStackTrace();
        	} 
                catch (IOException event) 
                {
                    event.printStackTrace();
        	} 
                catch (ClassNotFoundException event) 
                {
                    event.printStackTrace();
        	}
            
            }
Code:
class InitStruct implements Serializable
{
    public long 	nSize;
    public int 	nVersion;
    public int 	nPrototyp;
    public int 	nAppTyp;
    public char 	lpszInfo[];
    public long 	flags;
}
Gruß Christian
 
sisela hat gesagt.:
Hi Tom,
man ist ja gar nicht mal so schlecht dieses Java, Steige gerade von C++ in die Java Programmiertechnik ein und habe mir den Umstieg leichter vorgestellt.

Gruß Christian

Java ist wesentlich einfacher als C++. Ich habe erst Java gelernt und wenn ich mich nun mit C++ beschäftigen muss, kriege ich die Krise, wie kompliziert und umständlich alles in der C++ Welt ist. Von der API ganz zu schweigen...
3 Tips:
1. Schau in die Sun Tutorials
2. Schau in die API
3. Verschiedene Bücher zum Nachschlagen gibt es auch als Online-Versionen, z.B. die Java-Insel oder Handbuch der Java-Programmierung

Zu Deiner Datei: Nimm mal einen BufferedReader und/oder 1-3. ;)
 
Hi @snape!

Danke erst einmal. Sag mal gibt es in Java denn nichts wie sizeof()? Denn wenn ich den BufferedReader nehme, muss ich ja immer angeben wieviele Bytes ich lesen will. Wenn sich nun aber meine Datenstruktur ändert, möchte ich ja nicht die tausend stellen im Programm ändern. In C gibt es sowas wie sizeof(variable) und dann würde ich bei einem WORD variable halt ein WORD lesen und bei DWORD variable ein DWORD.
Ich hoffe du verstehst was ich meine, ich will halt nicht sowas wie
Code:
raFile.read(byte[]b, raFile.getFilePointer(), 8);
Die 8 muss halt irgendwie weg

mfg
 
Du musst die Größe nicht wissen. Schau mal z.B. hier:

Code:
	public static void main(String[] args)
	{
		try
		{
			FileReader fr = new FileReader("C:/boot.ini");
			BufferedReader br = new BufferedReader(fr);
			String line = null;
			Vector vector = new Vector();

			//So lange Zeilen aus der Datei einlesen bis
			//End Of File (EOF) --> br.readLine() => null 
			//gelesene Zeilen in den Vector schieben
			while ((line = br.readLine()) != null)
			{
				vector.add(line);
			}

			//Anzahl der Elemente im Vector
			int size = vector.size();
			//Zeilen ausgeben
			for (int i = 0; i < size; i++)
			{
				System.out.println(vector.get(i));
			}

		}
		catch (FileNotFoundException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
 
Sicherlich wäre es möglich die ganze Datei einzulesen aber genau das will ich nicht, denn die ist riesig. In meiner Datei stehen lauter Strukturen (leider kein Java Stream). Also sagen wir mal meine erste Variable der Struktur ist ein Integer. Nun möchte ich nur (!) diese Variable also sizeof(int) gerne auslesen, was genau 4Bytes entsprechen müsste. Also es bringt mir nichts die komplette Datei einzulesen, noch mit Streams aus der Datei heraus lesen, weil die Daten nicht mittels Java Streams reingeschrieben werden.

Wie gesagt in C ist das eine Zeile:
Code:
file.Read(&var, sizeof(var));

Im Moment versuche ich mich an der RandomAccessFile und lese halt immer genau die Größe eines bestimmten Datentyps.
Code:
init.nVersion = raFile.readShort();

Aber der Code wird dann so lang, das muss doch einfacher gehen, da ich ja jeden einzelnen Datentyp extra einlesen muss.

mfg
 
Hallo!

Die Serialisierung in Java macht noch ein wneig mehr als nur die Werte der jeweiligen Membervariablen (die sich Externalisieren lassen) ein einen Stream und dann auf die Platte zu hauen. Zusätzlich werden nämlich noch einige Verwaltungsinformationen zu der Klasse und den darin enthaltenen Daten abgelegt. Wie etwa Klassenname, Variablentyp etc. Deshalb kannst du mit dem Serialisierungsmechanismus nur schwer Daten die aus anderen nicht Java Anwendungen heraus erstellt wurden lesen (Du müsstest eben diese zusätzlichen Verwaltungsinformationen noch hinzufügen und so gestallten, dass Java was damit anfangen kann, was eigentlich so gut wie unmöglich ...oder sagen wir mal schwer möglich ist.)

Btw. lerne ich auch gerade C++ und muss sagen, dass mir meine Java Erfahrung dort extrem Hilft. Java hat nun mal sehr viele Konzepte von C++ übernommen /bzw. ähnlich realisiert was einem den Einstieg IMHO recht einfach macht.

Gruß Tom
 
Thomas Darimont hat gesagt.:
Hallo!
Btw. lerne ich auch gerade C++ und muss sagen, dass mir meine Java Erfahrung dort extrem Hilft. Java hat nun mal sehr viele Konzepte von C++ übernommen /bzw. ähnlich realisiert was einem den Einstieg IMHO recht einfach macht.
Gruß Tom

Dann bin ich entweder zu alt, zu doof oder mir fehlt einfach ein (guter) Tutor. Der ganze Krempel mit * und & will einfach nicht in meinen Kopf, wann und warum die zu benutzen sind.
Dazu geben mir die schlechte API und die kryptische Syntax den Rest. :(
 
Zurück