首页 > 其他分享 >『0015』 - Solidity Types - (Dynamically-sized byte array)、(Fixed-size byte arrays)、string之间的转换关系

『0015』 - Solidity Types - (Dynamically-sized byte array)、(Fixed-size byte arrays)、string之间的转换关系

时间:2023-04-08 17:01:46浏览次数:52  
标签:u0000 0015 字节 bytes32 数组 byte string

作者:黎跃春,

大纲

  1. 固定大小字节数组(Fixed-size byte arrays)之间的转换
  2. 固定大小字节数组(Fixed-size byte arrays)转动态大小字节数组(Dynamically-sized byte array)
  3. 固定大小字节数组(Fixed-size byte arrays)不能直接转换为string
  4. 动态大小字节数组(Dynamically-sized byte array)转string
  • 本身就是动态大小字节数组
  • 固定大小字节数组转string,需先转动态字节数组,再转string

固定大小字节数组(Fixed-size byte arrays)之间的转换

固定大小字节我们可以通过bytes0 ~ bytes32来进行声明,固定大小字节数组的长度不可变,内容不可修改。接下来我们通过下面的代码看看固定大小字节之间的转换关系。

pragma solidity ^0.4.4;

contract C {


   bytes9 name9 = 0x6c697975656368756e;


   function bytes9ToBytes1() constant returns (bytes1) {

       return bytes1(name9);
   }

   function bytes9ToBytes2() constant returns (bytes2) {

       return bytes2(name9);
   }

   function bytes9ToBytes32() constant returns (bytes32) {

       return bytes32(name9);
   }

}

结论:bytes9bytes1或者bytes2时,会进行低位截断,0x6c697975656368756e转换为bytes1,结果为0x6c,转换为bytes2时结果为0x6c69。当0x6c697975656368756e转换为bytes32时会进行低位补齐,结果为0x6c697975656368756e0000000000000000000000000000000000000000000000

固定大小字节数组(Fixed-size byte arrays)转动态大小字节数组(Dynamically-sized byte array)

pragma solidity ^0.4.4;

contract C {


   bytes9 name9 = 0x6c697975656368756e;

   function fixedSizeByteArraysToDynamicallySizedByteArray() constant returns (bytes) {

       return bytes(name9);
   }

}

对于刚接触的童鞋,很多人都会用上面的方法进行转换,以为理所当然,殊不知编译运行时,代码报错,原因如下:

备注:简言之,固定大小字节数组动态大小字节数组之间不能简单直接转换。

下面是固定大小字节数组转动态大小字节数组正确的姿势。

pragma solidity ^0.4.4;

contract C {

   bytes9 name9 = 0x6c697975656368756e;

   function fixedSizeByteArraysToDynamicallySizedByteArray() constant returns (bytes) {

       bytes memory names = new bytes(name9.length);

       for(uint i = 0; i < name9.length; i++) {

           names[i] = name9[i];
       }

       return names;
   }

}

在上面的代码中,我们根据固定字节大小数组的长度来创建一个memory类型的动态类型的字节数组,然后通过一个for循环将固定大小字节数组中的字节按照索引赋给动态大小字节数组即可。

固定大小字节数组(Fixed-size byte arrays)不能直接转换为string

pragma solidity ^0.4.4;

contract C {

    bytes9 names = 0x6c697975656368756e;

    function namesToString() constant returns (string) {

        return string(names);
    }

}

动态大小字节数组(Dynamically-sized byte array)转string

重要:因为string是特殊的动态字节数组,所以string只能和动态大小字节数组(Dynamically-sized byte array)之间进行转换,不能和固定大小字节数组进行转行。

  • 如果是现成的动态大小字节数组(Dynamically-sized byte array),如下:
pragma solidity ^0.4.4;

contract C {

    bytes names = new bytes(2);

    function C() {

        names[0] = 0x6c;
        names[1] = 0x69;
    }


    function namesToString() constant returns (string) {

        return string(names);
    }

}
  • 如果是固定大小字节数组转string,那么就需要先将字节数组转动态字节数组,再转字符串
pragma solidity ^0.4.4;

contract C {

   function byte32ToString(bytes32 b) constant returns (string) {

       bytes memory names = new bytes(b.length);

       for(uint i = 0; i < b.length; i++) {

           names[i] = b[i];
       }

       return string(names);
   }

}


可以通过0x6c697975656368756e作为参数进行测试,右边的返回结果看似liyuechun,它的实际内容为liyuechun\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000,所以在实际的操作中,我们应该将后面的一些列\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000去掉。

  • 正确的固定大小字节数组转string的代码
pragma solidity ^0.4.4;

contract C {

    // 0x6c697975656368756e


    function bytes32Content(bytes32 x) constant returns (bytes32) {
        // 0x6c697975656368756e0000000000000000000000000000000000000000000000
        return x;
    }


    function bytes32ToString(bytes32 x) constant returns (string) {
        //0x6c697975656368756e0000000000000000000000000000000000000000000000
        bytes memory bytesString = new bytes(32);
        uint charCount = 0;
        for (uint j = 0; j < 32; j++) {


            // 6 * 2 12


            //  0000001 1000 

            // 0x697975656368756e000000000000000000000000000000000000000000000000
            // byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
            byte char = byte(bytes32(uint(x)  <<  (8 * j)));

            if (char != 0) {
                bytesString[charCount] = char;

                // 0  0x6c
                // 1  0x69
                // 2  0x79 
                // 3  0x95
                // ......
                // 8  0x6e

                charCount++;
            }
        }
        bytes memory bytesStringTrimmed = new bytes(charCount); //0x6c697975656368756e
        for (j = 0; j < charCount; j++) {
            bytesStringTrimmed[j] = bytesString[j];
        }
        return string(bytesStringTrimmed);
    }

}

