我有一个函数来读取一行中的一个变量(整数,双或布尔)的值ifstream
:
template <typename Type>
void readFromFile (ifstream &in, Type &val)
{
string str;
getline (in, str);
stringstream ss(str);
ss >> val;
}
Run Code Online (Sandbox Code Playgroud)
但是,对于在第一行开头插入BOM(字节顺序标记)的编辑器创建的文本文件失败,遗憾的是它包含{Note,Word} pad.如何修改此函数以忽略字节顺序标记(如果存在于开头)str
?
bam*_*s53 13
(我假设你在Windows上,因为在UTF-8文件中使用U + FEFF作为签名主要是Windows的东西,应该在其他地方避免使用)
您可以将文件作为UTF-8文件打开,然后检查第一个字符是否为U + FEFF.您可以通过打开普通的基于char的fstream然后使用wbuffer_convert将其视为另一种编码中的一系列代码单元来完成此操作.VS2010还没有对char32_t的强大支持,所以下面在wchar_t中使用UTF-16.
std::fstream fs(filename);
std::wbuffer_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> wb(fs.rdbuf());
std::wistream is(&wb);
// if you don't do this on the stack remember to destroy the objects in reverse order of creation. is, then wb, then fs.
std::wistream::int_type ch = is.get();
const std::wistream::int_type ZERO_WIDTH_NO_BREAK_SPACE = 0xFEFF
if(ZERO_WIDTH_NO_BREAK_SPACE != ch)
is.putback(ch);
// now the stream can be passed around and used without worrying about the extra character in the stream.
int i;
readFromStream<int>(is,i);
Run Code Online (Sandbox Code Playgroud)
请记住,这应该在整个文件流中完成,而不是在stringstream上的readFromFile中完成,因为只有当它是整个文件中的第一个字符(如果有的话)时才应该忽略U + FEFF.它不应该在其他地方完成.
另一方面,如果你很高兴使用基于字符的流而只是想跳过U + FEFF(如果存在)那么James Kanze的建议似乎很好,所以这是一个实现:
std::fstream fs(filename);
char a,b,c;
a = fs.get();
b = fs.get();
c = fs.get();
if (a != (char)0xEF || b != (char)0xBB || c != (char)0xBF) {
fs.seekg(0);
} else {
std::cerr << "Warning: file contains the so-called 'UTF-8 signature'\n";
}
Run Code Online (Sandbox Code Playgroud)
此外,如果您想在wchar_t
内部使用codecvt_utf8_utf16
,codecvt_utf8
facet有一个可以为您使用"BOM"的模式.唯一的问题是,wchar_t
这些天被广泛认为是毫无价值的*所以你可能不应该这样做.
std::wifstream fin(filename);
fin.imbue(std::locale(fin.getloc(), new std::codecvt_utf8_utf16<wchar_t, 0x10FFFF, std::consume_header));
Run Code Online (Sandbox Code Playgroud)
*wchar_t
是没有价值的,因为它被指定只做一件事; 提供固定大小的数据类型,可以表示区域设置字符库中的任何代码点.它不提供语言环境之间的通用表示(即,相同的wchar_t
值可以是不同语言环境中的不同字符,因此您不一定转换为wchar_t
,切换到另一个语言环境,然后转换回char
以便进行iconv
类似编码转换.)
由于两个原因,固定大小的表示本身毫无价值; 首先,许多代码点具有语义含义,因此理解文本意味着无论如何都必须处理多个代码点.其次,某些平台(如Windows)使用UTF-16作为wchar_t
编码,这意味着单个wchar_t
甚至不一定是代码点值.(使用UTF-16这种方式是否符合标准是不明确的.标准要求语言环境支持的每个字符都可以表示为单个wchar_t
值;如果没有语言环境支持BMP之外的任何字符,则可以看到UTF-16符合要求.)
归档时间: |
|
查看次数: |
7198 次 |
最近记录: |