2015-12-12 78 views
2

我需要從整數列表中生成一個字節字符串(按照 的順序將它們通過套接字連接發送給C程序)。我試圖複製一些使用'struct'模塊的Python代碼。下面的Python代碼產生以下輸出:如何將字節數組轉換爲字符串

import struct 
struct.pack('HHHH', 1, 2, 3, 4) 
--> 
'\x01\x00\x02\x00\x03\x00\x04\x00' 

等效Lisp代碼產生以下輸出:

(ql:quickload :pack) 
(pack:pack "HHHH" 1 2 3 4) 
--> 
#(1 0 2 0 3 0 4 0) 

我怎樣才能此數組轉換爲字符串格式作爲由Python產生的相同的表示碼?

非常感謝,

大衛

回答

2

一個非常簡單的轉化字節數組轉換爲字符串的方法是通過使用map預定義功能:

(map 'string #'code-char (pack:pack "HHHH" 1 2 3 4)) 
+0

非常感謝您的回覆Renzo。從評估中得到的結果是我記得在我的探索過程中使用其他方法生成的(不幸的是我現在找不到),所以我得到的結果是「^ A^@^B^@^C^@^D^@」。我沒有把它解釋爲等同於Python輸出。他們是一樣的嗎? – peebz

+0

是的。 '^ @'是'\ x00'(全部爲零的字符),而'^ A'爲'\ x01'等。 – Renzo

+0

你可以用' (格式t「〜a〜%」(char-code x))))(其中'a'是生成的字符串)。 – Renzo

3

當你說「的字符串的字節「,聲明是不準確的。在CL中,字符串是字符的向量。一個角色沒有指定的大小。今天最常見的Lisp實現使用普通Unicode碼位來表示每個字符的大小至少爲21位(但通常爲32位)。

你可能想要的是一個8位字節的向量。這些Lisp類型爲(VECTOR (UNSIGNED-BYTE 8) *)

因此,爲了您的號碼清單轉變成這種載體的最簡單的方法是使用:

然而,這很可能是你實際上並不需要這麼做,因爲這被認爲是隻要流的元素類型設置爲正確的類型,就會自動關注。我不知道你使用的是打開你的網絡連接什麼API,但如果你使用usocket,正確的形式是:

(usocket:socket-connect host port :element-type '(unsigned-byte 8)) 

您可以然後直接寫你的號碼列表使用WRITE-SEQUENCE流,它們將按照您所期望的以字節發送。

最後,我想解釋爲什麼你的字符串技巧可能已經工作。可能發生的情況是,您將流打開爲字符流,這會導致您的字符串使用某種特定的編碼進行編寫。大多數字符串編碼與ASCII兼容(例如UTF-8),這意味着範圍0-127中的任何字節將作爲該字節發送,而高於127的值可能會導致各種不可預知的值(除非您的編碼是ISO 8859-1的情況下值最高爲255也是正確的)。依靠字符串編碼發送二進制數據是一個非常糟糕的主意,我建議您在發送二進制數據時使用適當的二進制流。

相關問題