2016-10-26 4 views
1

D'accord, je ne suis pas vraiment une personne C++, et ce sera probablement downvoted à damnation que je lis juste le code et faisant des estimations basées sur les autres langues que je connais (mauvais je sais, mais je juste envie de compiler une solution avec un petit changement)Utiliser TCHAR dans ostringstream

... 

BOOL uploadFile(HWND hwnd, LPCTSTR fileName) 
{ 
    const TCHAR* UPLOAD_SERVER = _T("myhostname.com"); //not my real hostname, just for this question 
    const TCHAR* UPLOAD_PATH = _T("/upload.php"); 
    const TCHAR* CONFIG_FILE = _T("config.ini"); 
    const TCHAR* API_KEY = _T("key"); 

    TCHAR szUploadServer[MAX_PATH]; 
    TCHAR szUploadPath[MAX_PATH]; 
    TCHAR szAPI[MAX_PATH]; 
    TCHAR szWD[MAX_PATH]; 

    const char* sBoundary = "----BOUNDARYBOUNDARY----";  // boundary 
    const char sCrLf[] = { 0xd, 0xa, 0x0 };     // ‰üs(CR+LF) 
    const TCHAR* szHeader = 
     _T("Content-type: multipart/form-data; boundary=----BOUNDARYBOUNDARY----"); 

    _tgetcwd(szWD, sizeof(szWD)/sizeof(TCHAR)); 
    _tcsncat(szWD, _T("\\"), 1); 
    _tcsncat(szWD, CONFIG_FILE, _tcslen(CONFIG_FILE)); 

    GetPrivateProfileString(_T("Configuration"), _T("SERVER"), UPLOAD_SERVER, szUploadServer, sizeof(szUploadServer)/sizeof(TCHAR), szWD); 
    GetPrivateProfileString(_T("Configuration"), _T("PATH"), UPLOAD_PATH, szUploadPath, sizeof(szUploadPath)/sizeof(TCHAR), szWD); 
    GetPrivateProfileString(_T("Configuration"), _T("API"), API_KEY, szAPI, sizeof(szAPI)/sizeof(TCHAR), szWD); 
    std::ostringstream buf; 

    // -- "api" part 
    buf << "--"; 
    buf << sBoundary; 
    buf << sCrLf; 
    buf << "content-disposition: form-data; name=\"api\""; 
    buf << sCrLf; 
    buf << sCrLf; 
    buf << szAPI; 
    buf << sCrLf; 
    // -- "imagedata" part 
    buf << "--"; 
    buf << sBoundary; 
    buf << sCrLf; 
    buf << "content-disposition: form-data; name=\"imagedata\""; 
    buf << sCrLf; 
    //buf << "Content-type: image/png"; // ˆê‰ž 
    //buf << sCrLf; 
    buf << sCrLf; 

    // –{•¶: PNG ƒtƒ@ƒCƒ‹‚ð“Ç‚Ýž‚Þ 
    std::ifstream png; 
    png.open(fileName, std::ios::binary); 
    if (png.fail()) { 
     MessageBox(hwnd, _T("PNG open failed"), szTitle, MB_ICONERROR | MB_OK); 
     png.close(); 
     return FALSE; 
    } 
    buf << png.rdbuf();  // read all & append to buffer 
    png.close(); 

    // ÅŒã 
    buf << sCrLf; 
    buf << "--"; 
    buf << sBoundary; 
    buf << "--"; 
    buf << sCrLf; 

    // ƒƒbƒZ[ƒWŠ®¬ 
    std::string oMsg(buf.str()); 

... beaucoup de lignes plus loin ...

HttpSendRequest(hRequest, 
       szHeader, 
       lstrlen(szHeader), 
       (LPVOID)oMsg.c_str(), 
       (DWORD) oMsg.length()) 

donc, comme vous pouvez le voir, le programme est en train de lire un fichier ini, l'écriture la clé API de szAPI, puis j'ai besoin de l'utiliser dans l'ostringstream (buf). Quand je regarde les variables POST en PHP, cela me donne un hexagone à 8 chiffres "0019EEE0" quand je voudrais donner une chaîne alphanumérique longue de 32 caractères dans le fichier ini. J'ai regardé comment convertir tchar en chaîne, mais rien n'a vraiment fonctionné pour moi. Quand je mets

#ifndef UNICODE 
    typedef std::string szAPI; 
#else 
    typedef std::wstring szAPI; 
#endif 

dans le fichier d'en-tête, rien ne se passe, et quand je l'ai mis à droite lorsque la variable doit convertir en chaîne, il des erreurs (symbole ne peut pas être surchargé avec un typedef)

J'utiliser TCHAR pour faire les en-têtes, mais je ne saurais pas comment faire fonctionner le code pour mettre l'image dans les en-têtes juste en-dessous de l'en-tête de l'api. Donc, je ne suis pas à l'aise avec ce travail. J'ai besoin de la clé API pour être dans le fichier ini afin que je puisse construire un zip en php avec un fichier ini généré et un exe, puis l'envoyer afin que je puisse suivre qui télécharge quoi sur mon serveur.

Si vous avez des idées, merci.

+0

Le but de 'TCHAR' devait permettre de construire un programme pour Windows 9x, de sorte que cela fonctionnerait sous Windows 9x pour un jeu de caractères local limité. Cet horrible appareil à base de macros a été rendu obsolète en l'an 2000 par l'introduction de Layer for Unicode. Puis, quelques années plus tard, Windows 9x n'était plus. Êtes-vous certain que vous ciblez Windows 9x et que vous avez une bonne raison de ne pas utiliser le calque pour Unicode? Si non, pourquoi sur Terre utilisez-vous 'TCHAR'? –

+0

Dans Windows moderne, utilisez simplement des caractères larges (chaînes et fonctions 'wchar_t') et utilisez-les. –

+0

N'utilisez pas TCHAR avec autre chose que des wrappers API Windows. Il est conçu pour faire la transition entre l'encodage de caractères ANSI et les caractères larges. En ce qui concerne le C stdlib, TCHAR n'existe pas. Déterminez le codage de caractères utilisé par votre logiciel et utilisez les fonctions de bibliothèque standard appropriées. –

Répondre

1

Comme vous l'avez noté, utilisez Windows UTF16, mais les fonctions Internet attendez-vous à UTF8.

char api[MAX_PATH]; 
wcstombs(api, szAPI, wcslen(szAPI) + 1); 

Cette conversion ne fonctionnera pas toujours.

En général, vous devez utiliser WideCharToMultiByte pour convertir UTF16 en UTF8.

Puisque vous utilisez Visual Studio, vous pouvez utiliser les classes ATL pour plus de commodité.

#include <AtlStr.h> 

... 
CStringA sA = CW2A(szAPI, CP_UTF8); 

sA contient maintenant des données UTF8. Utiliser comme suit:

my_ostringstream << sA.GetString(); 

ou

HttpSendRequest(hRequest, szHeader, lstrlen(szHeader), 
    (LPVOID)sA.GetString(), (DWORD)sA.GetLength()); 
+0

Merci pour cela. L'utf16 semblait fonctionner correctement dans toutes les situations, mais je suis passé à cela et ça marche aussi. J'ai dû donner à l'imagedata un nom de fichier dans les en-têtes pour que le téléchargement de fichiers php fonctionne. – Alice

0

D'accord, cela est sans doute pas la meilleure façon de faire les choses, mais j'ai essayé pendant des heures et il a commencé à travailler avec

... 

GetPrivateProfileString(_T("Configuration"), _T("SERVER"), UPLOAD_SERVER, szUploadServer, sizeof(szUploadServer)/sizeof(TCHAR), szWD); 
GetPrivateProfileString(_T("Configuration"), _T("PATH"), UPLOAD_PATH, szUploadPath, sizeof(szUploadPath)/sizeof(TCHAR), szWD); 
GetPrivateProfileString(_T("Configuration"), _T("API"), API_KEY, szAPI, sizeof(szAPI)/sizeof(TCHAR), szWD); 
char api[MAX_PATH]; 
wcstombs(api, szAPI, wcslen(szAPI) + 1); 

... 
0

Depuis vous avez l'intention d'utiliser votre code avec Win32, la façon la plus propre serait d'utiliser std::wostringstream au lieu de std::ostringstream pour faire des manipulations de cordes travail sur l'espace UCS-16 . Une autre solution consiste à utiliser les fonctions ANSI Win32 pour travailler sur l'espace multi-octets (par exemple, GetPrivateProfileStringA()), si ces problèmes i18n embêtant dans les fonctions ANSI ne sont pas problème dans votre application.