2014-06-08 21 views
3

我發現char*QByteArray中有空字節。代碼:在QByteArray中使用QDataStream的char *中的空字節

QByteArray arr; 
QDataStream stream(&arr, QIODevice::WriteOnly); 
stream << "hello"; 

看調試器變量視圖:

char* in QByteArray

我不明白爲什麼我一開始三個空字節。我知道[3]字節是字符串長度。我能刪除最後一個字節嗎?我知道它是以空字符結尾的字符串,但對於我的應用程序,我必須有原始字節(在開始存儲長度時有一個字節)。

更奇怪的對我來說,當我使用QString:

QString str = "hello"; 
[rest of code same as above] 
stream << str; 

QString in QByteArray

它不必在末尾的空,所以我想也許空字節之前,每個字符通知下一個字節爲char ?

只有兩個問題:

  1. 爲什麼這麼多的空字節?
  2. 我如何刪除它,包括最後一個空字節?
+1

QStrings是16位unicode字符串 - 這就是爲什麼你在第二個例子中看到每個字符2個字節。 – OnWhenReady

回答

4

我不明白爲什麼我在開頭有三個空字節。

這是一個固定大小的uint32_t(4字節)標題。它是四個字節,因此它可以指定長度爲(2^32-1)個字節的數據長度。如果它只有一個字節,那麼它只能描述長達255個字節的字符串,因爲這是可以放入一個字節中的最大整數值。

我可以刪除最後一個字節嗎?我知道它是以空字符結尾的字符串,但對於我的 應用程序,我必須有原始字節(一個字節在開始存儲長度爲 )。

當然,只要稍後解析數據數組的代碼不依賴於存在尾NUL字節才能正常工作。

對我來說更奇怪的是,當我使用QString [...]它沒有在結束時爲空,所以我認爲可能在每個字符之前的空字節通知下一個字節是char?

Qt serialization documentation page,爲QString被序列爲:

- If the string is null: 0xFFFFFFFF (quint32) 
- Otherwise: The string length in bytes (quint32) followed by the data in UTF-16. 

如果你不喜歡這種格式,而不是直接序列化的QString,你可以不喜歡

stream << str.toUtf8(); 

取而代之,那樣QByteArray中的數據將以更簡單的格式(UTF-8)。

爲什麼這麼多空字節?

當被編碼的長度值很小時,它們用於固定大小的頭部字段;或者指示以NUL結尾的C字符串的結尾。

我如何刪除它,包括最後一個空字節?

您可以添加字符串中的首選格式(無NUL終止,但有一個長頭字節)是這樣的:

const char * hello = "hello"; 
char slen = strlen(hello); 
stream.writeRawData(&slen, 1); 
stream.writeRawData(hello, slen); 

...但如果你有選擇,我強烈建議只是保持NUL終止子字節的字符串的末尾,基於這些原因:

  1. 單個前一長度字節將限制你的字符串爲255個字節長(或更少),這是一種不必要的限制那可能會是h阿姨你在未來。

  2. 避免使用NUL終結符字節實際上並不會節省任何空間,因爲您添加了字符串長度字節來進行補償。

  3. 如果NUL終止符字節在那裏,您可以直接將指針傳遞給字符串的第一個字節直接到任何代碼需要一個C風格的字符串,它將能夠立即使用該字符串(沒有任何數據轉換步驟)。如果你依賴於一個不同的約定,那麼你最終必須複製整個字符串,然後才能將它傳遞給該代碼,以便可以將NUL字節附加到該字符串的末尾,以便需要C字符串的代碼可以使用它。這將是CPU效率低下且容易出錯的。

+0

感謝您的解釋,現在我明白了。另外,writeRawData可以正常工作:)不幸的是,我必須刪除NUL終結符,因爲以這種方式創建的數據將通過TCP以特定的常量格式發送到服務器。 – aso

相關問題