Moin moin,
Ich versuche, per TCP/IP-Verbindung Daten von einem C++-Programm in ein
Java-Programm zu schaufeln. Übertragen wird ein Array aus Short-Werten,
die auf meinem System sowohl in C++ als auch in Java zwei Bytes lang
sind. Es kommen auch Daten an, nur sieht es so aus, als ob Java nur das
niederwertige Byte auswertet.
Im fogenden Beispiel gibt z.B. die Javakonsole aus: "Data: 0,1,0,-1,-2".
Wobei die erste Zahl (hier 0) ja vom C++-Programm mit jedem neuen Senden
inkrementiert wird. Dieser Wert läuft (laut Java-Ausgabe) hoch bis 127,
dann von -127 wieder in Richtung 0 und so fort. Wie ein überlaufender
vorzeichenbehafteter 8-bit-Wert. Auf der C++-Seite zählt der Wert ganz
normal hoch bis 32767, bevor er überläuft.
Ich habe schon probiert, die zwei Bytes auf der Java-Seite zu
vertauschen (big/little-endian-Problem), dann kommen viel zu große
Zahlen raus. Im Moment passen wenigsten die positiven und negativen
Zahlen zwischen -127 und 127, deswegen denke ich, daß das Problem nicht
mit big/little-endian zu tun hat??
Kann es sein, daß Java schon beim Einlesen der Daten aus dem buffer die
Daten wegen des Datentyps "byte" anders interpretiert als C++ und dann
der folgende Cast auf Short nicht mehr funktioniert? Dummerweise gibt es
keine Funktion, die aus einem InputStream gleich short-Werte, also
Zwei-Byte-Häppchen ausliest, oder?
Der Code auf der C++-Seite:
> DataSet.Data[i]=(short)buffer[i*2];
buffer[i*2] ist ein Byte. Das wandelst Du in ein short.
Und das geht schief....
Warum liest Du die Daten nicht gleich richtig ein:
zb so
n=IStr.read((byte)DataSet.Data,0,10);
Du solltest eventuell auch den Rückgabewert n auswerten.
Gebe allerdings zu, dass ich von Java keinen blassen Schimmer
habe...
Moin,
Danke für den Hinweis.
Ich habe mal den Teil
1
bytebuffer[]=newbyte[10];
2
n=IStr.read(buffer,0,10);
3
DataSetd=newDataSet();
4
for(inti=0;i<5;i++)
5
DataSet.Data[i]=(short)buffer[i*2];
ersetzt durch
1
DataSetd=newDataSet();
2
n=IStr.read((byte[])d.Data,0,10);
Das mag allerdings der Compiler nicht: "Inconvertible types" (ich
benutze JCreator mit SDK1.5.0_05).
Das dürfte auch der Kern meines Problems sein, denke ich. Ich hätte
gerne eine Funktion, die das aus dem Stream kommende Array
(un-interpretiert, so wie die bytes halt kommen) auf mein Short-Array in
der DataSet-Instanz kopiert. Dort würden dann wieder je zwei Bytes als
short interpretiert und alles wäre gut.
Aber sowas wie memcpy() gibt es ja in Java nicht, richtig? Ich hatte
gehofft, daß (short)buffer[i*2] die beiden bytes in buffer[i] und
buffer[i+1] in einen short packt. War wohl nix.
Gibt's vielleicht noch irgendwelche Klassen, die ich um meinen
InputStream wickeln kann, damit ich short-Variablen daraus lesen kann?
BufferedInputStream kann das anscheinend ebenfalls nicht...
Danke,
Nils
Bei mir musste ich mal Integerwerte aus einem Bytestream lesen.
Dazu habe ich den Bytestream in einen Puffer gelesen und dann daraus
Integers gemacht.
Hier der Code:
ObjectInputStream OIstr = new ObjectInputStream(IStr);
3
...
4
DataSet.Data[i] = OIStr.readShort();
5
...
Ob das allerdings funktioniert, ist nicht unbedingt gesagt, weil
C++-short und Java-Short nicht notwendigerweise gleich im Speicher
abgelegt werden (little endian/big endian). In diesme Fall solltest Du
Dirks Variante in Betracht ziehen.
Es hat übrigens (k)eine Minute gedauert, die Klasse ObjectInputStream im
Package java.io in der JDK-Dokumentation zu finden. ;o)
Gruß
Markus V.
Moin!
Bin gerade auf Arbeit und kann daher nicht sofort testen. Ich hätte
jetzt auch Dirks Methode genommen und mir den short-Wert aus den
einzelnen bytes zusammenaddiert bzw. über Bitoperatoren rausgeholt. Ist
natürlich umständlich, aber was will man machen ;-)
@Markus: Den ObjectInputStream werde ich natürlich auch ausprobieren,
das sieht ja genau passend aus für mein Problem.
Was für eine Java-Doku benutzt du denn? Ich habe einfach die zum SDK
gehörende Doku (ist ein dickes zip-file) entpackt und bekomme dann eine
Verzeichnisstruktur. Ziemlich weit oben liegt eine "index.html", die
rufe ich auf. Und bekomme links einen Frame mit allen (!) Klassen und im
Hauptframe die Eigenschaften, Methoden usw. dieser Klasse. Aber eben
keine Suchfunktion. Hast du da was besseres? Was vielleicht der MSDN
ähnelt und Kontextsuche ermöglicht?
Danke und Gruß,
Nils
Nachdem du jetzt das Schlüsselwort geliefert hast: Beim
ObjectInputStream wird auch ein DataInputStream erwähnt. Der paßt
vielleicht noch besser, weil die Daten nicht serialisiert vorliegen
müssen, sondern nur als Bytestream. Naja, ich werde heute abend mal ein
wenig testen und dann berichten...
Nils
@Nils
Schön, daß ich Dich auf die Spur bringen konnte. Wenn ich die Doku von
DataInputStream und ObjectInputStream lese, dürfte DataInputStream
wahrscheinlich besser geeignet sein. ;-)
Zum Thema Doku der Class-Library: Ich verwende genau dieses (entpackte)
ZIP-File und habe in meinem Browser einen schnell zu erreichenden Link
auf das lokale index.html-File. Allerdings enthält mein Browser-Fenster
3 (!) Frames. Oben links ist ein Frame mit Links auf die Packages. Whält
man eines aus, werden unten links nur noch die Interfaces, Classes und
Exceptions des betreffenden Packages angezeigt. Zu jedem Package gibt es
dann einen Überblick, zu was es gedacht ist und was darin enthalten ist.
Und wenn man es ganz genau nimmt, ist meine Einstiegsseite nicht die der
Klassen-Bibilothek sondern eine Übersichtsseite mit Verweisen zur Suche
(habe ich gerade entdeckt), Links zur Klassen-Doku, Links zu Tutorials,
die recht gut sind, ...
Insgesamt finde ich die Java-Klassen-Doku übersichtlicher und
vollständiger als das MSDN-Zeugs.
Für die Suche verwende ich übrigens zumeist Google. Die Ergebnisse sind
mindestens so hilfreich wie die MSDN-Suche. Eine kontextsensitive Hilfe
dürftest Du bei Eclipse oder NetBeans finden, beides Freeware und DIE
IDEs für Java-Entwicklung.
Gruß
Markus V.