wstring to base64

Thomasio

Erfahrenes Mitglied
Ich stehe hoffnunglos im Wald, 1000 Seiten mit Tutorials zu Konvertierungen und ich bringe alles durcheinander, zumindest kommt nichts gescheites heraus.

Ich habe einen std::wstring, den will ich base64 encoden, und wieder decoden zu std::wstring.
Ich habe Funktionen die einfache std::string zu base64 und zurück konvertieren können.
Gibt es z.B. hier: http://www.adp-gmbh.ch/cpp/common/base64.html
Im Web finde ich 100 Sachen wstring zu string oder char* zu konvertieren.
Aber alle meine Versuche das auf wstring umzustellen enden mit einem heillosen Wirrwarr von Pointern, bis ich völlig die Übersicht verloren habe.

Kann mir jemand auf den Weg helfen?
 
Hallo Thomasio,

ich poste mal 2 Funktionen, die Konvertierungen zwischen wstring und string vornehmen. Ich hoffe, das hilft dir weiter.

Gruß
MCoder
C++:
#include <cstdlib>
#include <string>

std::string W2S(std::wstring wstr)
{
    size_t len = wstr.length() * 2;
    char*  psz = new char[len + 1];

    wcstombs(psz, wstr.c_str(), len + 1);
    std::string str = psz;

    delete [] psz;
    return str;
}

std::wstring S2W(std::string str)
{
    size_t   len  = str.length();
    wchar_t* pwsz = new wchar_t[len + 1];

    mbstowcs(pwsz, str.c_str(), len + 1);
    std::wstring wstr = pwsz;

    delete [] pwsz;
    return wstr;
}
 
hi MCoder,

ganz vielen Dank dafür, das ist theoretisch genau das was ich brauche, ich habe nur ein kleines Verständnis-Problem damit.

Nach meinem Verständnis passt ein multibyte character einfach nicht in ein einzelnes byte, darum müssten beim konvertieren von wstring nach string alle Zeichen die in meiner OS-Sprache nicht existieren verloren gehen.

Als Beispiel ein string der ein Gemisch aus deutschen und polnischen Sonderzeichen enthält:

Code:
std::wstring x = L"äöü ??";
std::string converted = W2S(x);
std::wstring back = S2W(converted);
MessageBoxW(0,back.c_str(),L"Result",MB_OK);

gibt auf deutschem OS aus: äöü É>
auf polnischem OS fehlen entsprechend die deutschen Sonderzeichen und auf italienischem OS kommt völliger Murks raus.

Ich brauche die Konvertierung um Daten auf mehreren Wegen zwischen Usern auszutauschen (z.B. sockets oder e-mail), wobei die User nicht immer die gleiche OS Sprache haben.

edit:
Theoretisch brauche ich die Konvertierung zu string gar nicht, ich müsste "nur" die base64_encode() Funktion so umschreiben, dass sie statt jedem Zeichen jedes Byte zu base64 chars umsetzt und base64_decode() entsprechend einen wstring zurück gibt.
Nur bringe ich das nicht auf die Reihe.
 
Zuletzt bearbeitet:
Hallo,

versuche mal, ob du den von wcstombs() erzeugten Buffers an die base64_encode() Funktion übergeben kannst. Die Zuweisung zu string dürfte in der Situation wirklich nur Murks rausbringen.

Ansonsten bekommst du ja mit der c_str() Funktion ein wchar_t - Buffer, den du mittels memcpy() in ein char - Buffer kopieren könntest.

Gruß
MCoder
 
Ähem ..... ok, erwischt, ich verstehe Bahnhof.

Ansonsten bekommst du ja mit der c_str() Funktion ein wchar_t - Buffer, den du mittels memcpy() in ein char - Buffer kopieren könntest.

wchar_t ist nicht immer gleich, die Länge eines Zeichens kann je nach OS verschieden sein, da bin ich schon beim rausfinden der Länge verloren.
Davon abgesehen habe ich Anfänger keine Ahnung, wie ich einen wchar_t Buffer in einen char Buffer kopieren soll.

In jedem Fall bleibt mir danach noch das Problem mit dem zurück konvertieren, denn base64_decode gibt einen std::string zurück, sprich da gehen mir auch wieder alle nicht lokalen Zeichen verloren.

Ich habe mittlerweile 100 Sachen probiert, aber sobald irgendwas irgendwie konvertiert wird, geht irgendwo irgendwas verloren, bzw. braucht dann weitere Konvertierungen oder casts, die wiederum weitere Probleme verursacht, bis ich im Wald stehe.

