2012-05-07 32 views
3

我正在尋找從C編程中讀取stdin管道數據的最佳方法。如何高效地從stdin管道讀取需要查找的數據

問題:我需要尋求這一數據,也就是我需要在這同一個流的年底讀了一些數據後,從流讀取的開始數據。

小用例:gunzip -c 4GbDataFile.gz | myprogram

還有一句:

  1. 在本地主機:nc -l -p 1234 | myprogram
  2. 遠程主機:gunzip -c 4GbDataFile.gz | nc -q 0 theotherhost 1234

我知道,從FIFO讀可以做只有一次。所以,此刻:

  • stdin內存和工作從這塊內存啜一切

這是醜陋的,但它的工作原理。一個明顯的問題是,如果有人向我的應用發送了一個巨大(或連續)的流,我將以一個大的分配內存塊結束,否則我將耗盡內存。 (想想一個8GB的文件)

我想未來:

  • 我設置內存塊的大小限制(也許用戶自定義)。一旦我從標準輸入讀取了這麼多數據:
    1. 要麼我在這裏停止:「Errr。內存不足,bazinga。忘記它。」風格。
    2. 要麼我開始傾銷我正在閱讀到文件,並且在讀取所有數據後從該文件開始工作。

但是,那麼,有什麼意義呢?我無法找到我正在閱讀的數據的來源。如果這是一個本地8Gb文件,我將把它轉儲到同一系統上的另一個8Gb文件。

所以,我的問題是:

你如何有效地讀取從當你尋求來回的stdin管很多數據?

在此先感謝您的答案。

編輯:

我的程序需要給定的文件中讀取某個地方的元數據(根據文件格式的),所以,也許在流的末尾。然後它可以在流的開始處讀回其他數據,然後在另一個地方讀取其他數據。簡而言之:它需要訪問數據的任何字節。

一個例子是,但不啓動從stdin讀取之前知道文件格式讀取的歸檔文件的數據:我需要檢查檔案元數據,發現檔案文件名字和偏移等

所以我將製作標準輸入內容的本地副本並從中進行工作。謝謝大家的輸入;)

+1

ITYM'myprogram <4GbDataFile'。目前,'cat 4GbDataFile> myprogram'會覆蓋你的程序二進制文件。當你用管道替換'>'時,你會無用地使用貓。 – Jens

+0

謝謝,修正了錯字,增加了更有用的貓的用法。 – Lenain

回答

0

你的4GbDataFile中的數據結構並不適合你想要做的事情。創造性思考。不要把你的程序變成一些不該嘗試的東西。嘗試修復它生成的輸入格式,因此不需要返回4 GB。

如果你像錘子一樣:4GB的核心內存是非常昂貴的。相反,將從標準輸入讀取的數據保存到一個文件中,然後打開文件(或者將其映射到mmap中)並尋找您的內容。

+0

我無法修復輸入格式,因爲它可以是任何東西(我編輯了我的問題並在最後添加了一個程序工作示例)。不將4GB的文件格式化爲4GB的內核內存塊?將讀取的數據保存到文件中並尋找它可能更合適,但如果它是本地文件,它只是複製原始文件並在副本上工作而不是原始文件。 – Lenain

+1

**您不能擁有您的派並吃掉它。**尋找管道是不可能的。如果你堅持這樣做,你將不得不將不可檢索的數據變成可查找的(通過保存副本)。在映射時,不要映射整個數據,只需將您要查找的塊映射到mmap,然後根據搜索偏移量計算出來。 – Jens

+0

好的,謝謝,我會做一個副本,並警告用戶不要管道龐大的本地文件,並且傾向於將它們作爲fd以避免重複內容。 – Lenain

1

你需要明確你的要求。如果你需要seek()那麼顯然你不能從標準輸入輸入。如果您需要seek()那麼您應該將輸入文件名稱作爲參數。

+0

我剛纔提到,目前,它的工作原理是把所有的東西都記憶並記錄下來。我想這也會在使用臨時文件時起作用。我知道我不能在'fifo'上尋找,我正在尋找一個優雅的(比我更蠢的)解決方法;) – Lenain

+0

我認爲它會在使用臨時文件時起作用。 - 但是當你只是複製文件內容時,你爲什麼要這樣做?你的程序做什麼? – tuxuday

+0

我的程序需要讀取給定文件中某處的元數據(取決於文件格式),以便可能在流的末尾。然後它可以在流的開頭讀回其他數據,然後在另一個地方讀回數據。總之,它需要訪問任何字節的數據。例如,讀取歸檔文件的數據_不知道文件格式:我需要檢查歸檔元數據,查找歸檔文件名稱和偏移等。 – Lenain

0

我認爲你應該閱讀臭名昭着的Useless Use of Cat Award

TL; DR:將cat 4gbfile | yourprogram更改爲yourprogram < 4gbfile

如果你真的堅持要使用管道中的數據,你必須在啓動時將它存儲在一個臨時文件中,然後用dup2替換文件描述符0與臨時文件的fd的副本。

+0

這就是我想要的:使用管道中的數據。 (編輯我的問題,刪除「無用的貓」,它只是想成爲一個例子,否則我會用你和@Jens推薦的) – Lenain