我有一个关闭的soruce应用程序,它将一个文件作为输入,计算其哈希值,并执行一些我无法控制的其他操作。修改源代码或反向工程是不可行的。
这个程序是设计用来处理常规文件,但我需要提供一个非常大的文件从hdfs。复制文件将占用磁盘上太多的时间和空间。所以我想用保险丝,但我没有找到一个好的解决办法。我尝试使用命名管道,如下所示:
func readFile(namenode, path string, pipe *os.File) {
client, err := hdfs.New(namenode)
log.Println(err, client)
hdfsFile, err := client.Open(path)
if err != nil {
log.Fatal(err)
}
log.Println(hdfsFile)
// written, err := io.Copy(pipe, hdfsFile)
bytes := make([]byte, 4096)
for {
read, err := hdfsFile.Read(bytes)
log.Println(read, err)
if err != nil {
break
}
written, err := pipe.Write(bytes)
log.Println(written, err)
}
err = pipe.Close()
log.Println(err)
}
我知道上面的代码是不完整的,测试文件是10mb,但是在读取8次4096字节后,名为pipe buffer的文件就满了,而另一个程序则把它全部取下并关闭管道。
但是过了一段时间,另一个正在读取管道的程序关闭了管道,我得到了断管错误。有没有可能创建一个虚拟文件以外的保险丝和管道?
2条答案
按热度按时间avwztpqn1#
我知道问题是封闭源代码程序2需要一个文件名,而不直接接受来自stdin的输入?
运行程序时,可以使用标准的unix样式管道将进程的stdin和stdout连接在一起。命名管道可能有问题,为此使用fuse过于复杂。
您可以将程序1输出到标准输出。并为封闭源代码程序2提供虚拟文件名
/dev/stdin
具体如下:这是假设您正在linux上工作(您没有指定,但我假设是这样,因为您正在谈论fuse)。
如果program2关心文件名(例如需要一个特定的扩展名),那么您可以通过创建一个符号链接,使所需的名称指向
/dev/stdin
并提供符号链接的名称作为program2的参数:如果program2需要一个它可以统计的真实文件,但在本例中,这不应该是一个问题(从program2接受命名管道的问题可以看出),那么这些都不起作用。
另外,如果program2需要来自stdin的键盘输入,这种方法将不起作用。
qltillow2#
我想你对fuse的想法是对的。没有上游应用程序的源代码,很难说它试图使用什么样的文件语义(尽管使用strace可能有助于说明发生了什么)。也许。
在任何情况下,我都会看一看go fuse项目,特别是hello.go示例,它确切地说明了如何很好地处理单个文件的情况。