提问人:Edward Tsui 提问时间:11/1/2023 最后编辑:Remy LebeauEdward Tsui 更新时间:11/2/2023 访问量:92
如何修复MFC CStdioFile和CString乱码,同时读取和处理文件中的数据?
How to Fix MFC CStdioFile and CString Garbled Characters while Reading and Dealing with Data in Files?
问:
Visual Studio 2019 社区版和 MFC
我的代码:
void CTMCVDlg::FileIO()
{
// Getting source file path to read and destination file path to write
CString destpath, sourcepath, destname;
GetDlgItemText(IDC_EDIT1, sourcepath);
GetDlgItemText(IDC_EDIT1, destpath);
GetDlgItemText(IDC_EDIT2, destname);
destpath = GetFilePathExceptFileName(destpath);
CStdioFile outF(destpath + destname + _T(".osu"), CFile::modeWrite | CFile::modeCreate);
CStdioFile inF(sourcepath, CFile::modeRead | CFile::typeBinary);
// Operation Log
AppendText3(_T("Created and opened file \"") + filename + _T(".osu\""));
AppendText3(_T("Converting..."));
/*
* I want to read the source file line by line and when I meet a line with 'TimingPoints' the loop stops.
* szline: read file line by line
* temp: special string for exception of regular options
* aa: not used
*/
CStringW szline = _T("");
CString temp = _T("");
CStringA aa = "";
while (inF.ReadString(szline))
{
AppendText3(szline); // Just debug for what it read
if (szline.Find(_T("Mode:")) != -1) // If it meets a line including 'Mode:' then write 'Mode: 3'
{
temp = _T("Mode: 3");
outF.Write(temp, temp.GetLength() << 1);
outF.Write("\r\n", 2);
}
else // else write what it has read.
{
outF.Write(szline, szline.GetLength() << 1);
outF.Write("\r\n", 2);
}
if (szline.Find(_T("TimingPoints")) != -1) // if it meets 'TimingPoints' then exit the loop.
{
break;
}
}
}
文本文件编码:UTF-8
我想知道,为什么在读取 CString 对象时这一切都变成了乱码?
另外,为什么输出文件有很多多余的空换行符?
此外,我不能让循环结束,因为它找不到“TimingPoints”和“Mode:”关键字。我尝试使用宏将宽字符转换为 UTF-8 字符,但输出文件充满了乱码。CW2A
我想逐行读取输入文件并搜索关键字以进行不同的操作。
答:
0赞
Constantine Georgiou
11/2/2023
#1
由于缺乏适当的功能,您无法真正逐行读取文件:
CStdioFile::ReadString()
两者都需要文件中的 Unicode 内容,并返回一个 Unicode 字符串(假设您使用 Unicode 选项进行编译)。不幸的是,没有读取字符串的重载版本。ReadString()
CStringA
CFile
类没有可以逐行读取文件的函数,该类基本上用于二进制文件 I/O。
我可以想到两种可能的解决方案:
- 每次使用该类读取文件的一部分。您将读取一个缓冲区,并且必须将其转换为宽字符串,并实现自己的缓冲区管理和行分隔。
CFile
- 不要使用 /,而是使用 C++ 类,甚至是 C 函数。
CFile
CStdioFile
评论
0赞
Edward Tsui
11/2/2023
好的,谢谢,我将尝试另一种方式的std::string;w;
评论
inF.ReadString(szline)