(已解决) iselect 函数与有序文件

大佬们,过年好😄 Kung Hey Fat Choy 🙏

关于有序文本文件,有几个问题还得麻烦大佬们指导解惑。

实际场景是有 4500 个 txt 文件,都是 6 列,行数从几千行 (大于 1024 行) 到两万多行不等,需要从每一个 txt 文件中获取满足条件的某一行或者某几行,但这些 txt 文件格式并不规范,从以下截图中可以看到,第一行并不是传统的表头,最后一行也不是需要的数据。但有一个好处是,所有文件都是对第 1 列第 2 列分段有序的,第 1 列按每一天 (除了节假日) 升序,第 2 列从 9 点 30 分开始,每一分钟生成一行数据(上午从 0930-1130,下午从 1300-1500),也就是每天 240 行数据,具体数据请看本帖附件。

imagepng

这个查找需求已经解决了,相比较于 VBA 中传统的 OpenTextFile 方法 (耗时 56 秒),或者用 Open Binary Access 方法 (耗时 10 秒左右,运行不稳定,首次运行耗时很长,第二次运行会快很多,猜测也是缓存的影响,这里不追究),SPL 处理 4500 个 txt 耗时 6 秒左右,效率还是很高的。我的问题是在解决过程中发现的。

问题 1:像这种首行不是表头的 txt 文件,能否实现按最大列数导入成表格?

目前像这种 txt 用 file(txt).import()或者 import@t() 导入时,只能生成 1 列,如下截图:

imagepng

除非用 import@w()读成序列的序列,才能把所有有效的列完整的读出来,但读成序列的序列,总有一些用法上的限制。如果是 csv 格式,用 import@c() 或者 import@tc() 时,可以按最大列数读出,如下图所示:

imagepng

所以,txt 文件在 import 时可否实现跟 csv 文件 import 时一样按最大列数导入成序表?

问题 2:文本文件 (txt,csv) 在用 file().iselect@r 时会出现问题。

如果文本文件对其中的某一字段有序就可以使用 iselect 进行外存二分法查找,结果返回游标。因为 iselect 对有序文件的查找效率很高,所以我把上述 txt 文件掐头去尾后转存成了标准的 txt,csv 和 btx 格式,代码如下:

A B
1 =file("SZ#301459TXT.txt")
2 =file("SZ#301459CSV.csv")
3 =file("SZ#301459BTX.btx")
4 =file("SZ#301459.txt").import@fw()
5 =A4.delete@n([1,-1])(1)(1).split(" ")(2)
6 =A1.export@t(E(A4)) =A1.import@tf()
7 =A2.export@tc(E(A4)) =A2.import@tcf()
8 =A3.export@b(E(A4)) =A3.import@b()

然后用 iselect 进行查找,比如,以下语句只要能保证查找值的唯一性,均能正常出结果:

