C#文件流定位 C#如何使用Seek在文件任意位置读写

秋雪大大_7338

秋雪大大_7338

2026-02-09

837人浏览

原创

seek方法需配合支持定位的可读写流使用,检查canseek为true后再调用;避免在streamreader/streamwriter中混用seek;大文件优先用memorymappedfile替代。

c#文件流定位 c#如何使用seek在文件任意位置读写

Seek 方法必须配合可读写流使用

直接对 FileStream 调用 Seek 失败,大概率是因为流没以支持定位的模式打开。.NET 中只有打开时指定 FileAccess.ReadWrite 或对应权限,且底层文件句柄支持随机访问(如磁盘文件),CanSeek 才为 true。只用 FileAccess.Read 打开的流,即使物理上可定位,CanSeek 也可能返回 false —— 这是 .NET 的安全限制,不是 bug。

实操建议:

  • new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.None) 显式声明读写权限
  • 调用前务必检查 stream.CanSeek,避免运行时报 NotSupportedException
  • 网络流、加密流(如 CryptoStream)、压缩流(如 GZipStream)通常不支持 Seek,别强行调用

SeekOrigin 的三个取值含义和常见误用

SeekOrigin.BeginSeekOrigin.CurrentSeekOrigin.End 看似简单,但容易在边界计算出错。尤其是 SeekOrigin.End:它把偏移量当作“从末尾往前数”,所以要定位到倒数第 10 字节,得传 -10,而不是 10;若传正数会抛 IOException(“试图访问无效位置”)。

实操建议:

  • stream.Length 获取总长度,再结合 SeekOrigin.Begin 计算更直观,比如跳到第 1024 字节:stream.Seek(1024, SeekOrigin.Begin)
  • 修改当前位置后立即读写,别依赖“上次位置”,Seek 不会自动刷新缓冲区,后续 Read/Write 才真正触发 I/O
  • 向文件末尾追加数据时,不要用 SeekOrigin.End 再写,直接用 FileMode.Append 更安全

Seek 后读写中文或 UTF-8 字符串容易乱码

这是最隐蔽的问题:Seek 操作的是字节偏移,而字符串编码(如 UTF-8)中一个汉字占 2~4 字节。如果用 StreamReader 读文本,它内部有解码缓冲区,Seek 直接跳到中间字节会导致后续 ReadLine 解码失败,抛 ArgumentException(“数据无效”)。

Web3dropper Crypto Price Skill
Web3dropper Crypto Price Skill

用于代理的Billions/Iden3身份认证与身份管理工具,包含链接、证明、签名和验证。

下载

实操建议:

  • 纯文本场景下,避免混合使用 SeekStreamReader/StreamWriter;改用 FileStream + Encoding.GetBytes/GetString 手动处理字节
  • 若必须按行操作,先用 stream.Position 记录每行起始字节位置,Seek 时只跳到这些已知合法位置
  • UTF-8 BOM(EF BB BF)占 3 字节,开头 Seek(0, ...) 是安全的,但 Seek(1, ...) 就可能卡在 BOM 中间

大文件 Seek 性能与内存映射替代方案

对 GB 级文件反复 Seek + 小块读写,性能可能比顺序读还差——因为每次 Seek 触发磁盘寻道,机械硬盘尤其明显。而且 FileStream 默认缓冲区 4KB,小偏移频繁切换位置会让缓存失效。

实操建议:

  • 优先用 MemoryMappedFile 处理超大文件随机访问,它把文件映射到虚拟内存Seek 变成指针运算,无 I/O 开销
  • 若坚持用 FileStream,增大缓冲区(如 64KB),并尽量批量读写,减少 Seek 次数
  • 注意:32 位进程下 Positionlong,但某些旧系统 API 对 >2GB 文件支持不稳,测试时务必覆盖边界值

真正麻烦的从来不是 Seek 本身,而是你假设“文件是个字节数组”却忘了编码、缓冲、硬件寻道这些现实约束。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.03

1518

5

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

2164

5

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

2023.10.24

5684

49

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

2023.11.24

4649

6

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

2024.03.22

6394

16

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

2024.04.29

8454

11

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

2025.07.29

4279

17

c++字符串相关教程
c++字符串相关教程

本专题整合了c++字符串相关教程,阅读专题下面的文章了解更多详细内容。

2025.08.07

4307

13

常用字符串方法大全
常用字符串方法大全

常用字符串方法大全

2025.08.08

2288

14

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Fitten Code官方手册
Fitten Code官方手册

共0课时 | 0人学习

CodeGeex使用手册
CodeGeex使用手册

共0课时 | 0人学习

通义灵码手册
通义灵码手册

共0课时 | 0人学习