2016-10-19 54 views
0

我有一个封闭的soruce应用程序,它将一个文件作为输入,计算它的散列并执行其他一些我无法控制的东西。修改源代码或逆向工程是不可行的。Golang虚拟文件

该程序设计用于处理常规文件,但是我需要从HDFS提供非常大的文件。复制文件将花费太多时间和空间在磁盘上。所以我正在考虑使用FUSE,但我没有找到一个好的解决方案。我尝试使用命名管道如下:

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字节命名管道缓冲区满和其他程序需要它毕竟然而并关闭管道。

但过了一段时间,正在读取管道的其他程序关闭了管道,并且出现了管道故障错误。除了保险丝和管道之外,是否还有可能创建虚拟文件?

回答

1

我认为你实际上对FUSE有正确的想法。如果没有上游应用程序的源代码,很难说它尝试使用哪种文件语义(尽管strace有一段时间可能有助于说明正在发生的事情,也许......)。

在任何情况下,我会看看the Go-FUSE project,特别是the hello.go example,它显示了如何处理单个文件的情况。

1

我明白的问题是,封闭的源程序2期望文件名,并不接受直接从stdin输入?

运行的程序时,您可以使用标准的Unix风格的管道的过程中连接标准输入标准输出在一起。命名管道可能会有问题,使用FUSE这个过于复杂。

你可以让你的program1输出到stdout。与虚拟文件名给封闭源代码的程序2 /dev/stdin如下:

program1 | program2 /dev/stdin 

这是假设您正在使用Linux操作系统(未指定,但我认为,是因为你在谈论FUSE)。

如果程序2关心文件名(例如,需要一个特定的扩展名),您可能可以通过创建一个符号链接来指定/dev/stdin并提供符号链接的名称作为符号链接该参数程序2:

如果程序2希望它可以统计但在这种情况下,不应该是一个问题(因为它是从问题众所周知,程序2接受真正的文件
ln -s /dev/stdin file.ext 
program1 | program2 file.ext 
rm -f file.ext 

无的,这将工作一个命名管道)。

此外,如果program2期望从stdin键盘输入此方法将无法正常工作。