0

0

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

畫卷琴夢

畫卷琴夢

发布时间:2026-02-09 08:29:18

|

797人浏览过

|

来源于php中文网

原创

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(“数据无效”)。

情感家园企业站5.0 多语言多风格版
情感家园企业站5.0 多语言多风格版

一套面向小企业用户的企业网站程序!功能简单,操作简单。实现了小企业网站的很多实用的功能,如文章新闻模块、图片展示、产品列表以及小型的下载功能,还同时增加了邮件订阅等相应模块。公告,友情链接等这些通用功能本程序也同样都集成了!同时本程序引入了模块功能,只要在系统默认模板上创建模块,可以在任何一个语言环境(或任意风格)的适当位置进行使用!

下载

实操建议:

  • 纯文本场景下,避免混合使用 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 本身,而是你假设“文件是个字节数组”却忘了编码、缓冲、硬件寻道这些现实约束。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

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

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

444

2023.08.03

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

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

213

2023.09.04

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

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

1517

2023.10.24

字符串介绍
字符串介绍

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

634

2023.11.24

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

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

800

2024.03.22

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

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

772

2024.04.29

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

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

181

2025.07.29

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

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

86

2025.08.07

Golang处理数据库错误教程合集
Golang处理数据库错误教程合集

本专题整合了Golang数据库错误处理方法、技巧、管理策略相关内容,阅读专题下面的文章了解更多详细内容。

67

2026.02.06

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Rust 教程
Rust 教程

共28课时 | 5.6万人学习

Git 教程
Git 教程

共21课时 | 3.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号