2009-12-08 7 views
36

में अद्वितीय फ़ाइल पहचानकर्ता क्या चाल, नाम और सामग्री संशोधनों के बावजूद फ़ाइल के जीवनकाल के लिए फ़ाइल (और संभवतः निर्देशिका) को विशिष्ट रूप से पहचानने का कोई तरीका है? (विंडोज 2000 और बाद में)। किसी फ़ाइल की प्रतिलिपि बनाना प्रतिलिपि को अपना अद्वितीय पहचानकर्ता देना चाहिए।विंडोज

मेरा एप्लिकेशन अलग-अलग फाइलों के साथ विभिन्न मेटा-डेटा को जोड़ता है। यदि फ़ाइलों को संशोधित किया गया है, नाम बदल दिया गया है या स्थानांतरित किया गया है तो यह फ़ाइल संघों को स्वचालित रूप से पहचानने और अपडेट करने में सक्षम होने के लिए उपयोगी होगा।

फाइलसिस्टम वाटर उन घटनाओं को प्रदान कर सकता है जो इन प्रकार के परिवर्तनों को सूचित करते हैं, हालांकि यह एक मेमोरी बफर का उपयोग करता है जिसे आसानी से भर दिया जा सकता है (और घटनाएं खो जाती हैं) यदि कई फाइल सिस्टम घटनाएं जल्दी होती हैं।

एक हैश का कोई उपयोग नहीं है क्योंकि फ़ाइल की सामग्री बदल सकती है, और इसलिए हैश बदल जाएगा।

मैंने फ़ाइल निर्माण तिथि का उपयोग करने के बारे में सोचा था, हालांकि ऐसी कुछ स्थितियां हैं जहां यह अद्वितीय नहीं होगी (यानी जब एकाधिक फाइलों की प्रतिलिपि बनाई जाती है)।

मैंने NTFS में एक फ़ाइल एसआईडी (सुरक्षा आईडी?) के बारे में भी सुना है, लेकिन मुझे यकीन नहीं है कि यह वही करेगा जो मैं ढूंढ रहा हूं।

कोई विचार?

उत्तर

17

यदि आप GetFileInformationByHandle पर कॉल करते हैं, तो आपको BY_HANDLE_FILE_INFORMATION.nFileIndexHigh/Low में एक फ़ाइल आईडी मिल जाएगी। यह अनुक्रमणिका वॉल्यूम के भीतर अद्वितीय है, और यदि आप फ़ाइल (वॉल्यूम के भीतर) ले जाते हैं या उसका नाम बदलते हैं तो भी वही रहता है।

यदि आप मान सकते हैं कि एनटीएफएस का उपयोग किया जाता है, तो आप मेटाडेटा को स्टोर करने के लिए वैकल्पिक डेटा स्ट्रीम का उपयोग करने पर भी विचार करना चाहेंगे।

+0

लिंक के लिए धन्यवाद। मुझे वास्तव में एक और एपीआई कॉल मिला जो एक ही आईडी देता है लेकिन थोड़ा और काम करने की आवश्यकता है। मैं कोड के साथ आने के लिए पोस्ट कर सकता हूं। एक वैकल्पिक डेटा स्ट्रीम भी उपयोगी हो सकता है क्योंकि बीएटी का सामना करने वाला एकमात्र स्थान यूएसबी कुंजी/बाहरी ड्राइव पर है। हालांकि मैंने सुना है कि कुछ एंटी-वायरस/सुरक्षा सॉफ़्टवेयर को फ़ाइलों में छिपे हुए डेटा जोड़ने के साथ कोई समस्या हो सकती है। – Ash

+6

GetFileInformationByHandle के लिए प्रलेखन कहता है: "nFileIndexLow: फ़ाइल से जुड़े एक अद्वितीय पहचानकर्ता का निम्न-आदेश भाग। यह मान केवल तब उपयोगी होता है जब फ़ाइल कम से कम एक प्रक्रिया द्वारा खुलती है। यदि कोई प्रक्रिया नहीं खुलती है, तो अनुक्रमणिका अगली बार फ़ाइल खोले जाने पर बदल सकती है। " –

+0

एचएम, यह खंड एमएसडीएन (अब और?) पर प्रलेखन में प्रतीत नहीं होता है। अनुभवजन्य रूप से, मैं देख रहा हूं कि फाइल इंडेक्स रीबूट (एनटीएफएस फाइल सिस्टम पर) में अद्वितीय रहता है। – sqweek

28

यहां नमूना कोड है जो एक अद्वितीय फ़ाइल इंडेक्स देता है।

दृष्टिकोण() मैं कुछ शोध के बाद आया था। ApproachB() मैटियास और रूबेंस द्वारा प्रदान किए गए लिंक में जानकारी के लिए धन्यवाद है। एक विशिष्ट फ़ाइल को देखते हुए, दोनों दृष्टिकोण एक ही फ़ाइल इंडेक्स (मेरे मूल परीक्षण के दौरान) लौटाते हैं।

MSDN से कुछ चेतावनियां: फ़ाइल आईडी के लिए

समर्थन फ़ाइल प्रणाली विशेष है। फ़ाइल आईडी समय के साथ अद्वितीय होने की गारंटी नहीं है, क्योंकि फ़ाइल सिस्टम का पुन: उपयोग करने के लिए स्वतंत्र हैं। कुछ मामलों में, फ़ाइल के लिए फ़ाइल आईडी समय के साथ बदल सकती है।

FAT फ़ाइल सिस्टम में, फ़ाइल आईडी युक्त निर्देशिका और बाइट फ़ाइल के लिए प्रवेश की निर्देशिका भीतर भरपाई के पहले क्लस्टर से उत्पन्न है। कुछ डीफ्रैग्मेंटेशन उत्पाद इस बाइट ऑफसेट को बदलते हैं। (विंडोज इन-बॉक्स डीफ्रैग्मेंटेशन नहीं है।) इस प्रकार, एक एफएटी फ़ाइल आईडी समय के साथ बदल सकता है। का नामकरण FAT फ़ाइल सिस्टम में एक फ़ाइल भी फ़ाइल आईडी को बदल सकता है, लेकिन केवल नया फ़ाइल नाम पुराना एक से अधिक लंबा है।

एनटीएफएस फ़ाइल सिस्टम में, फ़ाइल उसी फ़ाइल आईडी को तब तक रखती है जब तक इसे हटाया नहीं जाता। आप एक फ़ाइल को फ़ाइल के साथ प्रतिस्थापित कर सकते हैं फ़ाइल आईडी को द्वारा ReplaceFile फ़ंक्शन का उपयोग करके फ़ाइल आईडी को बदले बिना। हालांकि, प्रतिस्थापन फ़ाइल की फ़ाइल आईडी, प्रतिस्थापित फ़ाइल नहीं, परिणामी फ़ाइल की फ़ाइल आईडी के रूप में बरकरार रखी गई है।

उपरोक्त पहली बोल्ड टिप्पणी मुझे चिंतित करती है। यह स्पष्ट नहीं है कि यह कथन केवल एफएटी पर लागू होता है, ऐसा लगता है कि यह दूसरा बोल्ड टेक्स्ट है। मुझे लगता है कि आगे परीक्षण सुनिश्चित करने का एकमात्र तरीका है।

[अद्यतन:। मेरी परीक्षण फ़ाइल सूचकांक/आईडी परिवर्तन जब एक फाइल अन्य आंतरिक NTFS हार्ड ड्राइव करने के लिए एक आंतरिक NTFS हार्ड ड्राइव से ले जाया जाता है में]

public class WinAPI 
    { 
     [DllImport("ntdll.dll", SetLastError = true)] 
     public static extern IntPtr NtQueryInformationFile(IntPtr fileHandle, ref IO_STATUS_BLOCK IoStatusBlock, IntPtr pInfoBlock, uint length, FILE_INFORMATION_CLASS fileInformation); 

     public struct IO_STATUS_BLOCK 
     { 
      uint status; 
      ulong information; 
     } 
     public struct _FILE_INTERNAL_INFORMATION { 
      public ulong IndexNumber; 
     } 

     // Abbreviated, there are more values than shown 
     public enum FILE_INFORMATION_CLASS 
     { 
      FileDirectoryInformation = 1,  // 1 
      FileFullDirectoryInformation,  // 2 
      FileBothDirectoryInformation,  // 3 
      FileBasicInformation,   // 4 
      FileStandardInformation,  // 5 
      FileInternalInformation  // 6 
     } 

     [DllImport("kernel32.dll", SetLastError = true)] 
     public static extern bool GetFileInformationByHandle(IntPtr hFile,out BY_HANDLE_FILE_INFORMATION lpFileInformation); 

     public struct BY_HANDLE_FILE_INFORMATION 
     { 
      public uint FileAttributes; 
      public FILETIME CreationTime; 
      public FILETIME LastAccessTime; 
      public FILETIME LastWriteTime; 
      public uint VolumeSerialNumber; 
      public uint FileSizeHigh; 
      public uint FileSizeLow; 
      public uint NumberOfLinks; 
      public uint FileIndexHigh; 
      public uint FileIndexLow; 
     } 
    } 

    public class Test 
    { 
     public ulong ApproachA() 
     { 
       WinAPI.IO_STATUS_BLOCK iostatus=new WinAPI.IO_STATUS_BLOCK(); 

       WinAPI._FILE_INTERNAL_INFORMATION objectIDInfo = new WinAPI._FILE_INTERNAL_INFORMATION(); 

       int structSize = Marshal.SizeOf(objectIDInfo); 

       FileInfo fi=new FileInfo(@"C:\Temp\testfile.txt"); 
       FileStream fs=fi.Open(FileMode.Open,FileAccess.Read,FileShare.ReadWrite); 

       IntPtr res=WinAPI.NtQueryInformationFile(fs.Handle, ref iostatus, memPtr, (uint)structSize, WinAPI.FILE_INFORMATION_CLASS.FileInternalInformation); 

       objectIDInfo = (WinAPI._FILE_INTERNAL_INFORMATION)Marshal.PtrToStructure(memPtr, typeof(WinAPI._FILE_INTERNAL_INFORMATION)); 

       fs.Close(); 

       Marshal.FreeHGlobal(memPtr); 

       return objectIDInfo.IndexNumber; 

     } 

     public ulong ApproachB() 
     { 
       WinAPI.BY_HANDLE_FILE_INFORMATION objectFileInfo=new WinAPI.BY_HANDLE_FILE_INFORMATION(); 

       FileInfo fi=new FileInfo(@"C:\Temp\testfile.txt"); 
       FileStream fs=fi.Open(FileMode.Open,FileAccess.Read,FileShare.ReadWrite); 

       WinAPI.GetFileInformationByHandle(fs.Handle, out objectFileInfo); 

       fs.Close(); 

       ulong fileIndex = ((ulong)objectFileInfo.FileIndexHigh << 32) + (ulong)objectFileInfo.FileIndexLow; 

       return fileIndex; 
     } 
    } 
