[已解决]大量文本约250w行如何短时间快速整理每30行保留一行数据?
本帖最后由 user11 于 2012-7-5 09:47 编辑最近做试验,结果设置参数的时候欠缺考虑,设置数据采集时间为1s一次,试验进行了一个月结束,麻烦来了
由于采样时间太短,生成的数据大约有259W行,文本太大有二三百兆没法处理了,
excel origin 打开就死掉,其实30s取样一次就可以了,自己用AU3写了个程序,精简数据。
前7行是固定格式的文件头,不需要精简,第八行以后是数据文本,每30行保留一行即可,
但是这个处理速度太慢,已经5、6个小时了还没搞定一个数据,求助如何提高效率~~{:face (396):}
非常感谢A版,问题完美解决,正则太神奇了,方法看楼下A版的神作!!实例22楼!
回复的朋友,非常感谢你们的想法和意见!!tryhi、lixiaolong的正则应该也可以用,
但是A版真是细心,给了直接可以用的,改都不用改,Qokelate考虑的确很周全!
#include <File.au3>
Dim $i=1
$aFile = FileOpenDialog("快速精简行",@ScriptDir&"\","文本文件 (*.txt;*.dic)", 1 + 4)
If @error Then
MsgBox(0,0,"文件未选择",3)
Exit
EndIf
$file=FileOpen($aFile)
$out_file=StringTrimRight($aFile,4)&'_已完成.txt'
if FileExists($out_file) then FileDelete($out_file)
FileOpen ($out_file,2)
While 1
$line = FileReadLine ($file,$i)
If @error = -1 Then ExitLoop
TrayTip("正在处理","行:"&$i,2,1)
FileWriteLine($out_file, $line)
if $i<7 then
$i=$i+1
else
$i=$i+30
endif
WEnd
打开/编辑超大文件(G级)的,是很大的课题的
不过你的文件还不算大,不过建议你用一些现成的Editor干这种事,如专门对超大文件有优化的EmEditor,UE等。它们都会自动判断硬件资源和部分读文件入内存处理,而不是全部读文件入内存的。
可惜的是au3不能支持Hash表,不然做这种事要快很多很多。也只好用Assign,Eval ,IsDeclared这种表驱动方式来模拟Hash表。 UE之类我当然知道,,关键我要精简一下数据,,不会正则,UE不熟悉,不只能能不能按行精简下来 回复 3# user11
就是不用这些,你在用FileReadLine之前,先用FileSetPo或_WinAPI_SetFilePointer效率也应该提高好多 回复 4# happytc
印象里filesetpos好像不支持行,忘了 用正则吧,应该就是几秒钟的事,现在没时间,晚上来试下~ 回复 5# netegg
对,肯定不能直接支持了,au3里所有默认的所谓‘行’的操作,其在用C++写的时候,其实也就是搜@LF后,得到偏移量(OffSet)后移动指针而已。 回复 6# afan
正则可以几秒钟,,这个厉害,,不懂正则,这个很需要,,期待A版 的大作! 本帖最后由 tryhi 于 2012-7-4 17:32 编辑
### 友情提示:本脚本由 Au3.REHelper 于 2012/07/04 17:28 自动生成,不保证其正确性,请自行测试 ###
#include <Array.au3>
Local $Str = _
'1行' & @CRLF & _
'2行' & @CRLF & _
'3行' & @CRLF & _
'4行' & @CRLF & _
'5行' & @CRLF & _
'6行' & @CRLF & _
'7行' & @CRLF & _
'8行' & @CRLF & _
'9行' & @CRLF & _
'10行' & @CRLF & _
'11行' & @CRLF & _
'12行' & @CRLF & _
'13行' & @CRLF & _
'14行' & @CRLF & _
'15行' & @CRLF & _
'16行' & @CRLF & _
'17行' & @CRLF & _
'18行' & @CRLF & _
'19行' & @CRLF & _
'20行' & @CRLF & _
'21行' & @CRLF & _
'22行' & @CRLF & _
'23行' & @CRLF & _
'24行' & @CRLF & _
'25行' & @CRLF & _
'26行' & @CRLF & _
'27行' & @CRLF & _
'28行' & @CRLF & _
'29行'
MsgBox(0, '原字符串', $Str)
Local $Test = StringRegExp($str, '.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+.*?\v+(.*?)\v+.*?', 3)
If Not @Error Then MsgBox(0, '匹配数量: ' & UBound($Test), '其中元素为: ' & $Test)
_ArrayDisplay($Test, UBound($Test))献丑写一条烂到鬼的正则,楼主可拿去测试一下,每30行提取一个1行(测试的时候不是每30行,所以上面的字符串没那么长)
坐等A版表演 回复 9# tryhi
正则可以这么写.
#include <Array.au3>
Local $Str
For $i = 1 To 30000
$Str &= $i & "行" &@CRLF
Next
Local $Test = StringRegExp($Str, '(?m)(^.*?\v){30}', 3)
_ArrayDisplay($Test, UBound($Test))
坐等Afan大大的表演,表示好奇! 98万多行,本机测试 5xx 毫秒Local $File_test = '98万行测试样本.txt', $File_New = '测试输出.txt'
If Not FileExists($File_test) Then
Local $sHead = '', $sData = ''
For $i = 1 To 7
$sHead &= '固定格式的文件头第' & $i & '行' & @CRLF
Next
Local $sData = '需保留行1' & @CRLF
For $i = 2 To 30
$sData &= '需删除行' & $i & @CRLF
Next
For $i = 1 To 15
$sData &= $sData
Next
;结尾添加一些行,因为不大可能数据总行数都是30的倍数
$sData &= '需保留行1------标记最后提取行' & @CRLF
For $i = 2 To 18
$sData &= '需删除行' & $i & @CRLF
Next
$sData &= '数据完毕'
FileWrite($File_test, $sHead & $sData)
Msgbox(0, 0, '已创建 983,066 行测试数据')
EndIf
;==================== 开始测试
Local $str = FileRead($File_test)
Local $ts = TimerInIt()
Local $sRP = StringRegExpRePlace($str, '^((?:\V*\v+){8})(?:\V*\v+){29}|(\V*\v+)(?:\V*\v+){29}', '\1\2')
FileDelete($File_New)
FileWrite($File_New, $sRP)
Msgbox(0, 0, '完成耗时:' & Round(TimerDiff($ts)) & ' ms')
测试 400万 行,2 秒多 这个要学习。 回复 12# afan
FileRead 会将整个文件读入内存,如楼主所说,如果文件是200M,内存占用将达200M
页:
[1]
2