【蛋疼c++】千万别用std::wifstream读取Unicode UTF16文件

上当了。

最近程序要和 Jscript / activex 脚本通信。

ActiveX这玩意,导出文件,如果是UTF8导出,会出现莫名异常:写一半直接退出。或许是系统语言设置的问题。

但是切换为utf16(unicode)导出就没有问题:

OpenTextFile method (Visual Basic for Applications) | Microsoft Learn

var fso = new ActiveXObject("Scripting.FileSystemObject");
var file = fso.CreateTextFile("", true, true );

然而蛋疼还没有完。在C++程序中,UTF8文件直接用 stf::ifstream 读进来就可以。


							std::ifstream file(L"");
							if (file.is_open()) {
								std::string line;
								while (std::getline(file, line)) {
								...
								}
							}
							file.close();

但 UTF16 却不能直接用 std::wifstream 读取。 StackOverflow 上有人说,需要告知 std::wifstream 编码格式。 c++ 标准库才会跳过bom、进行逐行解码。

有人整理如下:(18)用std::wifstream读取Unicode文本-CSDN博客

结果第二天就出现问题。一些特殊表情符号直接空白(比如:🍓)。或许是,这个办法不支持UTF16的surrogate pair,四个字节的符号。

我勒个去,编码直接变没了!

震惊!

立马鞭策chatgpt,让他写个直接读到 TCHAR* 数组里的替代办法,一点问题没有!c++还真是蛋疼啊~

TCHAR* ReadUTF16File(const TCHAR* filePath) {
	HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE) {
		// Handle file opening error
		return NULL;
	}

	DWORD fileSize = GetFileSize(hFile, NULL);
	TCHAR* buffer = new TCHAR[fileSize / sizeof(TCHAR) + 1];
	DWORD bytesRead = 0;
	ReadFile(hFile, buffer, fileSize, &bytesRead, NULL);
	buffer[fileSize / sizeof(TCHAR)] = '\0';

	CloseHandle(hFile);

	return buffer;
}

std::vector<std::wstring> _args;
QkString ln;
						if(StrCmpN(_args[i].c_str(), L"-loadArgsW", 10)==0) {
							TCHAR* all = ReadUTF16File(_args[i].c_str()+11)+1;
							TCHAR* current = all;
							TCHAR* next = nullptr;
							while ((next = _tcschr(current, _T('\n'))) != nullptr) {
								// Process the line from current to next
								ln.Empty();
								ln.Append(current, next-current);
								//*next = _T('\0');
								//_tprintf(_T("%s\n"), current);
								*next = _T('\n'); // Restore the newline character
								current = next + 1; // Move to the character after the newline
								ln.Trim();
								_args.push_back(ln.GetData());
							}
							if (*current != _T('\0')) {
								//_tprintf(_T("%s\n"), current);
								ln = current;
								ln.Trim();
								_args.push_back(ln.GetData());
							}
						}

这说明,程序里面 TCHAR* 字符串就是UTF16编码,或者说是 IE / JScript / ActiveX 认可的 unicode 编码模式,不需要 std::wifstream 多此一举地解码,直接读取到内存即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值