免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 13641 | 回复: 60
打印 上一主题 下一主题

[C] c真的可以直接操作文件吗? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-01-31 15:45 |只看该作者 |倒序浏览
一直觉得C不能直接对磁盘文件操作, 而是把文件全部读到内存理, 操作完成后,
在全部写回磁盘。 可是下面这个程序确实可以工作, 不知道哪位高手知道
其内部的实现思路大概是怎么的?

个人觉得应该是: 读到内存-改-写回内存

bash-3.1$ cat test.txt
This is a test file
for test04.c.


执行下面程序:
#include <stdio.h>

int main(void)
{
&nbsp;&nbsp;&nbsp;&nbsp;char *fname = "test.txt";
&nbsp;&nbsp;&nbsp;&nbsp;FILE *fp;

&nbsp;&nbsp;&nbsp;&nbsp;fp = fopen(fname, "r+");

&nbsp;&nbsp;&nbsp;&nbsp;fseek(fp, 0, SEEK_END);
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;fprintf(fp, "hello, world!\n");
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;return 0;
}


结果:
bash-3.1$ cat test.txt
This is a test file
for test04.c.

hello, world!

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
2 [报告]
发表于 2008-01-31 15:49 |只看该作者
原帖由 sihan 于 2008-1-31 15:45 发表
一直觉得C不能直接对磁盘文件操作, 而是把文件全部读到内存理, 操作完成后,
在全部写回磁盘。 可是下面这个程序确实可以工作, 不知道哪位高手知道
其内部的实现思路大概是怎么的?

个人觉得应该是:  ...

我有一个4g的文件,你的内存够大吗?

论坛徽章:
0
3 [报告]
发表于 2008-01-31 15:52 |只看该作者
文件系统是按块来的吧。

论坛徽章:
0
4 [报告]
发表于 2008-01-31 15:55 |只看该作者
原帖由 sihan 于 2008-1-31 15:45 发表
一直觉得C不能直接对磁盘文件操作, 而是把文件全部读到内存理, 操作完成后,
在全部写回磁盘。 可是下面这个程序确实可以工作, 不知道哪位高手知道
其内部的实现思路大概是怎么的?

个人觉得应该是:  ...

你对C的文件操作理解真有意思, 恐怕你以为这世界上所有语言都是仿JAVA的了.

论坛徽章:
0
5 [报告]
发表于 2008-01-31 16:02 |只看该作者
原帖由 lenovo 于 2008-1-31 15:49 发表

我有一个4g的文件,你的内存够大吗?


原帖由 zszyj 于 2008-1-31 15:55 发表

你对C的文件操作理解真有意思, 恐怕你以为这世界上所有语言都是仿JAVA的了.



那各位的意思是, 直接对磁盘进行操作了?

那如果我想给文件中间插入一段文字, fseek到文件中间, 然后fwrite进入。 这个过程怎么实现的呢?

岂不是要把我的fseek点以后的内容往后移我要fwrite的字节数, 然后在插入? 就好比在数组中间插入?

论坛徽章:
0
6 [报告]
发表于 2008-01-31 16:05 |只看该作者
sihan 说的大致没有错
一般情况下,我们并不能直接对磁盘进行读写操作
事实上,操作系统会维护一个内存区域,这个区域由很多小块内存组成
每一内存小块对应磁盘的一个小单元,比如一个扇区
然后我们对磁盘的所有读写操作,实际上都是对相应的内存镜像的操作
而磁盘与内存镜像之间的同步工作由操作系统完成(即所谓的读磁盘,写磁盘)

当然,这只是大概的一个描述,操作系统对于文件系统的管理
涉及到的磁盘读取,镜像分配,数据定位,文件组织,数据同步有很多复杂的机制跟算法
如果感兴趣,可以找本介绍内核的书,找文件系统相关的章节翻翻

[ 本帖最后由 halve 于 2008-1-31 16:07 编辑 ]

论坛徽章:
0
7 [报告]
发表于 2008-01-31 16:16 |只看该作者
......

[ 本帖最后由 sihan 于 2008-1-31 16:20 编辑 ]

论坛徽章:
0
8 [报告]
发表于 2008-01-31 16:18 |只看该作者
原帖由 halve 于 2008-1-31 16:05 发表
sihan 说的大致没有错
一般情况下,我们并不能直接对磁盘进行读写操作
事实上,操作系统会维护一个内存区域,这个区域由很多小块内存组成
每一内存小块对应磁盘的一个小单元,比如一个扇区
然后我们对磁盘的 ...



我刚问的问题的关键是: fopen("r+"), fseek(), fwrite() 这样的操作确实
可以不自己读文件到内存, 改, 然后写磁盘。

按理说:
fopen() ->open()
fseek() -> lseek()
fwrite() -> write()

照这样看, 那就是说, “读文件到内存, 改, 然后写磁盘”
这一系列操作是由 write保证的, 也就是操作系统保证的 ?
不知道我这样的理解对否?

或者说, write操作没有读文件到内存, 而是直接操作磁盘, 如下图这样:

原文件在磁盘上:
-----------------------------
|file_part1 | file_part2 |
-----------------------------

write插入操作后在磁盘上:
-----------------------------
|file_part1 | file_part2 |
-----------------------------
                / \
               /   \
         ----------------
         |file_part1.5|
         ----------------

论坛徽章:
0
9 [报告]
发表于 2008-01-31 16:23 |只看该作者
原帖由 sihan 于 2008-1-31 16:18 发表



我刚问的问题的关键是: fopen("r+"), fseek(), fwrite() 这样的操作确实
可以不自己读文件到内存, 改, 然后写磁盘。

按理说:
fopen() ->open()
fseek() -> lseek()
fwrite() -> write()

照 ...

你最初的理解是对的,都是先在内存里做了修改再写回磁盘的。
没有直接写磁盘的说法。

[ 本帖最后由 zx_wing 于 2008-1-31 16:24 编辑 ]

论坛徽章:
0
10 [报告]
发表于 2008-01-31 16:29 |只看该作者
对磁盘的操作,都是根据一个最小单位来进行的,比如扇区,一次读取一个扇区,一次更改一个扇区
根据你的流程
open() 得到这个文件磁盘布局的索引信息,即每个位置的数据存在磁盘哪个扇区上
lseek() 得到文件指定位置处数据对应的扇区位置
write() 修改扇区内容
这个过程中,所有的操作都是作用于磁盘的内存镜像
有可能你要修改的扇区并没有对应的内存镜像
这个时候系统会负责将这个扇区读入内存(总的镜像数目有限制,若没有多余空闲区域,系统会释放一个已经不再使用的镜像)
然后你修改这一小块内存之后,系统会在一个合适的时间将这块内存的内容写入扇区
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP