我想学习如何使用ColdFusion中的CFFILE标签来读取文本文件的内容。在我的例子中,该文本文件是FFMpeg在对媒体文件进行转码时生成的进度日志。我想编写一个ColdFusion脚本,它将定期轮询进度日志,直到日志指示FFMpeg已完成其转码操作。在客户端,我可以使用Ajax命中ColdFusion脚本,并在FFMpeg完成工作时向用户显示“完成百分比”。
我通过使用FFMpeg最近版本支持的新“progress”标志来获取FFMpeg来生成日志文件。下面我将向您展示使用此标志的方式,以及日志文件中生成的输出。
这是FFMpeg命令:
ffmpeg -i c:\my_original_file.ogg c:\my_converted_file.mp3 -progress c:\my_progress.txt
上述命令将导致FFMpeg生成名为my_progress.txt的日志文件。
以下是它在日志文件中生成的内容:
total_size=206150
out_time_ms=51410044
out_time=00:00:51.410044
dup_frames=0
drop_frames=0
progress=continue
以上6行是在日志文件中重复生成的,值越来越大。
total_size=206150
out_time_ms=51410044
out_time=00:00:51.410044
dup_frames=0
drop_frames=0
progress=continue
total_size=412413
out_time_ms=102975756
out_time=00:01:42.975756
dup_frames=0
drop_frames=0
progress=continue
total_size=618363
out_time_ms=154463111
out_time=00:02:34.463111
dup_frames=0
drop_frames=0
progress=continue
total_size=824939
out_time_ms=206107189
out_time=00:03:26.107189
dup_frames=0
drop_frames=0
progress=continue
最后,当作业完成时,最后6行的块是日志文件中的最后一行。注意最后一行的“progress = end”:
total_size=9725902
out_time_ms=2431348011
out_time=00:40:31.348011
dup_frames=0
drop_frames=0
progress=end
我想使用CFFILE标记编写一个Coldfusion脚本来读取文件的最后6行(无论文件有多大),并且每次都要执行此操作由浏览器通过Ajax调用。最后,我需要将这些行上的值解析为变量,这样我就可以将一些数据返回给调用者。
我已经研究过FFMpeg的进度条但是它们在PHP中对我来说很难,而且,它们解析了FFMpeg日志文件的旧格式化版本,我想使用上面更新的格式。有人可以帮忙吗?
答案 0 :(得分:2)
要获得最后六行tail会更快,因为它向后工作并且只加载你要求的内容(而不是读取整个文件然后循环遍历它)。无论文件大小如何,它显然也会使用更少的内存。
<cfexecute
name = "tail"
arguments = "--lines=6 #Filename#"
timeout = 30
variable = "LastSixLines"
/>
<cfset Data = {} />
<cfloop index="CurLine" array=#LastSixLines.trim().split('\n')# >
<cfset Data[ListFirst(CurLine,'=')] = ListRest(CurLine,'=') />
</cfloop>
由于您似乎在Windows上,您可能需要安装tail(它已预先安装用于Linux和MacOS)。获得它的最简单的选择是MSYS,你可能已经拥有它取决于你使用的其他软件 - 例如,Git for Windows使用MSYS,并且在bin文件夹中有tail.exe。
在这种情况下,上面的第二行改为:
name = "C:/Program Files/Git/bin/tail"
如果您需要代码在多个系统上工作,您可以将该部分变为变量(或将相应的目录放在系统PATH上,以便可以从任何地方调用它)。
答案 1 :(得分:0)
这将读取您的文件并创建一个包含最后6行的结构。
<cffile action="read" file="myfile.txt" variable="myfile">
<cfoutput>
<cfset linecount = listlen(myfile,chr(10))>
#linecount# lines
<cfset count = 0>
<cfset stData = {}>
<cfloop list="#myfile#" index="i" delimiters="#chr(10)#">
<cfset count++>
<cfif count GT linecount - 6><!--- we only care about the last 6 lines --->
#i#<Br>
<cfset stData[listfirst(i,'=')] = listlast(i,'=')><!--- add data to stData --->
</cfif>
</cfloop>
</cfoutput>
<cfdump var="#stData#">
上面的代码将从文本文件中输出原始数据,并根据作为分隔符的=
创建结构
您还可以将文件存储到数组中,然后像这样拉出最后6行。对于较小的文件(&lt; 200k行),此选项的速度约为2倍,但随着文件大小的增加,两个选项几乎相同,然后第一个选项在大约1M行变得更快
<cffile action="read" file="c:\ColdFusion10\cfusion\wwwroot\myfile.txt" variable="myfile">
<cfset filearray = listToArray(myfile,chr(10))>
<cfset linecount = arrayLen(filearray)>
<cfset stData = {}>
<cfloop from="0" to="5" index="i">
<cfset stData[listfirst(filearray[linecount - i],'=')] = listlast(filearray[linecount - i],'=')>
</cfloop>