【问题标题】:Use TCHAR in ostringstream在 ostringstream 中使用 TCHAR
【发布时间】:2016-10-26 01:03:41
【问题描述】:

好吧,我不是一个真正的 C++ 人,这可能会被认为是该死的,因为我只是在阅读代码并根据我知道的其他语言进行猜测(我知道不好,但我只是想编译一个小改动的解决方案)

...

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

...很多行之后...

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

所以,如您所见,程序正在读取一个ini文件,将API密钥写入szAPI,然后我需要在ostringstream(buf)中使用它。当我查看 PHP 中的 POST 变量时,当我希望它在 ini 文件中给出一个 32 个字符长的字母数字字符串时,它给了我一个 8 位十六进制“0019EEE0”。我研究了如何将 tchar 转换为字符串,但没有什么对我真正有用。当我放

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

在头文件中,什么都没有发生,当我把它当变量转换为字符串时,它会出错(符号不能用 typedef 重载)

我会使用 TCHAR 来制作标题,但我不知道如何使用代码将图像放在 api 标题正下方的标题中。

所以我有点不知所措。我需要将 API 密钥放在 ini 文件中,这样我就可以使用生成的 ini 文件和 exe 在 php 中构建一个 zip,然后将其发送出去,以便我可以跟踪谁将什么上传到我的服务器。

如果您有任何想法,谢谢。

【问题讨论】:

  • TCHAR 的目的是让为 Windows 9x 构建一个程序成为可能,这样它就可以在 Windows 9x 中为有限的本地字符集工作。这个丑陋的基于宏的设备在 2000 年因 Unicode 层的引入而被淘汰。几年后,Windows 9x 不复存在。您确定您的目标是 Windows 9x,并且您有充分的理由不使用 Unicode 层吗?如果没有,你到底为什么要使用TCHAR
  • 在现代 Windows 中,只需使用宽字符(基于wchar_t 的字符串和函数)即可。
  • 不要将 TCHAR 与 Windows API 包装器一起使用。它旨在在 ANSI 字符编码和宽字符之间进行转换。就 C 标准库而言,TCHAR 不存在。确定您的软件使用哪种字符编码并使用适当的标准库函数。
  • 在这种情况下,我几乎认为如果你在任何地方都使用wchar_t,然后使用HttpSendRequestW,一切都会变得更简单。它将处理任何必要的 ANSI 字符编码转换。
  • @Cheersandhth.-Alf 我有点希望他们能转换回 8 位字符,这次只有 UTF-8。

标签: c++ std tchar


【解决方案1】:

如您所述,Windows 使用 UTF16,但互联网功能需要 UTF8。

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

这种转换并不总是有效。

一般情况下,您必须使用WideCharToMultiByte 将UTF16 转换为UTF8。

由于您使用的是 Visual Studio,因此为了方便,您可以使用 ATL 类。

#include <AtlStr.h>

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

sA 现在包含 UTF8 数据。使用如下:

my_ostringstream << sA.GetString();

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

【讨论】:

  • 谢谢你。 utf16 似乎在所有情况下都可以正常工作,但我切换到它并且它也可以工作。我确实需要在标头中为图像数据提供一个文件名,以便 php 文件上传工作。
【解决方案2】:

好的,这可能不是最好的做事方式,但我已经尝试了几个小时,它开始使用了

...

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

...

【讨论】:

    【解决方案3】:

    由于您打算在 Win32 中使用您的代码,最简洁的方法是使用 std::wostringstream 而不是 std::ostringstream 使字符串操作在 UCS-16 空间上工作。

    另一个解决方法是使用 Win32 ANSI 函数处理多字节空间(例如,GetPrivateProfileStringA()),如果 ANSI 函数中那些讨厌的 i18n 问题在您的应用程序中没有问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多