c++ `seekg()`和`seekp()`是对字符还是字节进行操作?

m1m5dgzv  于 2023-05-20  发布在  其他
关注(0)|答案(2)|浏览(144)

第393页 '编程:Principles and Practice’ 介绍seekg()seekp()如下:
但是,如果必须,可以使用定位来选择文件中的特定位置进行阅读或写入。基本上,每个打开阅读的文件都有一个“读取/获取位置”,每个打开写入的文件都有一个“写入/放置位置”:
[图解]

fstream fs {name};          // open for input and output
if (!fs) error("can't open ", name);

fs.seek(5);                 // move reading position to the 5 (the 6th character)
char ch;
fs >> ch;                   // read and increment reading position
cout << "character[5] is " << ch << ' {' << int(ch) << "}\n";

fs.seekp(1);                // move writing position to 1
fs << 'y';                  // write and increment writing position

在代码片段中,“位置”用字符来表示,例如位置5被称为“第6个字符”。这让我很困惑,因为在此之前,我们一直认为文件是一个字节序列,所以我希望位置可以用 bytes 表示(在上面的例子中,我认为5是文件第6个字节的位置)。
因此,我尝试通过写入包含单个宽字符的文件的位置1来测试它:

wide.txt

test.cpp

#include "../std_lib_facilities.h"

int main() {

    fstream fs {"wide.txt"};

    fs.seekp(1);
    fs << 'y';
    fs.close();

    return 0;

}

运行此代码后,wide.txt看起来像这样:

�y�

看起来字符'y'被写入程序的第二个字节,而不是第二个字符,这意味着位置引用的是一个字节,而不是一个字符。那么,为什么书中的代码片段说“字符”?
我还注意到函数签名是basic_ostream& seekp( pos_type pos );(参见CPP Reference),但我找不到pos_type是指字符还是字节的解释。
cplusplus.com上的引用似乎也是用字符来定义位置的(强调是添加的):
设置下一个字符插入输出流的位置。
就像Reddit上的comment一样(强调添加):
一个streampos不是一个整数,**它不是流中的某个字节位置。它表示流中的一个字符位置,**类型保存一些流状态信息,用于代码转换和字符位置。
但这似乎与我在示例中看到的相矛盾,其中fs.seekp(1)似乎覆盖了字节1(第2个字节)。

xqnpmsa8

xqnpmsa81#

seekg()seekp()是对字符还是字节进行操作?
seek*函数的上下文中,它们是同一个东西--它与graphemes, grapheme-like units or symbols中的可见(或不可见)字符只有非常松散的关系。
对于编码,如UTF8,步进 “一个字符” 将需要澄清。seek*字符不考虑代码点,因此步进一个seek*-字符可能会将r/w指针定位在4个八位字节长的unicode字符内的某个位置,并且从/向那里阅读或写入可能会导致无效的代码点-或一些意外的字素。

tmb3ates

tmb3ates2#

seekg()seekp()是对字符还是字节进行操作?
两个都是?
为什么书中的代码片段说“字符”?
char是字符。它代表一个字节。在这种情况下,它们是相同的。
还有wfstream。它对 * 宽 * 字符进行操作。这些字符采用一个wchar_t类型编码的多个字节。
pos_type是指字符还是字节。
这一切都是抽象的。这取决于流引用的内容。在fstream的情况下,一个字符是一个char,它是一个字节。在wfstream的情况下,字符具有sizeof(wchar_t)字节。在我想象的typedef basic_ios<__uint128_t> my_super_stream_with_16_bytes_characters;中,一个字符有16个字节。
这与我在示例中看到的情况相反,其中fs.seekp(1)似乎覆盖了字节1
不,在本例中,只有fs * 指的是一个字符代表一个字节的流(在您的操作系统和实现上)。

相关问题