Concatenating Bytes32 to String – How to Concatenate a Bytes32[] Array to a String in Solidity?

arraysbytescontract-developmentsoliditystring

I am passing an array of bytes32 to my function. This array can contain numbers or hashes etc. to identify an object. In a new use case I want to pass a URL to this function by splitting the URL into parts converted to bytes32. How can I concatenate the single bytes32 to restore the URL?

I know I can create a bytes array and set bytes at indexes. But I don't know how I can access a specific position in a bytes32.

function bytes2string(bytes32[] data) returns (string) {
    bytes memory r = new bytes(1);
    r[0] = bytes1(data[0]);
    return string(r);
}

Best Answer

Thanks to Piper and Chris I found a working solution for Solidity <= 0.2.1. The reason why the first two log statements return different results is, because uintN is right-aligned and bytesN is left-aligned. Conversion between uintN and bytesN first shortens and then changes alignment. That's why it has to be converted back to bytes32 before converted to byte:

LogBytes1(byte(data)); // prints "s"
LogBytes1(byte(uint(data))); prints "\x00"
LogBytes1(byte(bytes32(uint(data)))); prints "s"

A tested solution to my question is:

function bytes32ArrayToString (bytes32[] data) returns (string) {
    bytes memory bytesString = new bytes(data.length * 32);
    uint urlLength;
    for (uint i=0; i<data.length; i++) {
        for (uint j=0; j<32; j++) {
            byte char = byte(bytes32(uint(data[i]) * 2 ** (8 * j)));
            if (char != 0) {
                bytesString[urlLength] = char;
                urlLength += 1;
            }
        }
    }
    bytes memory bytesStringTrimmed = new bytes(urlLength);
    for (i=0; i<urlLength; i++) {
        bytesStringTrimmed[i] = bytesString[i];
    }
    return string(bytesStringTrimmed);
}
Related Topic