+7

अच्छा, मैंने इसे आजमाया, लेकिन एक समस्या मिली: यह माइक्रोसॉफ्ट ऑफिस सूट (डॉक्टर, डॉक्क्स, एक्सएलएस ...) जैसी फाइल के लिए काम नहीं कर रहा है क्योंकि हर बार जब आप कोई बदलाव करते हैं, तो Office फ़ाइल को हटाना होता है, और एक इसे बदलने के लिए नई फ़ाइल, संदर्भ संख्या में यह परिणाम बदल गया, हालांकि संदर्भ संख्या अभी भी अद्वितीय है। यह उन फ़ाइलों में परिवर्तनों का पता लगाने के लिए काम नहीं कर सकता है, और शायद कुछ अन्य कार्यक्रमों के समान दृष्टिकोण भी होगा। तो मुझे लगता है कि मैं अपनी क्रिएशनटाइम विधि पर वापस आऊंगा ... – VHanded

+0

एफडब्ल्यूआईडब्ल्यू, मुझे एशले हैंडर्सन के दृष्टिकोण को काम करने के लिए नहीं मिला, लेकिन दृष्टिकोण ने काम किया। मैं VHanded के नोट की पुष्टि करने में सक्षम था कि जब आप Word (docx) दस्तावेज़ को संशोधित करते हैं तो FileID बदल जाता है, जो बहुत खराब है क्योंकि Office फ़ाइलें वे हैं जिन्हें मैं ट्रैक करना चाहता हूं। –

+0

"हर बार जब आप कोई परिवर्तन करते हैं, तो Office फ़ाइल को हटाने के लिए होता है" ... Dammit, AutoCAD यह भी करता है। 'FileSystemWatcher' –

0

उपयोगकर्ता भी अद्वितीय निर्देशिका पहचान का उल्लेख है। फ़ाइल के लिए अद्वितीय जानकारी पुनर्प्राप्त करने की तुलना में यह प्रक्रिया थोड़ी अधिक गड़बड़ है; हालांकि, यह संभव है। इसके लिए आपको उचित CREATE_FILEfunction पर कॉल करना होगा जो एक विशेष ध्वज है। उस हैंडल के साथ, आप एश के answer में GetFileInformationByHandle फ़ंक्शन को कॉल कर सकते हैं।

 [DllImport("kernel32.dll", SetLastError = true)] 
     public static extern SafeFileHandle CreateFile(
      string lpFileName, 
      [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess, 
      [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode, 
      IntPtr securityAttributes, 
      [MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition, 
      uint dwFlagsAndAttributes, 
      IntPtr hTemplateFile 
     ); 

मैं थोड़ा अधिक इस जवाब बाहर मांस, बाद में होगी:

यह भी एक kernel32.dll आयात की आवश्यकता है। लेकिन, उपर्युक्त लिंक के साथ, यह समझना शुरू कर देना चाहिए। मेरा एक नया पसंदीदा संसाधन pinvoke है जिसने मुझे .Net C# हस्ताक्षर संभावनाओं के साथ मदद की है।