我希望我做错了,但似乎kdb无法从命名管道读取数据(至少在Solaris上)。它会一直阻塞,直到它们被写入,但不会返回任何已写入的数据。
我可以创建一个文本文件:
$ echo Mary had a little lamb > lamb.txt
并且kdb很乐意阅读它:
q) read0 `:/tmp/lamb.txt
enlist "Mary had a little lamb"
我可以创建一个命名管道:
$ mkfifo lamb.pipe
并试图从中读取:
q) read0 `:/tmp/lamb.pipe
会导致kdb阻塞。写入管道:
$ cat lamb.txt > lamb.pipe
将导致kdb返回空列表:
()
kdb可以从命名管道中读取吗?我应该放弃吗?我不认为这是权限问题(我尝试在我的-m 777
命令上设置mkfifo
,但这没有任何区别。)
答案 0 :(得分:3)
发布kdb+ v3.4 Q
支持命名管道:根据您是要实现流式算法还是只读取管道,请使用fifo管道上的.Q.fps
或read1
:
要实现流式传输,您可以执行以下操作:
q).Q.fps[0N!]`:lamb.pipe
然后$ cat lamb.txt > lamb.pipe
将打印
在你的q会话中,"玛丽有一只小羊羔"
。通过用适当的函数替换0N!
,可以实现更有意义的算法。
要将文件的上下文读入变量do:
q)h:hopen`:fifo://lamb.pipe
q)myText: `char$read1(h)
q)myText
"玛丽有一只小羊羔\ n"
详细了解命名管道here。
答案 1 :(得分:1)
read0
失败时,您可以经常使用system"cat ..."
伪造它。 (我最初在尝试从/ proc中读取与read0
不兼容的东西时发现了这一点。)
q)system"cat /tmp/lamb.pipe"
<blocks until you cat into the pipe in the other window>
"Mary had a little lamb"
q)
请注意,调用system
会有相当高的开销(因为这样的事情会进入q) - 它会生成一个完整的shell进程,只是为了运行你的命令
您也可以直接使用custom C extension进行操作,可能直接调用read(2)
...
答案 2 :(得分:0)
read0的算法无法看到它在幕后做了什么,但据我所知,它预计有限流而不是连续流;所以它会阻止,直到它收到一个EOF信号。
答案 3 :(得分:0)
从v3.4开始支持管道流
详细步骤:
检查重复的管道文件
rm -f / path / dataPipeFileName
创建命名管道
mkfifo / path / dataPipeFileName
Feed数据
q).util.system [$ 1]; $ 1 =获取数据的命令> / path / dataPipeFileName&
使用kdb .Q.fps连接管道
q).Q.fps [0N!]`$“:/ path /”,dataPipeFileName;
参考: .Q.fps(流算法) 语法:.Q.fps [x; y]其中x是一元函数,y是文件路径 Q.fs用于管道。 (从V3.4开始)从管道中方便地读取大小完整的“ \ n”定界记录集,并将函数应用于每个记录。这样一来,您就可以实施流传输算法,将大型CSV文件转换为磁盘上的kdb +数据库,而无需一次将数据全部保存在内存中。