How can I convert a bytes32
to a string
? Does anyone has a magic function or library which does it?
-
2possible duplicate : ethereum.stackexchange.com/questions/1081/…– euri10Commented Mar 31, 2016 at 17:13
-
This about concatenating, isn't it?– arodriguezdonaireCommented Mar 31, 2016 at 17:16
-
is this a question for solidity or for outside the blockchain e.g. in javascript?– Paul SCommented Mar 31, 2016 at 20:44
-
No, just in the blockchain. I made another question with the js part– arodriguezdonaireCommented Mar 31, 2016 at 20:45
12 Answers
Based on the latest compiler version 0.4.24, I use the following.
function convertingToString()public returns(string){
bytes32 memory hw = "Hello World";
string memory converted = string(hw);
return converted;
}
Using explicit conversion to carry it out. The reverse is also possible.
For versions 0.5.0+ please use (tested from 0.5 to 0.7.2 - it is likely that it will continue to work past 0.7.2):
function bytes32ToString(bytes32 _bytes32) public pure returns (string memory) {
uint8 i = 0;
while(i < 32 && _bytes32[i] != 0) {
i++;
}
bytes memory bytesArray = new bytes(i);
for (i = 0; i < 32 && _bytes32[i] != 0; i++) {
bytesArray[i] = _bytes32[i];
}
return string(bytesArray);
}
-
12This does not work in solidity version 0.5.0+ Commented Jan 4, 2019 at 14:38
-
2
-
2
-
4does not work getting this error ` Failed to decode output: null: invalid codepoint at offset 2; missing continuation byte (argument="bytes", value={"0":91,"1":218,"2":113,"3":98,"4":184,"5":77,"6":255,"7":114,"8":27,"9":203,"10":143,"11":119,"12":114,"13":120,"14":180,"15":136,"16":222,"17":216,"18":209,"19":71,"20":82,"21":100,"22":212,"23":54,"24":28,"25":107,"26":10,"27":191,"28":204,"29":42,"30":153,"31":168}, code=INVALID_ARGUMENT, version=strings/5.1.0) ` was trying to convert this string
0x5bda7162b84dff721bcb8f777278b488ded8d1475264d4361c6b0abfcc2a99a8
Commented Jun 29, 2021 at 16:33
As of feb 2021 you can do
bytes32 foo = "hello";
string memory bar = string(abi.encodePacked(foo));
-
1As soon as StackOverfloor gets the system vote from Medium, I'll give other 10 upvotes. Commented May 23, 2021 at 2:53
-
4Failed to decode output: null: invalid codepoint at offset 2; missing continuation byte (argument="bytes".... Commented Jun 29, 2021 at 15:25
-
4unfortunately it keeps zero padding which might be a problem in some cases..– OssipCommented Apr 29, 2022 at 12:47
-
Here's one:
function bytes32ToString(bytes32 x) constant returns (string) {
bytes memory bytesString = new bytes(32);
uint charCount = 0;
for (uint j = 0; j < 32; j++) {
byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
if (char != 0) {
bytesString[charCount] = char;
charCount++;
}
}
bytes memory bytesStringTrimmed = new bytes(charCount);
for (j = 0; j < charCount; j++) {
bytesStringTrimmed[j] = bytesString[j];
}
return string(bytesStringTrimmed);
}
To test, here it is combined with how to concatenate an array of bytes32
. Paste the following in Remix.
contract C {
function bytes32ToString(bytes32 x) constant returns (string) {
bytes memory bytesString = new bytes(32);
uint charCount = 0;
for (uint j = 0; j < 32; j++) {
byte char = byte(bytes32(uint(x) * 2 ** (8 * j)));
if (char != 0) {
bytesString[charCount] = char;
charCount++;
}
}
bytes memory bytesStringTrimmed = new bytes(charCount);
for (j = 0; j < charCount; j++) {
bytesStringTrimmed[j] = bytesString[j];
}
return string(bytesStringTrimmed);
}
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);
}
}
Click "Create". Then in bytes32ToString
field enter
"0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
and click bytes32ToString
.
In bytes32ArrayToString
field enter
["0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"]
and click bytes32ArrayToString
.
Both will show same result (ABI encoding):
Result: "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
Here's another example. In bytes32ToString
field enter
"0xc3b6"
and click bytes32ToString
. You will get ö
.
-
I used the bytes32ToString function from above, but I obviously doesn't work with special characters such as ö ä ü etc. Is there a way to use this function with special characters? Commented Apr 20, 2017 at 10:02
-
@Bumblebee I added an example for ö and it works. If still needed, probably ask a separate question. (The input or decoding the output might be your problem.)– eth ♦Commented Apr 21, 2017 at 2:31
-
I am trying your
bytes32ArrayToString
with a fixedbytes32[10]
, but it seems I throw aninvalid opcode
if I use 8-10 full slots of the array. Meaning I have a test forabcdefghijklmnopqrstuvwxyzabcdef
(32 characters) 10 times in an array and pass that in, but it throws. If I have 7 or less it works. Any idea why? Commented Nov 12, 2017 at 12:49 -
@TheNomad Not sure. Suggestions, try once instead of 10 times, and post a new question (a Remix or ethfiddle link might help).– eth ♦Commented Nov 19, 2017 at 19:37
-
1@Russo It's not clear what you're trying to do in Python; Stackoverflow is a better fit for questions about converting from different Python types.– eth ♦Commented Jun 3, 2018 at 17:13
How to convert a bytes32 to string:
pragma solidity ^0.4.15;
contract Bytes32ToString {
function bytes32ToStr(bytes32 _bytes32) public pure returns (string) {
// string memory str = string(_bytes32);
// TypeError: Explicit type conversion not allowed from "bytes32" to "string storage pointer"
// thus we should fist convert bytes32 to bytes (to dynamically-sized byte array)
bytes memory bytesArray = new bytes(32);
for (uint256 i; i < 32; i++) {
bytesArray[i] = _bytes32[i];
}
return string(bytesArray);
}
}
In version 0.5.0 and above i ended up with using Viktor answer How to convert a bytes32 to string but removing the zeros otherwise you will end up with
'ERC20\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'
instead of
'ERC20'
This is the code:
/* bytes32 (fixed-size array) to string (dynamically-sized array) */
function bytes32ToString(bytes32 _bytes32) public pure returns (string memory) {
uint8 i = 0;
while(i < 32 && _bytes32[i] != 0) {
i++;
}
bytes memory bytesArray = new bytes(i);
for (i = 0; i < 32 && _bytes32[i] != 0; i++) {
bytesArray[i] = _bytes32[i];
}
return string(bytesArray);
}
It's recommended you convert a bytes32
to a string
using Web3.js to avoid gas costs. To do this, you would get the value of the bytes32
from Solidity to the front end then do:
web3.utils.hexToString(bytes32);
This will convert the bytes32
to a string
that you can then see and use in your frontend dApp.
Just in case, if you want to convert bytes32 to ASCII string, you can use the OpenZeppelin Strings library.
https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2504
Strings.toHexString(uint256(tokenIdSeed), 32),
The output should be like
0xd8df8ecd5432b247d2fc2beb0619d637e9de0df7512bd36220582deda9a1df6e
(this is just covert hexadecimal value of the bytes32 to string)
-
This is the simplest and most elegant solution among all the answers. Thank you!– DominikCommented Jun 3, 2022 at 8:34
Like @e18r already mentioned, the simplest way to do it without having to write all these crazy functions like everyone else is answering with (and would cost more gas), just do:
string(abi.encodePacked(bytes32));
-
1unfortunately it seems to keep zero padding which might be a problem in some cases.– OssipCommented Apr 29, 2022 at 12:47
A more gas-efficient method based on this answer (For versions 0.5.0+):
function toString(bytes32 source)
internal
pure
returns (string memory result)
{
uint8 length = 0;
while (source[length] != 0 && length < 32) {
length++;
}
assembly {
result := mload(0x40)
// new "memory end" including padding (the string isn't larger than 32 bytes)
mstore(0x40, add(result, 0x40))
// store length in memory
mstore(result, length)
// write actual data
mstore(add(result, 0x20), source)
}
}
This solution is using assembly to copy data to memory instead of for
looping.
Here's how I'm doing it:
function char(byte b) returns (byte c) {
if (b < 10) return byte(uint8(b) + 0x30);
else return byte(uint8(b) + 0x57);
}
function bytes32string(bytes32 b32) returns (string out) {
bytes memory s = new bytes(64);
for (var i = 0; i < 32; i++) {
byte b = byte(b32[i]);
byte hi = byte(uint8(b) / 16);
byte lo = byte(uint8(b) - 16 * uint8(hi));
s[i*2] = char(hi);
s[i*2+1] = char(lo);
}
out = string(s);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
contract stringtobytes{
function set(string memory _a)public pure returns(bytes memory){
return bytes(_a);
}
function set1(bytes memory _a)public pure returns(string memory){
return string(_a);
}
}
// you can convert strings to bytes(in decimal format) and vice versa with below code
//1- bytes1=8bit=2decimal
//2 bytes2=16bit=4decimal
//3 bytes3=24bit=6decimal
//4 bytes=dynamic array and reference value
-
2The question is about conversion from bytes32 to string, and your example doesn't work for that.– Ismael ♦Commented Feb 3, 2022 at 13:34
Here's the simplest way i tried
contract ModifyString{
bytes32 public VoterName;
mapping (address => VoterStruct) public voterCalls;
struct VoterStruct{
address VoterAddress;
string VoterID;
bytes32 VoterName2;
}
function addVoter(string memory _VoterID, string memory _VoterName)public {
// Load Voter struct trough mapping
VoterStruct storage newVoter = voterCalls[msg.sender];
// If want to write to global variable
VoterName = bytes32(abi.encodePacked( _VoterName));
// If want to write to struct
newVoter.VoterAddress = msg.sender;
newVoter.VoterID = _VoterID;
newVoter.VoterName2 = bytes32(abi.encodePacked(_VoterName));
}
function getVoterName() public view returns (string memory) {
// To load from Global Variables
bytes memory bytesData = abi.encodePacked(VoterName);
return string(abi.encodePacked(VoterName));
}
function getVoterName2() public view returns (string memory) {
// To look Voter name in global variable
bytes memory bytesData = abi.encodePacked(VoterName);
return string(abi.encodePacked(bytesData));
}
function getVoterName3() public view returns (string memory) {
// To look Voter name in struct
VoterStruct storage voterCall = voterCalls[msg.sender];
return string(abi.encodePacked(voterCall.VoterName2));
}
}
so to load the string, it need to be loaded in memory, as far as i know, string = bytes (without specific bytes number)
then return the output value using
string(abi.encodePacked(bytesData))
^^^^ ^^^^^
//The converted type to //Loaded Variable into memory or storage
ahh so there is to: 1.1 Write String to bytes32 to Global Variable, 1.2 Load string from bytes32 from Gobal Variable, 2.1 Write String to bytes32 to Struct, 2.2 Load String to bytes32 to struct. 😊😊😊