『0014』 - Solidity Types - 動態大小字節數組(Dynamically-sized byte array)
作者:黎躍春,區塊鏈、高可用架構工程師
微信:liyc1215 QQ群:348924182 博客:https://liyuechun.org
一、Dynamically-sized byte array
-
string
是一個動態尺寸的UTF-8
編碼字符串,它其實是一個特殊的可變字節數組,string
是引用類型,而非值類型。 -
bytes
動態字節數組,引用類型。
根據經驗,在我們不確定字節數據大小的情況下,我們可以使用string
或者bytes
,而如果我們清楚的知道或者能夠將字節書控製在bytes1
~ bytes32
,那麼我們就使用bytes1
~ bytes32
,這樣的話能夠降低存儲成本。
二、常規字符串 sting 轉換為 bytes
string
字符串中沒有提供length
方法獲取字符串長度,也沒有提供方法修改某個索引的字節碼,不過我們可以將string
轉換為bytes
,再調用length
方法獲取字節長度,當然可以修改某個索引的字節碼。
1、源碼
pragma solidity ^0.4.4;
contract C {
bytes9 public g = 0x6c697975656368756e;
string public name = "liyuechun";
function gByteLength() constant returns (uint) {
return g.length;
}
function nameBytes() constant returns (bytes) {
return bytes(name);
}
function nameLength() constant returns (uint) {
return bytes(name).length;
}
function setNameFirstByteForL(bytes1 z) {
// 0x4c => "L"
bytes(name)[0] = z;
}
}
2、效果圖
3、說明
function nameBytes() constant returns (bytes) {
return bytes(name);
}
nameBytes
這個函數的功能是將字符串name
轉換為bytes
,並且返回的結果為0x6c697975656368756e
。0x6c697975656368756e
一共為9字節
,也就是一個英文字母對應一個字節。
function nameLength() constant returns (uint) {
return bytes(name).length;
}
我們之前講過,string
字符串它並不提供length
方法幫助我們返回字符串的長度,所以在nameLength
方法中,我們將name
轉換為bytes
,然後再調用length
方法來返回字節數,因為一個字節對應一個英文字母,所以返回的字節數量剛好等於字符串的長度。
function setNameFirstByteForL(bytes1 z) {
// 0x4c => "L"
bytes(name)[0] = z;
}
如果我們想將name
字符串中的某個字母進行修改,那麼我們直接通過x[k] = z
的形式進行修改即可。x
是bytes類型的字節數組,k
是索引,z
是byte1
類型的變量值。
setNameFirstByteForL
方法中,我就將liyuechun
中的首字母修改成L
,我傳入的z
的值為0x4c
,即大寫的L
。
三、漢字字符串或特殊字符的字符串轉換為bytes
1、特殊字符
pragma solidity ^0.4.4;
contract C {
string public name = "a!+&520";
function nameBytes() constant returns (bytes) {
return bytes(name);
}
function nameLength() constant returns (uint) {
return bytes(name).length;
}
}
在這個案例中,我們聲明了一個name
字符串,值為a!+&520
,根據nameBytes
和nameLength
返回的結果中,我們不難看出,不管是字母
、數字
還是特殊符號
,每個字母對應一個byte(字節)
。
2、中文字符串
pragma solidity ^0.4.4;
contract C {
string public name = "黎躍春";
function nameBytes() constant returns (bytes) {
return bytes(name);
}
function nameLength() constant returns (uint) {
return bytes(name).length;
}
}
在上麵的代碼中,我們不難看出,黎躍春
轉換為bytes
以後的內容為0xe9bb8ee8b783e698a5
,一共9個字節
。也就是一個漢字需要通過3個字節
來進行存儲。那麼問題來了,以後我們取字符串時,字符串中最好不要帶漢字,否則計算字符串長度時還得特殊處理。
四、創建bytes字節數組
pragma solidity ^0.4.4;
contract C {
bytes public name = new bytes(1);
function setNameLength(uint length) {
name.length = length;
}
function nameLength() constant returns (uint) {
return name.length;
}
}
五、bytes可變數組length和push兩個函數的使用案例
pragma solidity ^0.4.4;
contract C {
// 0x6c697975656368756e
// 初始化一個兩個字節空間的字節數組
bytes public name = new bytes(2);
// 設置字節數組的長度
function setNameLength(uint len) {
name.length = len;
}
// 返回字節數組的長度
function nameLength() constant returns (uint) {
return name.length;
}
// 往字節數組中添加字節
function pushAByte(byte b) {
name.push(b);
}
}
說明:當字節數組的長度隻有2時,如果你通過push往裏麵添加了一個字節,那麼它的長度將變為3,當字節數組裏麵有3個字節,但是你通過length方法將其長度修改為2時,字節數組中最後一個字節將被從字節數組中移除。
五、總結
對比分析:
- 不可變字節數組
我們之前的文章中提到過如果我們清楚我們存儲的字節大小,那麼我們可以通過bytes1
,bytes2
,bytes3
,bytes4
,......,bytes32
來聲明字節數組變量,不過通過bytesI
來聲明的字節數組為不可變字節數組,字節不可修改,字節數組長度不可修改。
- 可變字節數組
我們可以通過bytes name = new bytes(length)
- length
為字節數組長度,來聲明可變大小和可修改字節內容的可變字節數組。
最後更新:2017-10-27 22:04:34