C++ Ifstream从文本文件中读取错误字符

C++ Ifstream从文本文件中读取错误字符,c++,io,C++,Io,我有以下简单代码,将文本文件的内容读入字符数组: const char* name = "test.txt"; std::cout << "Loading file " << name << std::endl; std::ifstream file; file.open(name); file.seekg (0, std::ios::end); int length = file.tellg(); std::cout << "Size: " &l

我有以下简单代码,将文本文件的内容读入字符数组:

const char* name = "test.txt";
std::cout << "Loading file " << name << std::endl;
std::ifstream file;
file.open(name);
file.seekg (0, std::ios::end);
int length = file.tellg();
std::cout << "Size: " << length << " bytes" << std::endl;
file.seekg (0, std::ios::beg);
char* buffer = new char[length];
file.read(buffer,length);
file.close();
std::cout.write(buffer,length);
const char*name=“test.txt”;

std::cout阅读有关打开文件以进行
二进制读取的信息(谷歌或请参阅)。

您可能希望以二进制模式打开文件:

file.open(name, ios_base::in | ios_base::binary);
否则,标准库会为您将每个Windows换行符(CR+LF)转换为单个
\n


这意味着您可以从文件中读取的字符数与文件大小不同。调用
read()
时,它会读取尽可能多的字符。如果它不能读取您请求的字符数,它将设置流的
故障位

您开始使用一些非常错误(但普遍存在)的观点。
file.tellg()
不返回
int
;它返回一个实现 类型为
streampos
的已定义对象,该对象必须是类类型,并且可以 或者可能无法转换为整体类型。如果是的话 可转换为整数类型(我不知道有什么实现 如果没有,即使不是必需的),也不能保证 得到的整数表示的不仅仅是一个神奇的cookie,它 将允许重新搜索到相同的位置

实际上,这在现代机器上可能不是什么大问题:两者都有 Unix和Windows返回文件开头的偏移量(以字节为单位)。 在Unix的情况下,这很好,因为 内部表示与外部表示是一对一的。在这种情况下 对于Windows,有一个行结尾的重新映射:在文本文件中,一行 结尾是一个两字节的0x0D,0x0A序列,读取时变成, 单个字符
'\n'
。和
streampos
(转换为整型) 以字节为单位给出必须在文件中查找的位置的偏移量,而不是 要到达该位置必须读取的字符数。为了东西 就像你看起来在做的一样,这不是问题;分配的 缓冲区可能比需要的大一点,但它永远不会太大 小的

请注意,在大型机上可能不是这样。历史上,在 至少,大型机使用面向块的文件,并且
streampos
可以很容易地分解为字段,并使用 用于块编号的特定位数,以及用于字节的其他位数 块中的偏移量。取决于这些在世界上的布局, 像您这样分配的缓冲区很容易达到几个数量级 太大,或者如果偏移量放在高阶位上,则太小

获得所需缓冲区确切大小的唯一可靠方法是 取决于系统,在某些系统(包括Windows)上,可能存在 除了读取所有字符并计数外,没有其他方法

(要求streampos
为类类型的原因是, 历史上,许多旧的多字节编码都有一个编码状态;您 在不知道字符的情况下无法正确解码字符 因此,要求
streampos
包含两个不同的 信息:要在文件中查找的位置,以及有关 这个状态。我不认为有任何依赖于状态的多字节
不过,现在广泛使用的编码。)

也许您可以使用
readsome
函数,在Windows上查看您实际读取了多少。不一定在其他系统上。