使用 TCHAR 和 ostringstream
Use TCHAR in ostringstream
好吧,我不是真正的 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 变量时,它给了我一个 8 位十六进制“0019EEE0”,而我希望它在 ini 文件中给出一个 32 个字符长的字母数字字符串。我查看了如何将 tchar 转换为字符串,但对我来说没有任何用处。当我把
#ifndef UNICODE
typedef std::string szAPI;
#else
typedef std::wstring szAPI;
#endif
在 header 文件中,没有任何反应,当我把变量转换为字符串时,它出错了(符号不能用 typedef 重载)
我会使用 TCHAR 制作 headers,但我不知道如何使用代码将图像放在 headers 的正下方 [=30] =] header.
所以我对完成这项工作有点不知所措。我需要将 API 密钥放在 ini 文件中,这样我就可以在 php 中使用生成的 ini 文件和一个 exe 构建一个 zip,然后将其发送出去,这样我就可以跟踪谁在将什么上传到我的服务器。
如果您有任何想法,谢谢。
好吧,这可能不是最好的做事方式,但我已经尝试了几个小时,它开始与
一起工作
...
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);
...
如您所述,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());
由于您打算在 Win32 上使用您的代码,最简洁的方法是使用 std::wostringstream
而不是 std::ostringstream
来使字符串操作在 UCS-16 space 上工作。
另一个解决方法是使用 Win32 ANSI 函数来处理多字节 space(例如,GetPrivateProfileStringA()
),如果 ANSI 函数中那些讨厌的 i18n 问题在您的应用程序中不是问题的话。
好吧,我不是真正的 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 变量时,它给了我一个 8 位十六进制“0019EEE0”,而我希望它在 ini 文件中给出一个 32 个字符长的字母数字字符串。我查看了如何将 tchar 转换为字符串,但对我来说没有任何用处。当我把
#ifndef UNICODE
typedef std::string szAPI;
#else
typedef std::wstring szAPI;
#endif
在 header 文件中,没有任何反应,当我把变量转换为字符串时,它出错了(符号不能用 typedef 重载)
我会使用 TCHAR 制作 headers,但我不知道如何使用代码将图像放在 headers 的正下方 [=30] =] header.
所以我对完成这项工作有点不知所措。我需要将 API 密钥放在 ini 文件中,这样我就可以在 php 中使用生成的 ini 文件和一个 exe 构建一个 zip,然后将其发送出去,这样我就可以跟踪谁在将什么上传到我的服务器。
如果您有任何想法,谢谢。
好吧,这可能不是最好的做事方式,但我已经尝试了几个小时,它开始与
一起工作...
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);
...
如您所述,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());
由于您打算在 Win32 上使用您的代码,最简洁的方法是使用 std::wostringstream
而不是 std::ostringstream
来使字符串操作在 UCS-16 space 上工作。
另一个解决方法是使用 Win32 ANSI 函数来处理多字节 space(例如,GetPrivateProfileStringA()
),如果 ANSI 函数中那些讨厌的 i18n 问题在您的应用程序中不是问题的话。