2010-11-30 80 views
2

嘿傢伙。所以這裏是交易。我有一個Java程序運行一個C++程序。 C++進程通過簡單地用std :: cout調用一些指針轉換寫入來向Java程序發送一些雙精度值。 Java程序使用Process的getInputStream(),讀取8個字節,並使用一些字節移位和Double.longBitsToDouble()將它們轉換爲double。我確認了兩個應用程序之間的字體大小以及字節順序相匹配。現在,雖然這在大多數情況下都很有效,但經常發生錯誤。Java Process InputStream錯誤?

我已經將錯誤中的一個隔離爲一個簡單的字節序列,我似乎無法正確傳輸。看看下面的代碼片段:

#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() 
} 

和Java應用程序:

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()) + " "); 
    } 
} 

這些都是很簡單的例子,但它們的服務器來證明我的問題。當我在Windows 7機器上運行這個。我得到了下面的Java輸出:

b6 e1 d a b9 98 e3 48 

預期的輸出是

b6 e1 a b9 98 e3 48 40 

不知何故,一個額外的字節符進行插入。然而,什麼是真正奇怪的是,如果在Java應用程序中,我們讀到一個多字節(改8至9),我們得到

b6 e1 d a b9 98 e3 48 40 

這意味着InputStream中實際上包含9個字節的數據,一旦該額外的0x0d被刪除它包含正確的數據。

你們認爲什麼?正如我之前提到的,這不是經常發生,但當它發生時,它是災難性的。

由於提前, zienkikk

回答

6

cout默認情況下在文本模式下打開了,我想說的情況是,輸出預處理過程中是0xA(換行)字符越來越轉換爲<CRLF>序列。我不認爲有可能將二進制數據可靠地寫入cout(例如參見here),所以我會將所需輸出轉換爲文本,然後在輸入端(Java)反序列化。

+0

您還可以使用以二進制模式打開的顯式文件來傳遞數據。 – 2010-11-30 12:19:59

+0

@Karl - 是的,我不知道如何建議OP連接流如果這樣的方式,但這是一個肯定的選項。 – 2010-11-30 12:20:45

2

在我看來,像你的Windows shell將UNIX風格行結束符LF(0xA)轉換爲Windows行結束符CRLF(0xD OxA)。

由於這個特殊原因,通常不建議將二進制數據寫入程序輸出流。將您的長數據轉換爲文本,然後在Java端進行解析。

3

C++正在將0x0A(即\ n)轉換爲0x0d0a,這是\ r \ n。有一種方法阻止它這樣做,不能幫助你。我不會使用iostreams作爲二進制數據,我可能只是使用write()或fwrite()。