[转帖]关于open的"+<"模式

| 1 Comment | 0 TrackBacks | WebBlog Articles

作者:非四。
地址:http://www.1313s.com/f/open.html

描述

很多人知道open除了<, >, >>模式外还有其他模式如"+<", 但有些人不太会用,或者说错误的用了"+<"模式。
一般我们更新文件(需要读取原内容文件)时,都先open<读取再对内容进行变化,最后open>写入。
而用+<加seek可以实现文件的读写更新,不用两次open,从而提高效率。
但值得注意的是:如果不用truncate,文件会出现你所不想要的后果。而另人遗憾的是书中说truncate不是所有平台都支持的。不过就我测试而言,Win2000/XP+Linux下都是可以的。
一切用实验来说话。具体原理可以参考perldoc或书籍。

实验

实验材料:程序目录下有一文本文件1.txt, 里面的内容为简单的“123456789”。
实验一:简单的计数器增加
原代码:


open(FH,"1.txt");
flock(FH, 1);
my $count = <FH>;
close(FH);
$count++;
open(FH,">1.txt");
flock(FH, 2);
print FH $count;
close(FH);

改写后的代码:

open(FH,"+<1.txt");
flock(FH, 2);
my $count = <FH>;
seek(FH,0,0);
print FH ++$count;
close(FH);


简单的从两次open转化为"+<"模式就是这个样子。

实验二:不用truncate的不可意料错误。

这种错误发生在后来写入的长度小于原文件的长度。
比如我们的任务是去掉1.txt中所有的1。如下代码是错误的,出现的结果不是我们想要的。

open(FH,"+<1.txt");
flock(FH, 2);
my $count = <FH>;
$count =~ s/1//sg;
seek(FH,0,0);
print FH $count;
close(FH);

我们所要的结果是23456789,而实际运行后的结果为234567899。后面多了一个9。
"+<"模式是覆盖模式,你后来输入的长度只覆盖那么长,如果原来文件的长度比输入的长度长,后面将会保留。
正确的代码为:

open(FH,"+<1.txt");
flock(FH, 2);
my $count = <FH>;
$count =~ s/1//sg;
seek(FH,0,0);
truncate(FH, 0);
print FH $count;
close(FH);

seek到文件头后将文件清空,再输入改变后的值。
当然有时候是不需要truncate的,看具体的要求具体分析。比如我们就要覆盖那么长后面的就要保留。
比如最上面的$count就不需要,因为加后的count不会小于原来的长度。

题外话

在写本文之前,我在看LeoBBSx的最新版本代码。LeoBBSx有用了+<模式(虽然不是很彻底,只部分采用),但遗憾的是没有truncate。
我没在本地做测试看它会不会出错,但我总觉得奇怪,它用这个模式的时候难道改变后的值都长于原来的值?
或许不用truncate是采用这模式不彻底的原因。

引用通告|TrackBacks (0)

本日志的TrackBack URL: http://easun.org/cgi-bin/mtos/tb_mt_41.pl/21.

本文相关评论|Comments (1)

小骆驼书里面 定长数据库 就是讲的他和pack/unpack的应用~
挺经典的
这篇也是

发表该文评论|Leave a comment

最近发表|Recent Entries

[MT Tips]如何让某个日志在Blog首页固顶?

貌似最简单的办法就是修改日期到一个很遥远的日期,比如 AnySQL 那样:) 但是带来的问题的很多,比如导致Feed阅读器犯糊涂或者影响搜索引擎的收录等等,更糟糕的是对于 日志来说,最主要的就是发布日期。也许大家都已经发现了,我的主页模仿 MT Forum 搞了一个固顶日志(也是为了风格统一)出来,这个固顶日志是后台通过自己设置实现的。是怎么设置的。答案是利用 <mt:Entries> 的tags 功能。 具体概念代码如下:<mt:Entries tag="@top" sort_by="authored_on" sort_order="descend" limit="1" blog_ids="1,5"> dosthing.....</mt:Entries> 这样我们只要要在固定的主题 加上…

北京 Perl Workshop 2008 网站开张 - 接受大会注册,演讲报名

网站开张了, 地址是 http://conference.perlchina.org/bjpw2008/ 由 PerlChina 和 Postgresql China 合办,2008 年 11 月 8 号举行的 Beijing Perl Workshop 是一个免费的 Perl 交流会,向所有对…

好玩的 MT Forum 的按作者归档

Perl Forum 用 MT4 的 MT Forum 的功能搭建起来了好几天了,一直没有发现什么意外,今天突然发现 按作者按月归档 貌似找完了整个发布完的 Perl Forum 也没有找到 link ,查看作者个人信息貌似也没有 link ? 真是好玩的 归档方式。从后台看,给每个用户(作者)都建立了按月的归档页面,估计是为了便于各用户归档自己的文章吧? 后台抓图如下:…