沒有這樣的功能。可能沒有文件名或與FILE *
對應的多個文件名。在Unix上,程序在重命名或刪除後可以繼續引用文件,這可能意味着您的文件名不存在FILE *
。或者可以對文件進行更多的硬鏈接,這意味着文件可以有多個名稱;你會選哪一個?爲了進一步混淆事物,可以通過在包含該文件的目錄上安裝文件系統來臨時隱藏文件。該文件仍然位於磁盤上,位於其原始路徑名中,但該文件在該路徑上將無法訪問,因爲該安裝程序會遮蓋該文件。
也有可能FILE *
根本不對應文件系統上的文件;雖然他們通常會這樣做,但您可以使用fdopen()
從任何文件描述符創建一個文件描述符,並且該文件描述符可能是管道,套接字或其他類似文件的對象,它們在磁盤上從來沒有路徑。在C庫的某些版本中,您可以打開一個字符串流(例如,glibc中的fmemopen()
),因此FILE *
實際上只對應於內存緩衝區。
如果您關心該名稱,最好只跟蹤打開文件時命名的內容。
有一些hacky的方法來近似獲取文件名;如果您只是將其用於調試或信息目的,那麼它們可能就足夠了。其中大多數將需要在文件描述符而不是FILE *
上運行,因爲文件描述符是引用文件的較低級別方式。要獲取文件描述符,請在FILE *
上運行fileno()
,並記住在沒有與該文件關聯的文件描述符FILE *
時檢查錯誤。
在Linux上,您可以在"/proc/self/fd/fileno"
上執行readlink()
,其中fileno
是文件描述符。這會告訴你文件打開時文件的文件名是什麼,或者是一個字符串,表示它是什麼類型的文件描述符,比如套接字或inotify句柄。 FreeBSD和NetBSD都有Linux仿真層,其中包括模擬Linux風格的procfs;如果你安裝了一個Linux兼容的procfs,你也許可以在這些上做到這一點,儘管我沒有它們可用於測試。
在Mac OS X上,您沒有/proc/self/fd
。如果你不關心如何找到原始文件名,但是引用文件的其他文件名可以起作用(這樣你就可以將它傳遞給另一個程序),你可以構造一個:/.vol/deviceid/inode
。例如,/.vol/234881030/281363
。要獲取這些值,請在文件描述符上運行fstat()
,並在生成的struct stat
上使用st_dev
和st_ino
。
在Windows上,文件和文件系統的工作方式與Unix完全不同。顯然,可以在Windows上將文件映射回其名稱。從Windows Vista開始,您只需撥打GetFinalPathNameByHandle()
即可。這需要一個HANDLE
;從文件描述符中獲取HANDLE
,請致電_get_osfhandle()
。在Windows Vista之前,您需要做更多的工作,如this article中所述。請注意,在Windows上fileno()
被命名爲_fileno()
,雖然前者可能會發出警告。
進一步進入hacky領域,還有一些技巧可以使用。你可以掏出lsof
,或者你可以提取它用來解析路徑名的代碼。 lsof
實際上直接在內核內存中查看,從內核的名稱緩存中提取信息。這有幾個限制,在the lsof
FAQ中列出。當然,您需要root或相當的權限才能直接或通過suid/sgid二進制文件來執行此操作。最後,對於尋找與打開的文件相匹配的一個或多個文件名的便攜式但速度慢的解決方案,您可以在文件描述符上使用fstat()
找到設備和inode編號,然後遞歸遍歷文件系統stat()
,直到找到具有匹配設備和inode編號的文件。請記住我上面提到的警告;您可能會發現沒有匹配的文件,多個匹配的文件,即使沒有找到任何匹配的文件,該文件可能仍然存在,但被掛載點隱藏。當然,可能存在競爭條件;有些東西可能會重新命名文件,以至於在遍歷層次結構時永遠不會看到它。
可能的重複[如何從FILE \ *結構在C中獲取文件的名稱](http://stackoverflow.com/questions/7988784/how-to-get-a-files-name-from-file- struct-in-c) – dasblinkenlight
從我的角度來看,@dasblinkenlight在該線程中沒有答案。 – 0x6B6F77616C74
有人回答,並且回答正確。 –