2016-10-19 80 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鍵盤輸入此方法將無法正常工作。