So konvertieren Sie ein bytes32 in einen String

bytes32Wie kann ich a in a umwandeln string? Hat jemand eine magische Funktion oder Bibliothek, die es tut?

Hier geht es um Verkettung, nicht wahr?
ist dies eine Frage für die Solidität oder für außerhalb der Blockchain, z. B. in Javascript?
Nein, nur in der Blockchain. Ich habe eine andere Frage mit dem js-Teil gestellt

Antworten (11)

Basierend auf der neuesten Compiler-Version 0.4.24 verwende ich Folgendes.

function convertingToString()public returns(string){
bytes32 memory hw = "Hello World";
string memory converted = string(hw);
return converted;
}

Verwenden der expliziten Konvertierung, um dies auszuführen. Auch der umgekehrte Weg ist möglich.

Für die Versionen 0.5.0+ verwenden Sie bitte (getestet von 0.5 bis 0.7.2 - es ist wahrscheinlich, dass es nach 0.7.2 weiter funktioniert):

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);
    }
Dies funktioniert nicht in Solidity-Version 0.5.0+
und was bedeutet??
aktualisiert für Solidity-Version nach 0.5.0
funktioniert nicht und erhalte diesen Fehler ` Ausgabe konnte nicht dekodiert werden: null: ungültiger Codepunkt bei Offset 2; fehlendes Fortsetzungsbyte (Argument="Bytes", Wert={"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) ` hat versucht, diesen String zu konvertieren0x5bda7162b84dff721bcb8f777278b488ded8d1475264d4361c6b0abfcc2a99a8

Ab Februar 2021 können Sie dies tun

bytes32 foo = "hello";
string memory bar = string(abi.encodePacked(foo));
Sobald StackOverfloor die Systemabstimmung von Medium erhält, gebe ich weitere 10 Upvotes.
Fehler beim Decodieren der Ausgabe: null: ungültiger Codepunkt bei Offset 2; fehlendes Fortsetzungsbyte (argument="bytes"....
Leider behält es keine Auffüllung bei, was in einigen Fällen ein Problem sein könnte.

Hier ist eine:

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);
}

Zum Testen wird es hier kombiniert mit dem Verketten eines Arrays vonbytes32 . Fügen Sie Folgendes in Remix ein .

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);
    }    
}

Klicken Sie auf „Erstellen“. Geben Sie dann in bytes32ToStringdas Feld ein "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"und klicken Sie auf bytes32ToString.

Geben Sie im bytes32ArrayToStringFeld ein ["0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"]und klicken Sie auf bytes32ArrayToString.

Beide zeigen dasselbe Ergebnis (ABI-Codierung): Ergebnis:"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"


Hier ist ein weiteres Beispiel. Geben Sie im bytes32ToStringFeld ein "0xc3b6"und klicken Sie auf bytes32ToString. Du wirst bekommen ö.

Geben Sie hier die Bildbeschreibung ein

Ich habe die bytes32ToString-Funktion von oben verwendet, aber ich arbeite offensichtlich nicht mit Sonderzeichen wie ö ä ü usw. Gibt es eine Möglichkeit, diese Funktion mit Sonderzeichen zu verwenden?
@Bumblebee Ich habe ein Beispiel für ö hinzugefügt und es funktioniert. Wenn es noch benötigt wird, stellen Sie wahrscheinlich eine separate Frage. (Die Eingabe oder Dekodierung der Ausgabe könnte Ihr Problem sein.)
Ich versuche es bytes32ArrayToStringmit einem festen bytes32[10], aber es scheint, dass ich einen werfe, invalid opcodewenn ich 8-10 volle Slots des Arrays verwende. Das heißt, ich habe einen Test für abcdefghijklmnopqrstuvwxyzabcdef(32 Zeichen) 10 Mal in einem Array und übergebe das, aber es wirft. Wenn ich 7 oder weniger habe, funktioniert es. Irgendeine Idee warum?
@TheNomad Nicht sicher. Vorschläge, versuchen Sie es einmal statt zehnmal und posten Sie eine neue Frage (ein Remix- oder Ethfiddle-Link könnte hilfreich sein).
@Russo Es ist nicht klar, was Sie in Python versuchen. Stackoverflow eignet sich besser für Fragen zur Konvertierung von verschiedenen Python-Typen.
Hatte keine Ahnung, dass ein String ein Array von Bytes ist. Heute etwas Neues gelernt! Danke!

So konvertieren Sie ein bytes32 in einen 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);
    }

}

Wie bei @e18r bereits erwähnt, ist der einfachste Weg, dies zu tun, ohne all diese verrückten Funktionen schreiben zu müssen, mit denen alle anderen antworten (und mehr Benzin kosten würden), einfach:

string(abi.encodePacked(bytes32));

Leider scheint es keine Auffüllung beizubehalten, was in einigen Fällen ein Problem sein könnte.

Es wird empfohlen, mithilfe von Web3.js a bytes32in a umzuwandeln, um Benzinkosten zu vermeiden. stringUm dies zu tun, würden Sie den Wert bytes32von Solidity an das Frontend abrufen und dann Folgendes tun:

web3.utils.hexToString(bytes32);

Dadurch wird die bytes32in eine konvertiert, die stringSie dann in Ihrer Frontend-dApp sehen und verwenden können.

Für alle Fälle, wenn Sie bytes32 in ASCII-Strings konvertieren möchten, können Sie die OpenZeppelin Strings-Bibliothek verwenden.

https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2504

Strings.toHexString(uint256(tokenIdSeed), 32),

Die Ausgabe sollte wie sein

0xd8df8ecd5432b247d2fc2beb0619d637e9de0df7512bd36220582deda9a1df6e 

(Dies ist nur ein verdeckter Hexadezimalwert der Bytes32 in den String)

Dies ist die einfachste und eleganteste Lösung unter allen Antworten. Vielen Dank!

In Version 0.5.0 und höher endete ich mit der Verwendung von Viktor answer How to convert a bytes32 to string , aber das Entfernen der Nullen, sonst werden Sie damit enden

'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'

Anstatt von

'ERC20'

Dies ist der 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);
    }

Eine gaseffizientere Methode basierend auf dieser Antwort (für Versionen 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)
    }
}

Diese Lösung verwendet Assembly, um Daten in den Speicher zu kopieren, anstatt forSchleifen zu verwenden.

So mache ich es:

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);
        } 

}

// Sie können Zeichenfolgen in Bytes (im Dezimalformat) und umgekehrt mit dem folgenden Code konvertieren

//1- Bytes1=8bit=2dezimal

//2 Bytes2=16bit=4dezimal

//3 Bytes3=24bit=6dezimal

//4 Bytes=dynamisches Array und Referenzwert

Die Frage bezieht sich auf die Konvertierung von Bytes32 in String, und Ihr Beispiel funktioniert dafür nicht.