您正在从Perl 5.38.0查看此文档的版本。查看最新版本
Tie::File—通过Perl数组访问磁盘文件的行
使用Tie::File;tie@array,'tie::File',filename或die。。。;$array[0]=“废话”;#文件的第一行现在是“废话”#(行号从0开始)打印$array[42];#文件的显示行43$n_recs=数组;#档案里有多少记录?$#数组-=2;#从末尾剪下两张唱片for(@array){s/PERL/PERL/g;#在文件中的所有位置用PERL替换PERL}#这些就像常规的推、弹出、取消移动、移动和拼接#除了他们以您期望的方式修改文件之外push@array,新记录。。。;我的$r1=pop@array;unshift@array,新记录。。。;我的$r2=shift@array;@old_recs=splice@array,3,7,新记录。。。;解开@array;#全部完成
领带::文件
将常规文本文件表示为Perl数组。数组中的每个元素都对应于文件中的一条记录。文件的第一行是数组的元素0;第二行是元素1,依此类推。
文件是不加载到内存中,所以即使是巨大的文件也可以使用。
对数组的更改会立即反映在文件中。
懒惰的人和初学者现在可能会停止阅读手册。
什么是“记录”?默认情况下,其含义与<...>
操作符:它是以结尾的字符串$/
,这可能是“\n”
.(小异常:在DOS和Win32系统上,“记录”是以“\r\n”
.)您可以通过提供记录
中的选项领带
呼叫:
tie@array,'tie::File',$File,recsep=>'es';
这表示记录由字符串分隔锿
。如果文件包含以下数据:
诅咒这些讨厌的苍蝇!\n个
然后@阵列
看起来有四个要素:
“诅咒”“e p”“ky-fli”“!\n”
不允许将未定义的值用作记录分隔符。Perl的特殊“段落模式”语义(a la$/ = ""
)未仿真。
从绑定数组读取的记录末尾没有记录分隔符字符串;这是为了允许
$数组[17].=“额外”;
按预期工作。
(请参见“自动转换器”,见下文。)存储在数组中的记录在写入文件之前将附加记录分隔符字符串(如果它们还没有)。例如,如果记录分隔符字符串是“\n”
,则以下两行执行完全相同的操作:
$array[17]=“樱桃派”;$array[17]=“樱桃派\n”;
结果是,文件第17行的内容将被替换为“樱桃派”;换行符将第17行与第18行分隔开。这意味着此代码将不执行任何操作:
chomp$array[17];
因为咀嚼
ed值将在写回文件时重新附加分隔符。无法创建缺少尾部记录分隔符字符串的文件。
插入符合以下条件的记录包含此模块不支持记录分隔符字符串。它可能会产生一个合理的结果,但这个结果在未来的版本中可能会有所改变。使用“splice”插入记录或将一条记录替换为多条记录。
#自动测深仪
通常,数组元素会删除记录分隔符,这样,如果文件包含文本
黄金乳香没药
绑定数组将包含(“金”、“乳香”、“没药”)
。如果您设置自动测深仪
如果值为false,则不会删除记录分隔符。如果上面的文件与
tie@givents,“tie::File”,$givents、autochomp=>0;
然后是数组@礼物
似乎包含(“黄金”、“乳香”、“没药”)
、或(在Win32系统上)(“黄金”,“乳香”,“没药”)
.
通常,指定的文件将被打开以进行读写访问,如果不存在,则将创建该文件。(也就是说,旗帜O_RDWR|O_CREAT(_RDWR)
在中提供打开
呼叫)如果要更改此设置,可以在模式
选项。请参见Fcntl公司获取可用标志的列表。例如:
#打开文件(如果存在),但如果不存在则失败使用Fcntl“O_RDWR”;tie@array,'tie::File',$File,mode=>O_RDWR;#如果文件不存在,则创建该文件使用Fcntl'O_RDWR','O_CREAT';tie@array,'tie::File',$File,mode=>O_RDWR|O_CREAT;#以只读模式打开现有文件使用Fcntl“O_RDONLY”;tie@array,'tie::File',$File,mode=>O_RDONLY;
不支持以只读或追加模式打开数据文件。
这是内存量的上限领带::文件
将在管理文件时随时使用。这用于两件事:管理读缓存以及管理延迟写入缓冲区.
从文件中读入的记录被缓存,以避免重复地重新读取它们。如果将同一记录读取两次,第一次将其存储在内存中,第二次将从读缓存。读缓存中的数据量不会超过指定的值记忆
.如果领带::文件
想要缓存一条新记录,但读缓存已满,它将通过使读缓存中最近访问过的记录过期来腾出空间。
默认内存限制为2Mib。您可以通过提供记忆
选项。参数是所需的缓存大小,以字节为单位。
#我有很多内存,所以使用大缓存来加快访问速度tie@array,'tie::File',$File,memory=>20_000_000;
将内存限制设置为0将禁止缓存;每次检查记录时,都会从磁盘中提取记录。
这个记忆
值不是所用内存的绝对或精确限制。领带::文件
除了读缓存和延迟写缓冲区之外,对象还包含一些结构,这些结构的大小不受影响记忆
.
缓存本身会为每个缓存的记录消耗大约310个字节,因此,如果您的文件有许多短记录,您可能需要降低缓存内存限制,否则缓存开销可能会超过缓存数据的大小。
#dw_size(数据_大小)
(这是一项高级功能。第一次阅读时跳过本节。)
如果您使用延期书写(请参阅“延迟写入”,如下所示),则写入数组的数据不会直接写入文件;相反,它将保存在延迟写入缓冲区稍后写出。延迟写入缓冲区中的数据也会根据使用记忆
选项。
您可以设置dw_size(数据_大小)
选项来限制可以保存在延迟写入缓冲区中的数据量。此限制不能超过总内存限制。例如,如果您设置dw_size(数据_大小)
至1000和记忆
到2500,这意味着将保存不超过1000个字节的延迟写入。读缓存的可用空间会有所不同,但它将始终至少为1500字节(如果延迟写入缓冲区已满),并且可能会增长到2500字节(如果推迟写入缓冲区为空)
如果您没有指定dw_size(数据_大小)
,默认为整个内存限制。
-模式
是的同义词模式
.-记录
是的同义词记录
.-存储器
是的同义词记忆
你明白了。
#公共方法
这个领带
调用返回一个对象,比如0美元
。你可以打电话
$rec=$o->FETCH($n);$o->STORE($n,$rec);
在第行提取或存储记录n美元
分别为;与其他绑定数组方法类似。(请参见珍珠岩详细信息。)您也可以在此对象上调用以下方法:
#一大群
$o->flock(模式)
将锁定绑定文件。模式
与Perl内置的第二个参数的含义相同一大群
功能;例如锁定_SH
或LOCK_EX |锁_NB
.(这些常数由使用Fcntl“:flock”
声明。)
模式
可选;默认值为锁定_执行
.
领带::文件
维护文件中每个记录的字节偏移量的内部表。
当您使用一大群
锁定文件,领带::文件
假设读缓存不再可信,因为自上次读取文件以来,另一个进程可能已经修改了该文件。因此,成功呼叫一大群
丢弃读缓存和内部记录偏移量表的内容。
领带::文件
承诺以下操作顺序是安全的:
my$o=tie@array,“tie::File”,$filename;$o->羊群;
特别地,领带::文件
将不在领带
呼叫。(例外:使用模式=>O_TRUNC
当然,会在领带
呼叫。如果要安全地执行此操作,请在不使用O_TRUNC(_TRUNC)
,锁定文件,然后使用@数组=()
.)
解锁文件的最佳方法是放弃对象并解开数组。在不解除文件锁定的情况下解除文件锁定可能是不安全的,因为如果这样做,对象中的更改可能仍然是未写入的。这就是为什么没有解锁的捷径。如果你真的想过早解锁文件,你知道该怎么做;如果你不知道该做什么,那就不要做。
关于文件锁定的所有常见警告都适用于此。特别要注意,Perl中的文件锁定是咨询的,这意味着持有锁不会阻止其他人读取、写入或擦除文件;这只会防止他们同时获得另一个锁。锁类似于绿色交通灯:如果你有一个绿灯,那并不能阻止从另一个方向过来的白痴从侧面撞到你;它只是向你保证,这个白痴不会同时也有绿灯。
#自动测深仪
我的$old_value=$o->autochomp(0);#禁用autochomp选项我的$old_value=$o->autochomp(1);#启用自动检测选项我的$ac=$o->autochomp();#恢复当前值
请参见“自动转换器”,如上所示。
#推迟
,脸红
,丢弃
、和自动推迟
请参见“延迟写入”,如下所示。
$off=$o->偏移量($n);
此方法返回n美元
文件中的第条记录。如果没有这样的记录,则返回未定义的值。
#绑定到已打开的文件句柄
如果美元每小时
是文件句柄,例如由IO::文件
或者其中一个IO(输入输出)
模块,您可以使用:
tie@array,“tie::File”,$fh。。。;
同样,如果你打开那个把手FH公司
有规律的打开
或系统打开
,您可以使用:
tie@array,'tie::File',\*FH。。。;
以只读方式打开的句柄将不起作用。只要您不尝试修改数组,以只读方式开启的句柄将起作用。句柄必须连接到可查找的数据源,这意味着没有管道或套接字。如果领带::文件
可以检测到您提供了一个无法识别的句柄领带
调用将引发异常。(在Unix系统上,它可以检测到这一点。)
请注意,Tie::File将只关闭它在内部打开的所有文件句柄。如果如上所述传递给它一个文件句柄,则您“拥有”该文件句柄,并负责在解开@数组后将其关闭。
并列::文件调用双模
在内部打开的文件句柄上,但不在用户传入的文件句柄中。为了一致性,特别是在跨平台使用绑定文件时,您可能希望调用双模
在绑定文件之前在文件句柄上。
#延迟写入
(这是一项高级功能。第一次阅读时跳过本节。)
通常,修改领带::文件
数组立即写入基础文件。每个作业都像$a[3]=。。。
根据需要重写尽可能多的文件;通常,从第3行到末尾的所有内容都需要重写。这是最简单、最透明的行为。即使对于大型文件,性能也相当好。
然而,在某些情况下,这种行为可能过于缓慢。例如,假设您有一个百万记录文件,并且您希望:
for(@FILE){$_ = "> $_";}
第一次循环时,您将重写整个文件,从第0行到末尾。第二次循环时,您将从第1行到末尾重写整个文件。第三次循环时,您将把整个文件从第2行重写到末尾。等等。
如果这种情况下的表现不可接受,您可以推迟实际写作,然后立即全部完成。以下循环将对大文件执行更好的操作:
(并列@a)->推迟;对于(@a){$_ = "> $_";}(捆扎@a)->齐平;
如果领带::文件
的内存限制足够大,所有写操作都将在内存中完成。然后,当你打电话时->冲洗
,整个文件将在一次传递中被重写。
(实际上,前面的讨论有点像小谎。在这种常见情况下,您不需要启用延迟写入来获得良好的性能,因为领带::文件
将自动为您执行此操作,除非您明确告知不要执行此操作。请参阅“自动延迟”,见下文。)
打电话->冲洗
将数组返回到立即写入模式。如果您希望放弃延迟写入,可以调用->丢弃
而不是->冲洗
。请注意,在某些情况下,某些数据可能已经写入,但为时已晚->丢弃
放弃所有更改。支持->丢弃
可能在未来版本的领带::文件
.
延迟写入缓存在内存中,上限由dw_size(数据_大小)
选项(见上文)。如果延迟写入缓冲区已满,并且您尝试写入更多延迟数据,则缓冲区将被刷新。所有缓冲的数据都将立即写入,缓冲区将被清空,现在空的空间将用于未来的延迟写入。
如果延迟写入缓冲区尚未满,但缓冲区和读缓存的总大小将超过记忆
限制,最旧的记录将从读缓存中过期,直到总大小低于限制。
推
,流行音乐
,转移
,取消移位
、和剪接
无法延迟。当您执行其中一个操作时,任何延迟的数据都会写入文件,并立即执行该操作。在未来版本中,这可能会发生变化。
如果在启用延迟写入的情况下调整数组大小,则会立即调整文件大小,但不会写入延迟记录。这有一个令人惊讶的结果:@a=(…)
立即擦除文件,但延迟写入实际数据。这可能是一个错误。如果它是一个错误,将在未来版本中修复。
#自动探索
领带::文件
尝试猜测延迟写什么时候可能有用,并自动打开和关闭。
对于(@a){$_ = "> $_";}
在这个例子中,只有前两个作业会立即完成;在此之后,对文件的所有更改都将延迟到用户指定的内存限制。
通常,您应该可以忽略这一点,只使用模块而不考虑延迟。但是,特殊应用程序可能需要对哪些写入被延迟进行精细控制,或者可能需要立即执行所有写入。要禁用自动防御功能,请使用
(绑定@o)->自动防御(0);
或
tie@array,'tie::File',$File,autodefer=>0;
同样,->自动导向(1)
重新启用自动防御,以及->自动防御()
恢复自动防御设置的当前值。
#并发访问文件
如果希望从多个进程同时访问同一文件,则缓存和延迟写入是不合适的。此模块内部执行的其他优化也与并发访问不兼容。此模块的未来版本将支持并发=>1
启用安全并发访问的选项。
本文档的早期版本建议使用内存=>0
以实现安全的并发访问。这是错误的。在0.96之前,文件将不支持安全并发访问。
#CAVEATS(洞穴)
(这是拉丁文中的“警告”。)
我们做出了合理的努力来提高该模块的效率。然而,更改大文件中间记录的大小总是相当缓慢的,因为必须移动新记录之后的所有内容。
绑定数组的行为与常规数组的行为并不完全相同。例如:
#这确实印有“多么不寻常!”undef$a[10];如果定义了$a[10],则打印“多么不寻常!\n”;
未定义
-正在执行领带::文件
数组元素只清空文件中相应的记录。当你再次阅读它时,你会得到空字符串,所以应该是-未定义
将定义'ed值。同样,如果你有自动测深仪
禁用,然后
#如果'autochomp'被禁用,则会打印“How uncemple!”undef$a[10];如果$a[10];则打印“多不寻常!\n”;
因为什么时候自动测深仪
已禁用,$10]美元
将读回为“\n”
(或记录分隔符字符串是什么。)
还有其他细微差异,特别是在存在
和删除
,但总的来说,通信非常紧密。
我认为,由于该模块与文件I/O有关,因此几乎所有正常使用该模块的情况都会受到严重的I/O限制。这意味着,在模块内维护复杂数据结构的时间将被实际执行I/O的时间所支配。当有机会花费CPU时间来避免执行I/O时,我通常会尝试利用它。
您可能会认为延迟编写就像事务一样脸红
作为犯罪
和丢弃
作为回降
,但它不是,所以不要。
每个记录偏移量和每个缓存项都有很大的内存开销:每个缓存数据记录大约310字节,每个偏移表项大约21字节。
每记录开销将限制每个文件可以访问的最大记录数。请注意访问阵列通孔的长度$x=标量@tied_file
访问全部的记录并存储其偏移量。同样适用于foreach(@tied_file)
,即使您提前退出循环。
#子分类
这个版本绝对不承诺任何关于内部的内容,这些内容可能会发生更改,恕不另行通知。该模块的未来版本将具有定义良好且稳定的子类化API。
#怎么样DB_文件
?
人们有时会指出DB_文件会做类似的事情,并询问原因领带::文件
模块是必需的。
您可能会喜欢以下几个原因领带::文件
。列表位于http://perl.plover.com/TieFile/why-not-DB_File文件
.
马克·杰森·多明斯
要联系作者,请发送电子邮件至:mjd-perl-tiefile+@plover.com
要在发布此模块的新版本时接收公告,请发送空白电子邮件至mjd-perl-tiefile-subscribe@plover.com
.
本模块的最新版本,包括文档和任何重要新闻,将在
http://perl.plover.com/TieFile/
#许可证
领带::文件
0.96版版权所有(C)2003 Mark Jason Dominus。
这个库是自由软件;您可以重新发布它和/或使用与Perl本身相同的条款对其进行修改。
这些术语是您选择的(1)Perl艺术许可证,或(2)自由软件基金会发布的GNU通用公共许可证第2版,或(3)GNU通用公共许可证的任何后续版本。
本库的发行是为了希望它有用,但没有任何保证;甚至没有适销性或特定用途适用性的暗示保证。有关更多详细信息,请参阅GNU通用公共许可证。
您应该已经收到GNU通用公共许可证的副本以及此库程序;它应该在档案里复制
如果没有,请写信给美国马萨诸塞州波士顿富兰克林街51号五楼自由软件基金会,邮编:02110-1301
有关许可查询,请联系作者:
马克·杰森·多明斯华诺克南街255号。宾夕法尼亚州费城,邮编:19107
领带::文件
版本0.98附带绝对无担保。有关详细信息,请参阅许可证。
非常感谢Jarkko Hietaniemi,感谢他在我还没有写这本书的时候就同意把它放在核心位置,感谢他总体上的帮助、支持和胜任。(通常规则是“任选一个”。)同样要感谢阿比吉特·梅隆森(Abhijit Menon-Sen)所做的一切。
特别感谢Craig Berry和Peter Prymmer(负责VMS可移植性帮助)、Randy Kobes(负责Win32可移植性协助)、Clinton Pierce和Autrijus Tang(负责超出职责范围的英勇的11小时Win32测试)、Michael G Schwern(负责测试建议)和其他CPAN测试人员(通常用于测试)。
特别感谢Tels提出了一些速度和内存优化建议。
更多感谢:爱德华·阿维斯/马蒂亚·巴本/汤姆·克里斯蒂安森/杰里特·哈斯/古鲁萨米·萨拉西/贾科·希塔尼米(再次)/尼古拉·克内泽维奇/约翰·科米内茨/尼克·英·西蒙斯/塔西洛·冯·帕塞瓦尔/H.迪特尔·皮尔西/斯拉文·雷齐克/埃里克·鲁德/彼得·斯科特/彼得·索姆/奥特里朱斯·唐(再次)/Tels(再次)/Juerd Waalboer/托德·里纳尔多
#TODO公司
更多测试。(我还没想到的东西。)
段落模式?
固定长度模式。Leave-blanks模式。
也许是自动锁定模式?
对于该模块的许多常见用途,读缓存是一项责任。例如,插入单个记录或扫描一次文件的程序的缓存命中率为零。这意味着一个主要的优化:缓存最初应该被禁用。这里有一种混合方法:最初,缓存是禁用的,但缓存代码维护了有关启用缓存后命中率会有多高的统计信息。当它看到命中率足够高时,它就会启用自己。此代码中的STAT注释是此实现的开始。
用fcntl()锁定记录?然后,该模块可能支持撤消日志并获取实际事务。这将是一次多么令人沮丧的旅行。
跟踪缓存的最高记录。这将允许行中读取更快地跳过缓存查找(如果从1..N开始读取时缓存为空,则最后缓存的值始终为N-1)。
更多测试。