大CSV解析
我很难想出一个健壮而轻巧的算法来处理一些大的CSV文件。下面是一个简单的示例,展示了它们的外观: Time a b c 0 2.9 1.6 4.1 0 3.6 1.1 0.5 0 3.4 0.2 1.7 1.2 0.1 4.2 1.9 1.201 2.3 3.1 4.8 9.99 0.2 0.8 1.2 10 3.1 3.3 2.3 10 3.6 3.5 3.0 10.01 1.1 4.5 3.9 10.01 2.2 3.0 2.3 17 4.3 2.3 3.8 20 1.0 3.2 3.0 30 4.1 3.0 4.9 40 3.8 3.3 1.6 时间a b c 0 2.9 1.6 4.1 0 3.6 1.1 0.5 0 3.4 0.2 1.7 1.2 0.1 4.2 1.9 1.201 2.3 3.1 4.8 9.99 0.2 0.8 1.2 10 3.1 3.3 2.3 10 3.6 3.5 3.0 10.01 1.1 4.5 3.9 10.01 2.2 3.0 2.3 17 4.3 2.3 3.8 20 1.0 3.2 3.0 30 4.1 3.0 4.9 40 3.8 3.3 1.6 我需要根据以下规则对我的CSV进行后处理:大CSV解析,csv,vbscript,Csv,Vbscript,我很难想出一个健壮而轻巧的算法来处理一些大的CSV文件。下面是一个简单的示例,展示了它们的外观: Time a b c 0 2.9 1.6 4.1 0 3.6 1.1 0.5 0 3.4 0.2 1.7 1.2 0.1 4.2 1.9 1.201 2.3 3.1 4.8 9.99 0.2 0.8 1.2 10 3.1 3.3 2.3 10 3.6 3.5
filename=“测试”
采样时间=10.0
公差=1e-1
Dim FSO,输入,输出
常数ForReading=1
写入常数=2
'创建对象
设置FSO=CreateObject(“Scripting.FileSystemObject”)
设置输入=FSO.OpenTextFile(文件名和“.csv”,用于读取,False)
设置output=FSO.OpenTextFile(文件名&“\u output.csv”,用于写入,True)
'第一行:写入标题
s=input.ReadLine()
output.WriteLines
'第二行:初始化sSplit_old
s=input.ReadLine()
sSplit=拆分(s,“,”)
sSplit_old=sSplit
“继续读。。。
直到input.AtEndOfStream
'读取新行并将其拆分为组件
'读取行的第一个元素(即时间)时需要此参数
s=input.ReadLine()
sSplit=拆分(s,“,”)
'如果剩余时间/采样时间低于公差,则
“行必须进行处理。
'这里是“\”运算符(即整数除法:5\2=2,而5/2=2.5)
'用作“Mod”运算符返回整数余数。
如果CDbl(sSplit(0))-采样时间*(CDbl(sSplit(0))\采样时间)<公差,则
'如果当前时间接近上一个时间(在公差范围内)。。。
如果Abs(CDbl(sSplit(0))-CDbl(sSplit_old(0))<公差,则
'... 循环遍历阵列并存储平均值
对于i=0至UBound(sSplit)
sSplit_old(i)=(CDbl(sSplit(i))+CDbl(sSplit_old(i))/2.0
下一个
其他的
'... 否则,只需写上一次并保存当前时间
“一个用来和下一个比较
s=连接(sSplit_old,“,”)
output.WriteLines
sSplit_old=sSplit
如果结束
如果结束
环
output.WriteLines
输入,关闭
输出,关闭
当您为Windows操作系统支付了(太多)费用时,您也为SQL引擎支付了费用。所以使用它:
Option Explicit
Dim db : Set db = CreateObject("ADODB.Connection")
Dim dd : dd = "E:\work\proj\soa\47155733\data"
Dim cs
If "AMD64" = CreateObject("WScript.Shell").ExpandEnvironmentStrings("%PROCESSOR_ARCHITECTURE%") Then
cs = "Driver=Microsoft Access Text Driver (*.txt, *.csv);Dbq=" & dd & ";Extensions=asc,csv,tab,txt;"
WScript.Echo "64 Bit:", cs
Else
cs = "Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=" & dd & ";Extensions=asc,csv,tab,txt;"
WScript.Echo "32 Bit:", cs
End If
db.Open cs
Dim ss : ss = "SELECT * FROM [47155733.txt]"
WScript.Echo ss
WScript.Echo db.Execute(ss).GetString(2,,vbTab,vbCrlf,"*")
ss = "SELECT t, avg(a), avg(b), avg(c) FROM [47155733.txt]" _
& " WHERE t = Int(t) And 0.0 = t Mod 10 GROUP BY t"
WScript.Echo ss
WScript.Echo db.Execute(ss).GetString(2,,vbTab,vbCrlf,"*")
ss = "SELECT Round(1/3, 3)"
WScript.Echo ss
WScript.Echo db.Execute(ss).GetString(2,,vbTab,vbCrlf,"*")
输出:
cscript 47155733.vbs
SELECT * FROM [47155733.txt]
0 2,9 1,6 4,1
0 3,6 1,1 0,5
0 3,4 0,2 1,7
1,2 0,1 4,2 1,9
1,201 2,3 3,1 4,8
9,99 0,2 0,8 1,2
10 3,1 3,3 2,3
10 3,6 3,5 3
10,01 1,1 4,5 3,9
10,01 2,2 3 2,3
17 4,3 2,3 3,8
20 1 3,2 3
30 4,1 3 4,9
40 3,8 3,3 1,6
SELECT t, avg(a), avg(b), avg(c) FROM [47155733.txt] WHERE t = Int(t) And 0.0 = t Mod 10 GROUP BY t
0 3,3 0,966666666666667 2,1
10 3,35 3,4 2,65
20 1 3,2 3
30 4,1 3 4,9
40 3,8 3,3 1,6
SELECT Round(1/3, 3)
0,333
在Windows 10上测试32位和64位;德国地区。我更喜欢在schema.ini文件中指定文件格式:
[47155733.txt]
Format=Delimited(,)
ColNameHeader=True
DecimalSymbol=.
Col1=t Double
Col2=a Double
Col3=b Double
Col4=c Double
背景:
,.如果在电子表格中执行此操作,会更容易。VBA是你的选择吗?不是。我需要将其作为自动化脚本的一部分,该脚本需要在生成csv的机器上运行。这是我正在编写的一个自动化脚本的一部分,用于从一个巨大的数据文件到一个较小的即用数据集。由于您没有提到代码的特定问题(需要更好的算法),我建议您将此移到codereview.stackexchange.com您的代码“工作不正常”的原因是什么?是的。字段之间的单个分隔符,而不是问题中显示的内容。教训:不要美化你的数据样本。把你的数据准确地显示出来,这可能会对如何解决一项任务产生根本性的影响。这正是我要提出的。应该添加到VBScript中的一件事是
SetLocale“en-us”
(或OP喜欢的任何内容),以控制数字在字符串中的输出方式。OP说,预期的文件为几百MB,有数百列。ADODB的速度可能非常慢(并且在内存有限的情况下可能根本无法工作)。
[47155733.txt]
Format=Delimited(,)
ColNameHeader=True
DecimalSymbol=.
Col1=t Double
Col2=a Double
Col3=b Double
Col4=c Double