¿Cómo puedo convertir un bytes32
a un string
? ¿Alguien tiene una función mágica o una biblioteca que lo haga?
Basado en la última versión del compilador 0.4.24, uso lo siguiente.
function convertingToString()public returns(string){
bytes32 memory hw = "Hello World";
string memory converted = string(hw);
return converted;
}
Usando conversión explícita para llevarlo a cabo. También es posible lo contrario.
Para las versiones 0.5.0+, utilice (probado de 0.5 a 0.7.2; es probable que continúe funcionando después de 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);
}
0x5bda7162b84dff721bcb8f777278b488ded8d1475264d4361c6b0abfcc2a99a8
A partir de febrero de 2021 puedes hacerlo
bytes32 foo = "hello";
string memory bar = string(abi.encodePacked(foo));
Aquí hay uno:
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);
}
Para probar, aquí se combina con cómo concatenar una matriz debytes32
. Pega lo siguiente en 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);
}
}
Haz clic en "Crear". Luego en bytes32ToString
el campo ingrese "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
y haga clic en bytes32ToString
.
En bytes32ArrayToString
el campo ingrese ["0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"]
y haga clic en bytes32ArrayToString
.
Ambos mostrarán el mismo resultado (codificación ABI): Resultado:"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
Aquí hay otro ejemplo. En bytes32ToString
el campo ingrese "0xc3b6"
y haga clic en bytes32ToString
. obtendrás ö
_
bytes32ArrayToString
con un fijo bytes32[10]
, pero parece que arrojo un invalid opcode
si uso 8-10 ranuras completas de la matriz. Lo que significa que tengo una prueba para abcdefghijklmnopqrstuvwxyzabcdef
(32 caracteres) 10 veces en una matriz y la paso, pero arroja. Si tengo 7 o menos funciona. ¿Alguna idea de por qué?Cómo convertir un bytes32 a cadena:
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);
}
}
Como @ e18r ya mencionado, la forma más sencilla de hacerlo sin tener que escribir todas estas funciones locas con las que todos los demás están respondiendo (y costaría más gasolina), simplemente hazlo:
string(abi.encodePacked(bytes32));
Se recomienda convertir un bytes32
a a string
usando Web3.js para evitar costos de gasolina. Para hacer esto, obtendría el valor de bytes32
Solidity en el front-end y luego haría:
web3.utils.hexToString(bytes32);
Esto convertirá el bytes32
a un string
que luego puede ver y usar en su dApp frontend.
Por si acaso, si desea convertir bytes32 a una cadena ASCII, puede usar la biblioteca OpenZeppelin Strings.
https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2504
Strings.toHexString(uint256(tokenIdSeed), 32),
La salida debería ser como
0xd8df8ecd5432b247d2fc2beb0619d637e9de0df7512bd36220582deda9a1df6e
(esto es solo un valor hexadecimal encubierto de los bytes32 a la cadena)
En la versión 0.5.0 y superior, terminé usando la respuesta de Viktor Cómo convertir un bytes32 en una cadena pero eliminando los ceros ; de lo contrario, terminará con
'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'
en vez de
'ERC20'
Este es el código:
/* 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);
}
Un método más eficiente en gas basado en esta respuesta (para versiones 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)
}
}
Esta solución utiliza ensamblaje para copiar datos en la memoria en lugar de hacer un for
bucle.
Así es como lo estoy haciendo:
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);
}
}
// puede convertir cadenas a bytes (en formato decimal) y viceversa con el siguiente código
//1- bytes1=8bit=2decimal
//2 bytes2=16bit=4decimales
//3 bytes3=24bit=6decimal
//4 bytes=matriz dinámica y valor de referencia
eur10
arodriguezdonaire
pablo s
arodriguezdonaire