You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

seekg()和seekp()操作的是字符还是字节?测试与文档矛盾解析

seekg()与seekp():到底操作字节还是字符?

问题背景

《Programming: Principles and Practice》第393页对文件定位函数的示例代码注释称,seek()(实际应为seekg()/seekp())的位置参数按字符计数(比如位置5对应第6个字符)。但实际测试中发现并非如此:

若确有需要,可使用定位功能选择文件中特定位置进行读写。基本而言,每个打开的读文件有一个“读位置”,每个打开的写文件有一个“写位置”:
[示意图]

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 

用户创建了包含单个宽字符的wide.txt文件,运行以下测试代码:

#include "../std_lib_facilities.h"

int main() {
    fstream fs {"wide.txt"};
    fs.seekp(1);
    fs << 'y';
    fs.close();
    return 0;
}

运行后wide.txt变为�y�,说明'y'被写入了第2个字节位置,而非第2个字符位置。这与部分资料中“按字符计数”的描述产生矛盾。

核心结论

seekg()(读定位)和seekp()(写定位)的偏移参数本质是字节数,而非字符数,除非满足以下特殊场景:

  • 使用窄字符流(默认的char类型流);
  • 文件采用的编码中每个字符恰好占用1字节(比如ASCII、ISO-8859-1等单字节编码)。

此时字节数与字符数相等,才会出现“按字符计数”的表象。

矛盾产生的原因

  1. 书籍的简化教学表述:
    书中示例针对的是窄字符场景,作者为了降低初学者的理解门槛,直接将“字节偏移”简化描述为“字符位置”,忽略了多字节编码的复杂情况。

  2. 部分资料的表述歧义:
    很多资料在讨论seekg()/seekp()时,默认假设用户使用的是单字节编码的窄字符流,因此采用了“按字符计数”的简化说法,没有明确说明多字节编码下的差异。

  3. 宽字符流的编码特性:
    宽字符(如wchar_t)在文件中通常以多字节编码存储(比如UTF-16、UTF-32),单个宽字符占用2或4字节。此时seekp(1)定位的是第2个字节,而非第2个字符,写入单字节的'y'会破坏宽字符的编码结构,导致乱码。

内容的提问来源于stack exchange,提问作者user51462

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 00:53:17