byte char = byte(bytes32(uint(x) * 2 ** (8 * j)))在上面的代码中,估计大家最难看懂的就是这一句代码,我们通过下面的案例给大家解析:

pragma solidity ^0.4.4;

contract C {

    // 0x6c

    function uintValue() constant returns (uint) {

        return uint(0x6c);
    }

    function bytes32To0x6c() constant returns (bytes32) {

        return bytes32(0x6c);
    }

    function bytes32To0x6cLeft00() constant returns (bytes32) {

        return bytes32(uint(0x6c) * 2 ** (8 * 0));
    }

    function bytes32To0x6cLeft01() constant returns (bytes32) {

        return bytes32(uint(0x6c) * 2 ** (8 * 1));
    }

    function bytes32To0x6cLeft31() constant returns (bytes32) {

        return bytes32(uint(0x6c) * 2 ** (8 * 31));
    }
}
  • bytes32(uint(0x6c) * 2 ** (8 * 31));左移31位
  • bytes32(uint(0x6c) * 2 ** (8 * 1)); 左移1位

通过byte(bytes32(uint(x) * 2 ** (8 * j)))获取到的始终是第0个字节。

总结

string本身是一个特殊的动态字节数组,所以它只能和bytes之间进行转换,不能和固定大小字节数组进行直接转换,如果是固定字节大小数组,需要将其转换为动态字节大小数组才能进行转换。

技术交流

  • 区块链技术交流QQ群:348924182
  • 「区块链部落」官方公众号


标签:u0000,0015,字节,bytes32,数组,byte,string
From: https://blog.51cto.com/u_10981011/6177813

相关文章

  • 『0014』 - Solidity Types - 动态大小字节数组(Dynamically-sized byte array)
    作者:黎跃春,一、Dynamically-sizedbytearraystring是一个动态尺寸的UTF-8编码字符串,它其实是一个特殊的可变字节数组,string是引用类型,而非值类型。bytes动态字节数组,引用类型。根据经验,在我们不确定字节数据大小的情况下,我们可以使用string或者bytes,而如果我们清楚的知道或者......
  • golang中的substring
    发现golangstrings包中没有javastring.substring方法,于是尝试了下:想要在java中实现提取“世”的需求//java代码Strings="Hello,世界";System.out.println(s.substring(7,8));//世在golang中尝试这样://golang代码s1:="Hello,世界"fmt.Println(s1[7:8])//�因为......
  • String
    创建方式属性lenth方法charAt():获取指定位置的字符indexOf():检索字符串trim():去除字符串左右两侧空格substring(start,end)---开始索引,结束索引(含头不含尾)<script>//创建字符串对象varstr=newString("hello");console.log(str);varstr2......
  • C++竞赛常用函数库stl快捷查询手册(vector,map,set,queue,string等)
    1.控制输出流<iomanip>;cout<<setprecision(<span="">int);保留int位有效数字cout<<setprecision(<span="">int)<<fixed;保留int位有效小数为不足4位数的数填充0(如1填充变成0001),cout<<setfill('0')<<setw(4)(一次性效果)......
  • js String汇总
    //----------JavaScriptString----------//charAtcharCodeAt//concatrepeatsplit//slicesubstring//replacereplaceAll//toLowerCasetoUpperCase//startsWithendsWith//indexOflastIndexOfincludes//matchsearch//charAt()//返回在指定位......
  • StringToByte(char* source, uint8_t* dest, int sourceLen)
    voidStringToByte(char*source,uint8_t*dest,intsourceLen){inti;uint8_thighByte,lowByte;for(i=0;i<sourceLen;i+=2){highByte=toupper(source[i]);lowByte=toupper(source[i+1]);if(highB......
  • PrintDocument DrawString C# 换行问题
    在使用80mm小票机做再次开发时使用DrawString无法自动换行导致文字被截断终于找到解决方案:别忘了给我点赞,留言源代码如下:立跑可用 链接:https://pan.baidu.com/s/1vywMUvGXMaFh_1o7ywDQTA?pwd=yyyy提取码:yyyy......
  • String split 坑 防止空 str.split(",")和str.split(",",-1)的区别
    str.split(",",-1);  packagecom.example;publicclassSplitTest{  publicstaticvoidmain(String[]args){    /**     *1.如果字符串最后一位有值,则没有区别,2.如果最后n位都是切割符,split("")不会继续切分,split("",-1)会继续切分......
  • 解决ORA-04031:unable to allocate 56bytes of shared memory
    登录PL/SQLDeveloper出现ORA-04031错误。解决方式:用oracle账号登录linux服务器进入sqlplussqlplus/assysdba查看sga大小showparametersga;扩大sga空间altersystemsetsga_max_size=10Gscope=spfile;altersystemsetsga_target=10Gscope=spfile;关机重启s......
  • 【segmentation fault】std::string析构崩溃
    今天写了一个小工具,运行时发生segmentationfault,现象如下第一步:review崩溃附近代码,产生疑惑,崩溃的地方居然是变量定义的地方std::stringaccessToken;崩溃在这个地方,我直接懵了,只是变量定义为啥会报错,没有任何思路,打算单步调试。第二步:单步调试代码,发现并且是定义的时候崩......