So wie ich das sehe, muss ich ganz schlicht die Anfangsadresse meines wstring finden, die Länge in Byte rausfinden, jedes Byte einzeln zum entsprechenden base64_char konvertieren und dann das Selbe nochmal rückwärts für den decode.
Mein Problem dabei ist zuerstmal, dass ich mit Pointern wirklich auf Kriegsfuss stehe (ich bin einfach zu blöd dazu), und zum zweiten bringe ich die Konvertierung weder beim encode noch beim decode zustande, weil ich bei 64 base64_chars und 256 möglichen Werten pro Byte die Übersicht verliere, erst recht, wenn ich dann beim decode auch noch mehrere Bytes pro Zeichen brauche.

Am Rande bemerkt:
Es wäre mir völlig Wurscht, ob das Ganze nun base64 oder sonstwas ist, ich muss nur irgendein Format haben, was ich über einen socket schicken kann, von mir aus binary oder sonstwas.
Aber wenn am anderen Ende ein char buffer[1024] ankommt, dann ist dieser naturgemäss auf 1 Byte pro Zeichen begrenzt, und ich muss aus diesem Buffer wieder den original wstring machen.
 
wchar_t ist nicht immer gleich, die Länge eines Zeichens kann je nach OS verschieden sein
Da bin ich mir jetzt nicht so sicher, ob das wirklich so ist. Ich denke, das sind generell 16 Bit.
Was ich aber meinte, ist folgendes:
C++:
std::wstring x = L"äöü ??";

char *pBuffer = new char[x.size() * sizeof(wchar_t)];
memcpy(pBuffer, x.c_str(), x.size() * sizeof(wchar_t));

// base64 encoden

delete [] pBuffer;
Gruß
MCoder
 
Code:
wstring x = L"äöü ??";
char *pBuffer = new char[x.size() * sizeof(wchar_t)];
memcpy(pBuffer, x.c_str(), x.size() * sizeof(wchar_t));
string Result = base64_encode(reinterpret_cast<const unsigned char*>(pBuffer),sizeof(pBuffer));
MessageBox(0,Result.c_str(),"Result",MB_OK);
delete [] pBuffer;

gibt aus: 5AD2AA==

Das könnte zumindest mal richtig sein, auch wenn ich fürchte, dass 6 base64_chars nicht wirklich 6 wstring Zeichen enthalten können.
Aber um das zu überprüfen, müsste ich wissen, wie ich aus Result wieder wstring mache.

base64_decode(Result);

kann ich ja noch, aber dann habe ich halt wieder einen std::string, der (vermutlich) ein wstring Zeichen pro 2 string Zeichen enthält.

Selbst wenn ich base64 mal ganz weg lasse.
Wie mache ich aus pBuffer wieder wstring?
Noch schlimmer:
Beim senden über socket wird aus pBuffer ein char[1024], wie mache ich da wieder wstring draus?
 
Hallo Thomasio,

ich habe mir das Thema noch mal genauer angeschaut. Für die Konvertierungen solltest die Funktionen WideCharToMultiByte() und MultiByteToWideChar() verwenden. Für die Kodierung ist UTF-8 sinnvoll, weil man da portabel ist. Allerdings sollte man dann den Buffer recht großzügig dimemsionieren, weil ein Zeichen mit bis zu 3 Bytes codiert werden kann. Wahrscheinlich kannst du dann auch direkt den Buffer über die Leitung schicken und brauchst nicht extra noch base64 zu kodieren.

Hier der Beispielcode dazu:
Code:
std::wstring wstr = L"äöü ??";

// Konvertierung in einen Byte-Buffer

char pBuffer[1024];

int nBytes = WideCharToMultiByte( CP_UTF8,
                                  0,
                                  wstr.c_str(),
                                  wstr.size(),
                                  pBuffer,
                                  sizeof(pBuffer),
                                  NULL,
                                  NULL );

pBuffer[nBytes] = '\0';

// ... und zurück
                     
wchar_t pwBuffer[1024];

int nWchars = MultiByteToWideChar( CP_UTF8,
                                   0,
                                   pBuffer,
                                   nBytes,
                                   pwBuffer,
                                   nBytes );
                                   
pwBuffer[nWchars] = L'\0';
std::wstring wstr2 = pwBuffer;
Gruß
MCoder
 
Zurück