我正在努力找一堂课阅读和阅读写文件。对于字符串,有两种方式:ANSI和Unicode。 ANSI函数很好,但我的Unicode函数有问题。
有点连线,我可以读取Unicode文件就好了,我的意思是,没有检查或跳过“0xFEFF”的东西。无论我在哪种语言(我试过英语,中文和日语),它都有效。有什么我应该知道的吗?
然后最大的问题就出现了:将Unicode字符串写入文件。首先我尝试简单的英语作为没有'\ n'字符的字母,它确实很好用。然后我按'\ n'进入并且事情开始出错了:输出插入了许多空格,因为“a b c d e f g \ n h i j k l m n \ n o p q r s t \ n u v w x y z”('\ n'可以工作但空间很大)并且文件再次是ANSI。不要问其他语言的字符,我甚至根本不能阅读它们。
所以这就是问题:如何正确地将Unicode字符串写入文件中以及如何操作?请不要提及“_wopen”功能,文件已经用“fopen”功能打开。
答案&建议会非常感激。
我正在使用Windows 7和visual studio。
编辑:它适用于具有以下代码的非英文字符,但仍然错误地使用'\ n'。
char* cStart = "\xff\xfe";
if (::ftell(m_pFile) == 0)
::fwrite(cStart, sizeof(wchar_t), 1, m_pFile);
但是如何运作?我的意思是我在阅读文件时没有看到它。
编辑:我的代码的一部分。
void File::ReadWText(wchar_t* pString, uint32 uLength)
{
wchar_t cLetter = L'\0';
uint32 uIndex = 0;
do {
cLetter = L'\0';
::fread(&cLetter, sizeof(wchar_t), 1, m_pFile);
pString[uIndex] = cLetter;
}while (cLetter != L'\0' && !::feof(m_pFile) && uIndex++ < uLength);
pString[uIndex] = L'\0';
}
void File::WriteWText(wchar_t* pString, uint32 uLength)
{
char* pStart = "\xff\xfe";
if (::ftell(m_pFile) == 0)
::fwrite(pStart, sizeof(wchar_t), 1, m_pFile);
m_uSize += sizeof(wchar_t) * ::fwrite(pString, sizeof(wchar_t), uLength, m_pFile);
}
void main()
{
::File* pFile = new File();
wchar_t* pWString = L"abcdefg\nhijklmn\nopqrst\nuvwxyz";
pFile->Open("TextW.txt", File::Output);
// fopen("TextW.txt", "w");
pFile->WriteWText(pWString, ::wcslen(pWString));
pFile->Close();
}
输出文件的内容是:“abcdefg栀碗樀欀氀洀ഀഀഀഀ瘀瘀瘀礀礀礀”,文件用Unicode。
我不知道它是否是“L'\ n'”的正确表达式,我之前从未使用过Unicode。 谢谢你帮助我:)。
答案 0 :(得分:3)
我刚注意到这个问题被标记为C和C ++:下面是讨论C ++中的情况。它完全忽略了使用,我不知道如何处理不同的编码。
在读取或写入文件时,您需要告诉系统文件的编码是什么,以便在读取时将文件中的字节转换为程序内部的字符,并在写入时将字符转换为字节。在许多情况下,完全忽略此转换,因为从字节到字符的转换是标识:字节可以解释为字符,反之亦然。当外部编码为ASCII时(在我的问题中,这被称为“ANSI”),这是真的。
假装UTF-8编码文件使用标识转换从字节转换为字符工作到某些扩展。 C ++中内部字符表示的原始愿景是每个字符有一个单位,例如一个char
或wchar_t
。尽管Unicode已经制定了一系列可以很好地实现此目标的目标(例如,每个角色由一个单位表示,单位大小为16位),但他们觉得牺牲了所有原始目标,我们最终得到了一个系统其中一个字符(我认为它们实际上称为“代码点”,但我不是Unicode专家)可以由多个单词组成(例如,当使用组合字符时)。在任何情况下,只要个别单位在不注意字符的情况下不会发生变异,通常可以将UTF-8作为char
(例如std::string
)和UTF-的序列进行处理。 16作为wchar_t
的序列(例如std::wstring
)。但是,当读取不同于UTF-8(或UTF-8子集的ASCII)的内容时,您需要小心设置流,以便知道使用了哪种编码。
设置文件流以了解特定编码的标准方法是创建一个合适的std::locale
,其中包含在外部字节和内部字符之间使用其特定的std::codecvt<...>
方面转换编码。如何实际获得相应的std::locale
取决于个人实施。默认转换是为了假装程序使用ASCII的扩展名,该扩展名涵盖char
的所有值。在读写UTF-8时,这应该可行。
我不确定“编写Unicode字符串”是什么意思,但从它的外观来看,你正在编写std::wstring
而没有设置编码。
答案 1 :(得分:2)
使用来源回答编辑过的问题:
void File::ReadWText(wchar_t* pString, uint32 uLength)
是错误的。
如果uLength
是数组的大小(wchar_t string[size]
)
while (.... && uIndex++ < uLength);
应为while (.... && (++uIndex)+1 < uLength);
否则pString[uIndex] = L'\0';
可能会溢出!
新行问题.. L"abcdefg\nhijklmn\nopqrst\nuvwxyz";
windows使用\r\n
作为新行。 L"abcdefg\r\nhijklmn\r\nopqrst\r\nuvwxyz";
应该有用。
基于此msdn-thread unicode newline problem
和您的// fopen("TextW.txt", "w");
,我相信您必须使用"wb"
打开文件!
否则\n
将自动扩展为\r\n
,这会阻碍您的unicode编码..
答案 2 :(得分:1)
嗯这可能会有所帮助..
不要忘记在FF FE
开头写BOM。
因为您还没有发布任何代码..
我相信你把新行写成ASCII '\n'
(如你的问题中所写)
对于新行,您需要撰写0D 00 0A 00
或者如果您想使用'\n'
,则必须将其(short)'\n'