golang虚拟文件

nafvub8i  于 2021-06-02  发布在  Hadoop
关注(0)|答案(2)|浏览(321)

我有一个关闭的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的文件就满了,而另一个程序则把它全部取下并关闭管道。
但是过了一段时间,另一个正在读取管道的程序关闭了管道,我得到了断管错误。有没有可能创建一个虚拟文件以外的保险丝和管道?

avwztpqn

avwztpqn1#

我知道问题是封闭源代码程序2需要一个文件名,而不直接接受来自stdin的输入?
运行程序时,可以使用标准的unix样式管道将进程的stdin和stdout连接在一起。命名管道可能有问题,为此使用fuse过于复杂。
您可以将程序1输出到标准输出。并为封闭源代码程序2提供虚拟文件名 /dev/stdin 具体如下:

program1 | program2 /dev/stdin

这是假设您正在linux上工作(您没有指定,但我假设是这样,因为您正在谈论fuse)。
如果program2关心文件名(例如需要一个特定的扩展名),那么您可以通过创建一个符号链接,使所需的名称指向 /dev/stdin 并提供符号链接的名称作为program2的参数:

ln -s /dev/stdin file.ext
program1 | program2 file.ext
rm -f file.ext

如果program2需要一个它可以统计的真实文件,但在本例中,这不应该是一个问题(从program2接受命名管道的问题可以看出),那么这些都不起作用。
另外,如果program2需要来自stdin的键盘输入,这种方法将不起作用。

qltillow

qltillow2#

我想你对fuse的想法是对的。没有上游应用程序的源代码,很难说它试图使用什么样的文件语义(尽管使用strace可能有助于说明发生了什么)。也许。
在任何情况下,我都会看一看go fuse项目,特别是hello.go示例,它确切地说明了如何很好地处理单个文件的情况。

相关问题