דילוג לתוכן
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
כיווץ
תחומים

תחומים - פורום חרדי מקצועי

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
  1. דף הבית
  2. תכנות
  3. ארכיון code613m
  4. יצירת רשימת קבצים ותקיות בתוך תקיה נבחרת

יצירת רשימת קבצים ותקיות בתוך תקיה נבחרת

מתוזמן נעוץ נעול הועבר ארכיון code613m
4 פוסטים 2 כותבים 368 צפיות
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • רחמיםר מנותק
    רחמיםר מנותק
    רחמים מורחק
    כתב ב נערך לאחרונה על ידי
    #1

    מצאתי פרוייקט ממש מוצלח, שבו תוך 3-4 שניות מקבלים רשימה של כל הקבצים והתקיות שיש בכונן C מה שע''י פונקציות רגילות של Directory.GetDirectories או Directory.GetFiles יכול לקחת כמה דקות ארוכות.

    אבל הבעיה היא שהוא תמיד סורק את כל הכונן, וזה לא מתאים כאשר הכונן גדול ואני צריך לסרוק רק איזו תקיה קטנה.
    השאלה יש למישהו הצעה איך ליעל את הדברים האלו למקסימום? אולי למישהו יש רעיון לשפץ את הפונקציה המהירה שלא תסרוק את הכל אלא רק את מה שצריך?

    תודה לכולם ושבת שלום.

    Public Sub FindAllFiles(ByVal szDriveLetter As String,
                                fFileFound As FileFound_Delegate,
                                fProgress As Progress_Delegate,
                                fMatch As IsMatch_Delegate)
    
            Dim usnRecord As USN_RECORD
            Dim mft As MFT_ENUM_DATA
            Dim dwRetBytes As Integer
            Dim cb As Integer
            Dim dicFRNLookup As New Dictionary(Of Long, FSNode)
            Dim bIsFile As Boolean
    
            ' This shouldn't be called more than once.
            If m_Buffer.ToInt32 <> 0 Then
                Console.WriteLine("invalid buffer")
                Exit Sub
            End If
    
            ' progress 
            If Not IsNothing(fProgress) Then fProgress.Invoke("Building file list.")
    
            ' Assign buffer size
            m_BufferSize = 65536 '64KB
    
            ' Allocate a buffer to use for reading records.
            m_Buffer = Marshal.AllocHGlobal(m_BufferSize)
    
            ' correct path
            szDriveLetter = szDriveLetter.TrimEnd("\"c)
    
            ' Open the volume handle 
            m_hCJ = OpenVolume(szDriveLetter)
    
            ' Check if the volume handle is valid.
            If m_hCJ = INVALID_HANDLE_VALUE Then
                Console.WriteLine("Couldn't open handle to the volume.")
                Cleanup()
                Exit Sub
            End If
    
            mft.StartFileReferenceNumber = 0
            mft.LowUsn = 0
            mft.HighUsn = Long.MaxValue
    
            Do
                If DeviceIoControl(m_hCJ, FSCTL_ENUM_USN_DATA, mft, Marshal.SizeOf(mft), m_Buffer, m_BufferSize, dwRetBytes, IntPtr.Zero) Then
                    cb = dwRetBytes
                    ' Pointer to the first record
                    Dim pUsnRecord As New IntPtr(m_Buffer.ToInt32() + 8)
    
                    While (dwRetBytes > 8)
                        ' Copy pointer to USN_RECORD structure.
                        usnRecord = Marshal.PtrToStructure(pUsnRecord, usnRecord.GetType)
    
                        ' The filename within the USN_RECORD.
                        Dim FileName As String = Marshal.PtrToStringUni(New IntPtr(pUsnRecord.ToInt32() + usnRecord.FileNameOffset), usnRecord.FileNameLength / 2)
    
                        'If Not FileName.StartsWith("$") Then
                        ' use a delegate to determine if this file even matches our criteria
                        Dim bIsMatch As Boolean = True
                        If Not IsNothing(fMatch) Then fMatch.Invoke(FileName, usnRecord.FileAttributes, bIsMatch)
    
                        If bIsMatch Then
                            bIsFile = Not usnRecord.FileAttributes.HasFlag(FileAttribute.Directory)
                            dicFRNLookup.Add(usnRecord.FileReferenceNumber, New FSNode(usnRecord.FileReferenceNumber, usnRecord.ParentFileReferenceNumber, FileName, bIsFile))
                        End If
                        'End If
    
                        ' Pointer to the next record in the buffer.
                        pUsnRecord = New IntPtr(pUsnRecord.ToInt32() + usnRecord.RecordLength)
    
                        dwRetBytes -= usnRecord.RecordLength
                    End While
    
                    ' The first 8 bytes is always the start of the next USN.
                    mft.StartFileReferenceNumber = Marshal.ReadInt64(m_Buffer, 0)
    
                Else
    
                    Exit Do
    
                End If
    
            Loop Until cb <= 8
    
            If Not IsNothing(fProgress) Then fProgress.Invoke("Parsing file names.")
    
            ' Resolve all paths for Files
            For Each oFSNode As FSNode In dicFRNLookup.Values.Where(Function(o) o.IsFile)
                Dim sFullPath As String = oFSNode.FileName
                Dim oParentFSNode As FSNode = oFSNode
    
                While dicFRNLookup.TryGetValue(oParentFSNode.ParentFRN, oParentFSNode)
                    sFullPath = String.Concat(oParentFSNode.FileName, "\", sFullPath)
                End While
                sFullPath = String.Concat(szDriveLetter, "\", sFullPath)
    
                If Not IsNothing(fFileFound) Then fFileFound.Invoke(sFullPath, 0)
            Next
    
            '// cleanup
            Cleanup()
            If Not IsNothing(fProgress) Then fProgress.Invoke("Complete.")
        End Sub
    

    פורסם במקור בפורום CODE613 ב11/10/2013 10:51 (+03:00)

    תגובה 1 תגובה אחרונה
    0
    • M מנותק
      M מנותק
      magicode
      כתב ב נערך לאחרונה על ידי
      #2

      לדעתי הוא קורא את הסקטורים בדיסק קשיח ששיכים לאינדקס של כל הקבצים.

      בגלל זה זה כל כך מהר כי הוא עוקף את המנגנון של מערכת הפעלה. וגם לכן אי אפשר לעשות פר תקיה כי אתה חייב לקרוא הכל כדי לדעת איפה נמצא הקבצים של התקיה הספציפית שאתה רוצה. אז מימלא זה אותו עבודה.

      פורסם במקור בפורום CODE613 ב11/10/2013 12:16 (+03:00)

      תגובה 1 תגובה אחרונה
      0
      • רחמיםר מנותק
        רחמיםר מנותק
        רחמים מורחק
        כתב ב נערך לאחרונה על ידי
        #3

        נכון, אבל זה לא ממש אותו עבודה בכל המקרים כי לפעמים יותר מהר לקרוא את כל שמות הקבצים עם הפונקציה המהירה ולסנן רק מה שאני צריך מאשר ללכת עם הפונקציות Directory.GetDirectories או Directory.GetFiles ולפעמים זה להיפך, השאלה אם יש איזו עצה מבריקה איך אני אדע מראש באיזו דרך לילך? [או אולי להפעיל את שניהם ומי שיגמור ראשון לקחת אותו, ולהפסיק את השני....?]

        פורסם במקור בפורום CODE613 ב12/10/2013 21:28 (+03:00)

        תגובה 1 תגובה אחרונה
        0
        • M מנותק
          M מנותק
          magicode
          כתב ב נערך לאחרונה על ידי
          #4

          @רחמים

          נכון, אבל זה לא ממש אותו עבודה בכל המקרים כי לפעמים יותר מהר לקרוא את כל שמות הקבצים עם הפונקציה המהירה ולסנן רק מה שאני צריך מאשר ללכת עם הפונקציות Directory.GetDirectories או Directory.GetFiles ולפעמים זה להיפך, השאלה אם יש איזו עצה מבריקה איך אני אדע מראש באיזו דרך לילך? [או אולי להפעיל את שניהם ומי שיגמור ראשון לקחת אותו, ולהפסיק את השני....?]

          התכוונתי שהקריאה בשיטה שהבאת זה אותו עבודה בין אם זה תקיה ספציפית או הכל.

          ולדעתי הפעלה של שניהם לא יהיה טוב כי זה דיסק קשיח אחד והוא קורא לפי תור אז ככה זה ימעיט לך חצי מהביצועים.

          פורסם במקור בפורום CODE613 ב13/10/2013 14:39 (+03:00)

          תגובה 1 תגובה אחרונה
          0

          בא תתחבר לדף היומי!
          • התחברות

          • אין לך חשבון עדיין? הרשמה

          • התחברו או הירשמו כדי לחפש.
          • פוסט ראשון
            פוסט אחרון
          0
          • דף הבית
          • קטגוריות
          • פוסטים אחרונים
          • משתמשים
          • חיפוש
          • חוקי הפורום