閱讀518 返回首頁    go 阿裏雲 go 技術社區[雲棲]


『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,並且返回的結果為0x6c697975656368756e0x6c697975656368756e一共為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是索引,zbyte1類型的變量值。

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,根據nameBytesnameLength返回的結果中,我們不難看出,不管是字母數字還是特殊符號,每個字母對應一個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;
    }

}

solidity 漢字 字符串長度

在上麵的代碼中,我們不難看出,黎躍春轉換為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

  上一篇:go  『0015』 - Solidity Types - 動態字節數組(Dynamically-sized byte array)、固定大小字節數組(Fixed-size byte arrays)、string之間的轉換關係
  下一篇:go  『0013』 - Solidity Types - 固定大小字節數組(Fixed-size byte arrays)