2010-11-30 15 views
2

Hey Leute. Also hier ist der Deal. Ich habe ein Java-Programm, das ein C++ - Programm ausführt. Der C++ - Prozess sendet einige Doubles an das Java-Programm, indem er einfach write auf std :: cout mit einem Pointer-Casting aufruft. Das Java-Programm verwendet die getInputStream() -Prozedur des Prozesses, liest 8 Byte ein und konvertiert sie in ein Double, wobei einige Byte-Verschiebungen und Double.longBitsToDouble() verwendet werden. Ich habe sichergestellt, dass die Schriftgrößen sowie Byte-Ordnungen zwischen den 2 Anwendungen übereinstimmen. Während dies die meiste Zeit funktioniert, tritt gelegentlich ein Fehler auf.Java Process InputStream Fehler?

Ich habe einen der Fehler auf eine einfache Sequenz von Bytes isoliert, die ich nicht korrekt übertragen kann. Schauen Sie sich die folgenden Schnipsel:

#include <iostream> 

int main(int argc, char** argv) { 
    long long l = 0x4048e398b90ae1b6; 
    char* ptr = (char*) &l; 
    std::cout.write(ptr, 8); 
    std::cout.flush(); 


    // for (int i = 0; i < 8; ++i) 
    // std::cout.put(ptr[i]); 
    // std::cout.flush() 
} 

Und die Java App:

public static void main(String[] argv) throws IOException { 
    Process p = Runtime.getRuntime().exec("prog.exe"); 
    InputStream is = p.getInputStream(); 

    for (int i = 0 ; i < 8; ++i) { 
    System.err.print(Long.toHexString(is.read()) + " "); 
    } 
} 

Diese sind ziemlich einfache Beispiele, aber sie Server, mein Problem zu demonstrieren. Wenn ich das auf meinem Windows 7-Rechner ausführe. Ich erhalte den folgenden Java-Ausgang:

b6 e1 d a b9 98 e3 48 

Die erwartete Ausgabe ist

b6 e1 a b9 98 e3 48 40 

Irgendwie ein zusätzliches 0x0d Byte eingefügt wird. Doch was wirklich seltsam ist, dass, wenn in der Java-Anwendung wir ein weiteres Byte (Wechsel der 8 zu einem 9) lesen, erhalten wir

b6 e1 d a b9 98 e3 48 40 

Das bedeutet, dass der Input enthielt tatsächlich 9 Bytes von Daten und einmal, dass extra 0x0d ist entfernt es enthält die richtigen Daten.

Was denkst du? Wie ich bereits erwähnt habe, passiert dies nicht oft, aber wenn es so ist, ist es katastrophal.

Vielen Dank im Voraus, zienkikk

Antwort

6

cout standardmäßig im Textmodus geöffnet ist, was würde ich sagen, ist passiert, dass die 0xa (Zeilenvorschub) Zeichen werden während der Ausgabe Vorverarbeitung zu einer <CRLF> Sequenz umgewandelt zu werden.

Ich glaube nicht, dass es möglich ist, binäre Daten zuverlässig in cout zu schreiben (siehe here zum Beispiel), also würde ich Ihre gewünschte Ausgabe in Text konvertieren und dann auf der Eingangsseite (Java) deserialisieren.

+0

Sie können auch eine explizite Datei verwenden, die im Binärmodus geöffnet wurde, um die Daten zu übertragen. –

+0

@Karl - Ja, ich war mir nicht sicher, wie ich vorschlagen sollte, dass OP die Streams miteinander verbindet, wenn man so vorgeht, aber das ist eine Option. –

+0

Danke für die schnellen Antworten. Genau das war der Fehler.Die Verwendung einer Datei verlangsamt die Menge an Daten, die ich übergebe, aber da dieser Code auf einer Unix-Maschine laufen soll, denke ich, wird es ausreichen (ich war einfach zu faul, die virtuelle Maschine hochzufahren und sie zu testen)). Ich weiß, dass das Schreiben von binären Daten zu stdout ein bisschen ify ist, aber es schien wie der einfachste Weg, um das gewünschte Ergebnis zu erreichen. – zienkikk

2

Sieht für mich wie Ihre Windows-Shell konvertiert UNIX-Stil Zeilenbegrenzer LF (0xA) zu Windows Line Terminator CRLF (0xD OxA).

Im Allgemeinen ist es aus diesem speziellen Grund nicht ratsam, Binärdaten in den Programmausgangsstrom zu schreiben. Konvertieren Sie Ihre langen Daten in Text und analysieren Sie sie dann auf einer Java-Seite.

+0

Hier ist keine Shell beteiligt. – EJP

+0

@EJP. Einverstanden. Mein C++ wird immer rostiger. –

3

C++ übersetzt 0x0A, was \ n ist, zu 0x0d0a, was \ r \ n ist. Es gibt eine Methode, um es zu stoppen, kann dir nicht helfen, was es ist. Ich würde Iostreams nicht selbst für Binärdaten verwenden, ich würde wahrscheinlich nur write() oder fwrite() verwenden.