A
1 =file("SZ#301459TXT.txt")
2 =file("SZ#301459CSV.csv")
3 =file("SZ#301459BTX.btx")
4 [2023/12/28,2024/01/11,2024/01/12,2024/01/15,2024/02/06,2024/02/07,2024/02/08]
5
6 以下 3 种两个字段的单值查找均能出结果
7 =A1.iselect@ft("2024/02/080931",#1+#2).fetch()
8 =A2.iselect@ftc("2024/02/080931",#1+#2).fetch()
9 =A3.iselect@b("2024/02/080931",#1+#2).fetch()
10
11 以下 3 种两个字段区间形式多个结果时,都能正常出结果
12 =A1.iselect@ft("2023/02/061300":"2024/02/080945",#1+#2).fetch()
13 =A2.iselect@ftc("2023/02/061300":"2024/02/080945",#1+#2).fetch()
14 =A3.iselect@b("2023/02/061300":"2024/02/080945",#1+#2).fetch()

但是 iselect 还有 @r 选项,用于查找值不是唯一值时的场景。此例中因为第 1 列虽然有序,但值不唯一,所以用 @r 选项,此时,不管是单值查找还是区间查找或者序列查找,只有 btx 格式能正常出结果(但 btx 也会有其它问题,行数不够时会报错,请看下文),txt 和 csv 在用 iselect@r 选项时会报错,如下所示:

A B
1 =file("SZ#301459TXT.txt")
2 =file("SZ#301459CSV.csv")
3 =file("SZ#301459BTX.btx")
4 [2023/12/28,2024/01/11,2024/01/12,2024/01/15,2024/02/06,2024/02/07,2024/02/08]
5
6 以下 3 种单字段的单值查找 @r 时,txt/csv 会报错,btx 正常
7 =A1.iselect@ftr("2024/02/08",#1).fetch() 报错
8 =A2.iselect@ftcr("2024/02/08",#1).fetch() 报错
9 =A3.iselect@br("2024/02/08",#1).fetch() 结果正常
10
11 以下 3 种单字段区间形式多个结果 @r 选项时,txt/csv 出来的结果不全,btx 正常出结果
12 =A1.iselect@ftr("2023/02/06":"2024/02/08",#1).fetch() 结果不全
13 =A2.iselect@ftcr("2023/02/06":"2024/02/08",#1).fetch() 结果不全
14 =A3.iselect@br("2023/02/06":"2024/02/08",#1).fetch() 结果正常
15
16 以下 3 种单字段序列形式多个结果 @r 选项时时,txt/csv 会报错,btx 正常
17 =A1.iselect@ftr(A4,#1).fetch() 报错
18 =A2.iselect@ftcr(A4,#1).fetch() 报错
19 =A3.iselect@br(A4,#1).fetch() 结果正常

报错时的截图如下:

imagepng

我以为 txt/csv 之所以会报错,有可能是 txt 文件本身来源有问题,于是模拟生成文件测试如下,结果跟上述是一样的,txt、csv 格式在用 iselect@r 时会有问题,猜测可能是 txt、csv 格式不能随意分段或者是分段没有做好?


A B C
1 =file(“test1.txt”)
2 =file(“test2.csv”)
3 =file(“test3.btx”)
4 =file(“test4.ctx”) =A4.create@y(#ID1,#ID2,Amt)
5 =8.news(128;get(1):ID1,~:ID2,rand(100):Amt)
6 =A1.export@t(A5) =A1.import@t()
7 =A2.export@tc(A5) =A2.import@tc()
8 =A3.export@b(A5) =A3.import@b()
9 =B4.append@i(A5) =A4.open() =B4.import()
10 =A1.iselect@tr(1:2,#1).fetch()
11 =A1.iselect@tr([1,2],#1).fetch()
12 =A2.iselect@trc(1:2,#1).fetch()
13 =A2.iselect@trc([1,2],#1).fetch()
14 =A3.iselect@br(1:2,#1).fetch()
15 =A3.iselect@br([1,2],#1).fetch()
16 =B4.cursor(;#1>=1&&#1<=2).fetch()

上述模拟语句中,txt 和 csv 格式在用 iselect@r 时问题一样存在,要么结果不全,要么报错。但发现了另一个问题:

问题 3:btx.iselect() 时,如果 btx 文件的行数小于等于 1024 行就会报错

请注意上述代码格 A5 中,news 之所以写成 8×128=1024 行,就是为了引出 btx 报错的问题,代码格 A14、A15 报错如下,说是 btx 文件格式错误:

imagepng

只要文件行数大于 1024 行,btx 就不会报错,且能正常出结果,比如变成 1025 行,此时 btx 没有问题,但 txt 和 csv 在用区间形式的参数时 (1:2) 结果不全,请看以下代码格中的 A10 和 A12,但用序列形式的参数时([1,2]),txt 和 csv 出来的结果倒是正常的,请看以下代码格中的 A11 和 A13:

A B C
1 =file("test1.txt")
2 =file("test2.csv")
3 =file("test3.btx")
4 =file("test4.ctx") =A4.create@y(#ID1,#ID2,Amt)
5 =5.news(205;get(1):ID1,~:ID2,rand(100):Amt)
6 =A1.export@t(A5) =A1.import@t()
7 =A2.export@tc(A5) =A2.import@tc()
8 =A3.export@b(A5) =A3.import@b()
9 =B4.append@i(A5) =A4.open() =B4.import()
10 =A1.iselect@tr(1:2,#1).fetch() 结果不全
11 =A1.iselect@tr([1,2],#1).fetch() 结果正常
12 =A2.iselect@trc(1:2,#1).fetch() 结果不全
13 =A2.iselect@trc([1,2],#1).fetch() 结果正常
14 =A3.iselect@br(1:2,#1).fetch() 结果正常
15 =A3.iselect@br([1,2],#1).fetch() 结果正常
16 =B4.cursor(;#1>=1 && #1<=2).fetch() 结果正常

以上 3 个问题恳请大佬们得闲时给予帮助,谢谢!

附件如下:

zip