2013-09-30 45 views
2

我在其中我應該寫ByteArray到文件的項目工作的閱讀序列化從C++中的ByteArray。之後,使用C++程序讀取相同的文件。如何通過從文件

而且ByteArray,我寫入該文件是這三個ByteArrays的組合 -

  • 首先2個字節是我schemaId我已經使用短的數據類型來表示它。
  • 然後下一8字節是我Last Modified Date我所使用長數據類型來表示它。
  • 而其餘的字節是可變大小這是我爲我的屬性實際值..

導致ByteArray到文件寫入之後。現在我需要從C++ program中讀取該文件,並讀取將包含ByteArray的第一行,然後如上所述相應地拆分ByteArray,從而可以從中提取我的schemaId,Last Modified Date和我的實際attribute value

我已經完成了我所有的編碼,總是用Java編寫的,而我是C++的新手......我能夠用C++編寫程序來讀取文件,但不知道該如何讀取ByteArray,我能爲我上面提到的分裂呢..

下面是我的Java代碼,這將導致寫入ByteArray傳遞到文件,現在我需要閱讀它從C++回到同一個文件..

public static void main(String[] args) throws Exception { 

    String os = "whatever os is"; 
    byte[] avroBinaryValue = os.getBytes(); 

    long lastModifiedDate = 1379811105109L; 
    short schemaId = 32767; 

    ByteArrayOutputStream byteOsTest = new ByteArrayOutputStream(); 
    DataOutputStream outTest = new DataOutputStream(byteOsTest); 
    outTest.writeShort(schemaId); 
    outTest.writeLong(lastModifiedDate); 
    outTest.writeInt(avroBinaryValue.length); 
    outTest.write(avroBinaryValue); 

    byte[] allWrittenBytesTest = byteOsTest.toByteArray(); 

    DataInputStream inTest = new DataInputStream(new ByteArrayInputStream(allWrittenBytesTest)); 

    short schemaIdTest = inTest.readShort(); 

    long lastModifiedDateTest = inTest.readLong(); 

    int sizeAvroTest = inTest.readInt(); 
    byte[] avroBinaryValue1 = new byte[sizeAvroTest]; 
    inTest.read(avroBinaryValue1, 0, sizeAvroTest); 


    System.out.println(schemaIdTest); 
    System.out.println(lastModifiedDateTest); 
    System.out.println(new String(avroBinaryValue1)); 

    writeFile(allWrittenBytesTest); 
} 

    /** 
* Write the file in Java 
* @param byteArray 
*/ 
public static void writeFile(byte[] byteArray) { 

    try{ 
     File file = new File("bytearrayfile"); 

     FileOutputStream output = new FileOutputStream(file); 
     IOUtils.write(byteArray, output);   
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 
} 

下面是我正在讀取上述文件(由Java編寫)的C++程序,我不確定我應該如何分割ByteArrays以便我可以單獨讀取人的ByteArray相應..

#include "ReadFile.h" 
#include <iostream> 
#include <fstream> 
#include <string> 

using namespace std; 

int main() { 
    string line; 

    std::ifstream myfile("bytearrayfile", std::ios::binary); 

    //check to see if the file is opened: 
    if (myfile.is_open()) 
    { 
     //while there are still lines in the 
     //file, keep reading: 
     while (! myfile.eof()) 
     { 

     // I am not sure what I am supposed to do here? 

     } 

     //close the stream: 
     myfile.close(); 
    } 

    else cout << "Unable to open file"; 

    return 0; 
} 

反序列化個體的ByteArray後,我應該能夠從上述C++程序提取schemaId爲32767lastModifiedDate作爲1379811105109和我的屬性值作爲whatever os is

我是C++新手,所以面臨很多問題。我的代碼的任何示例基礎將幫助我更好地理解。

任何人都可以幫助我嗎?謝謝。

更新: -

下面是由我能夠提取schemaIdlastModifiedDateattributeLength我最新的代碼。

,但不知道如何提取的實際屬性價值 -

int main() { 
    string line; 

    std::ifstream myfile("bytearrayfile", std::ios::binary); 

    if (myfile.is_open()) { 

     uint16_t schemaId; 
     uint64_t lastModifiedDate; 
     uint32_t attributeLength; 

     char buffer[8]; // sized for the biggest read we want to do 

     // read two bytes (will be in the wrong order) 
     myfile.read(buffer, 2); 
     // swap the bytes 
     std::swap(buffer[0], buffer[1]); 

     // only now convert bytes to an integer 
     schemaId = *reinterpret_cast<uint16_t*>(buffer); 

     cout<< schemaId <<endl; 

     // read eight bytes (will be in the wrong order) 
     myfile.read(buffer, 8); 
     // swap the bytes 
     std::swap(buffer[0], buffer[7]); 
     std::swap(buffer[1], buffer[6]); 
     std::swap(buffer[2], buffer[5]); 
     std::swap(buffer[3], buffer[4]); 

     // only now convert bytes to an integer 
     lastModifiedDate = *reinterpret_cast<uint64_t*>(buffer); 

     cout<< lastModifiedDate <<endl; 

     // read 4 bytes (will be in the wrong order) 
     myfile.read(buffer, 4); 
     // swap the bytes 
     std::swap(buffer[0], buffer[3]); 
     std::swap(buffer[1], buffer[2]); 

     // only now convert bytes to an integer 
     attributeLength = *reinterpret_cast<uint32_t*>(buffer); 

     cout<< attributeLength <<endl; 

     // not sure how to extract the actual attribute value? 

     //close the stream: 
     myfile.close(); 
    } 

    else 
     cout << "Unable to open file"; 

    return 0; 
} 
+0

爲什麼你有'while(!myfile.eof())'?想想你在做什麼。你必須閱讀用Java編寫的C++中的相同內容。在Java中,有四件事情可以寫出來,所以在C++中,你可以閱讀相同的四件事。直到需要文件結束時纔會有循環。 – john

+0

你可以指定其他格式的序列化嗎?例如[JSON](http://en.wikipedia.org/wiki/JSON)或[BSON](http://en.wikipedia.org/wiki/BSON)?看到這個線程:http://stackoverflow.com/questions/245973/whats-the-best-c-json-parser – yegorich

+0

@john:我得到了while循環,因爲我正在關注如何讀取文件在C++上的一些教程在C + +代碼..我不是很好的C++所以這就是爲什麼我面臨這個問題.. – AKIWEB

回答

2

在Java程序是

  1. 寫模式ID
  2. 寫上次變更日期
  3. 寫Avro的二進制數據長度
  4. 寫入avro二進制數據

所以在C++程序是

  1. 讀模式ID
  2. 閱讀最後修改日期
  3. 讀Avro的二進制數據長度
  4. 讀Avro的二進制數據

這確實很這個程序的C++和Java之間差別不大,所以如果你可以用Java來做,你應該(通過一些研究)能夠它在C++中。

這裏是一個開始(第1項)

short schemaId; 
myFile.read(reinterpret_cast<char*>(&schemaId), sizeof(short)); 

reinterpret_cast<char*>是必要的,因爲讀功能需要char*爲它的第一個參數。因此,如果第一個參數是指向char的指針以外的其他參數,則必須進行強制轉換。

這確實假設sizeof(short) == 2(在Java中總是如此,在C++中通常是這樣),並且沒有任何永恆性問題。很難知道這一點,你只需要嘗試一下,看看。

在讀取或寫入二進制整數時,Java和C++的實現可能會使用不同的字節順序。這被稱爲Endianess。如果是這種情況,那麼當你讀取整數時,你將不得不交換字節順序。這裏有一些代碼來做到這一點(這是非常繁瑣的東西,可能有一個更清潔的方式)。

uint16_t schemaId; 
uint64_t lastModifiedDate; 
uint32_t attributeLength; 
char buffer[8]; // sized for the biggest read we want to do 

// read two bytes (will be in the wrong order) 
myfile.read(buffer, 2); 
// swap the bytes 
std::swap(buffer[0], buffer[1]); 
// only now convert bytes to an integer 
schemaId = *reinterpret_cast<uint16_t*>(buffer); 

// read eight bytes (will be in the wrong order) 
myfile.read(buffer, 8); 
// swap the bytes 
std::swap(buffer[0], buffer[7]); 
std::swap(buffer[1], buffer[6]); 
std::swap(buffer[2], buffer[5]); 
std::swap(buffer[3], buffer[4]); 
// only now convert bytes to an integer 
lastModifiedDate = *reinterpret_cast<uint64_t*>(buffer); 

等等

您需要#include <algorithm>得到std::swap功能。

+0

謝謝約翰。如果我這樣做的第一個像這樣 - 'short schemaId;我不知道爲什麼會發生這種錯誤,因爲我不知道爲什麼會這樣。「我總是得到這個錯誤'沒有匹配函數調用'std :: basic_ifstream :: read(short int *,unsigned int)''不知道爲什麼? – AKIWEB

+0

對不起我的錯,我會修復上面的代碼 – john

+0

謝謝約翰,現在錯誤消失了..但是我得到了非常不同的結果schemaId。我已經用實際的代碼更新了我的問題。 – AKIWEB