• Vui lòng đọc nội qui diễn đàn để tránh bị xóa bài viết
  • Tìm kiếm trước khi đặt câu hỏi

Duyệt File/Folder theo chiều rộng (không Đệ Quy)

Các thủ thuật về hệ thống, thư mục, tập tin và mạng
User avatar
MATH-INFO
Thành viên năng nổ
Thành viên năng nổ
Posts: 55
Joined: Fri 15/07/2005 9:58 am
Location: TP.HCM, F12, Gò Vấp
Contact:

Duyệt File/Folder theo chiều rộng (không Đệ Quy)

Postby MATH-INFO » Wed 09/04/2008 7:35 pm

Thủ thuật: Duyệt File/Folder theo chiều rộng (không Đệ quy)
Tác giả: MATH-INFO
Mô tả: Thông thường chúng ta hay duyệt tập tin thư mục con bằng cách gọi đệ quy, đó là cách duyệt theo chiều sâu, khi đó sẽ có thể tốn bộ nhớ do windows sẽ tạo ra nhiều stack sau mỗi lời gọi đệ quy. Nay mình xin giới thiệu kỹ thuật duyệt file theo chiều rộng (không dùng đệ quy), bằng cách dùng thêm một Collection để lưu lại các sub folder chưa được duyệt, sub folder nào duyệt xong sẽ được remove ra khỏi Collection.
Đoạn code sau sẽ dùng hàm 2 hàm API để duyệt: FindFirstFile FindNextFile.
Áp dụng được cho tập tin thư mục có tên Unicode


Tạo ra một form gồm có một textbox Text1 và 1 button Command1, copy đoạn code dưới vào form.

Code: Select all

  1. Option Explicit
  2.  
  3. Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileW" (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long
  4. Private Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileW" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long
  5. Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
  6.  
  7. Const FILE_ATTRIBUTE_DIRECTORY = &H10
  8. Const FILE_ATTRIBUTE_HIDDEN = &H2
  9. Const FILE_ATTRIBUTE_NORMAL = &H80
  10. Const FILE_ATTRIBUTE_READONLY = &H1
  11. Const FILE_ATTRIBUTE_SYSTEM = &H4
  12.  
  13. Private Type FILETIME
  14.     dwLowDateTime As Long
  15.     dwHighDateTime As Long
  16. End Type
  17.  
  18.  
  19. Private Type WIN32_FIND_DATA
  20.     dwFileAttributes As Long
  21.     ftCreationTime As FILETIME
  22.     ftLastAccessTime As FILETIME
  23.     ftLastWriteTime As FILETIME
  24.     nFileSizeHigh As Long
  25.     nFileSizeLow As Long
  26.     dwReserved0 As Long
  27.     dwReserved1 As Long
  28.     cFileName As String * 255
  29.     cAlternate As String * 14
  30. End Type
  31.  
  32. Private Sub Command1_Click()
  33.     Dim DirCount As Integer, fileCount As Integer
  34.     WalkDir Text1.Text, DirCount, fileCount
  35.     MsgBox "Folder: " & DirCount & " - File: " & fileCount
  36. End Sub
  37.  
  38. Private Sub WalkDir(sFolder As String, DirCount As Integer, fileCount As Integer)
  39.     Dim myFolder As New Collection
  40.     Dim FileData As WIN32_FIND_DATA
  41.     Dim res As Long, hSearch  As Long, fileName As String
  42.    
  43.     DirCount = 0
  44.     fileCount = 0
  45.     myFolder.Add (sFolder)
  46.    
  47.     Do While (myFolder.Count)
  48.    
  49.         sFolder = myFolder.Item(1)
  50.         myFolder.Remove (1)
  51.        
  52.         hSearch = FindFirstFile(StrConv(sFolder & "\*.*", vbUnicode), FileData)
  53.         If (hSearch = -1) Then GoTo 1
  54.        
  55.         Do
  56.             fileName = TrimPath(FileData.cFileName)
  57.            
  58.             If (fileName <> ".") And (fileName <> "..") Then
  59.            
  60.                 If (FileData.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then
  61.                
  62.                     myFolder.Add (sFolder & "\" & fileName)
  63.                     DirCount = DirCount + 1
  64.                     '---------------'
  65.                     ' do some thing '
  66.                     '---------------'
  67.                 Else
  68.                
  69.                     fileCount = fileCount + 1
  70.                     '---------------'
  71.                     ' do some thing '
  72.                     '---------------'
  73.                 End If
  74.                
  75.             End If
  76.            
  77.             res = FindNextFile(hSearch, FileData)
  78.         Loop Until (res = 0)
  79.        
  80. 1:      FindClose (hSearch)
  81.  
  82.     Loop
  83. End Sub
  84.  
  85.  
  86. Private Function TrimPath(sPath As String) As String
  87.     Dim i As Integer
  88.    
  89.     sPath = StrConv(sPath, vbFromUnicode)
  90.    
  91.     i = InStr(sPath, Chr(0))
  92.     If i > 0 Then sPath = Left(sPath, i - 1)
  93.     TrimPath = sPath
  94. End Function
  95.  
  96.  


[size=100][color=#0000FF][b]"The essential in the existence of a man like me is what he thinks and how he thinks, not what he does or suffers."[/b][/color][/size]
[img]http://vn47.com/DKhanh/Images/signature.png[/img]

User avatar
MATH-INFO
Thành viên năng nổ
Thành viên năng nổ
Posts: 55
Joined: Fri 15/07/2005 9:58 am
Location: TP.HCM, F12, Gò Vấp
Contact:

Re: Duyệt File/Folder theo chiều rộng (không Đệ Quy)

Postby MATH-INFO » Wed 09/04/2008 9:37 pm

"MATH-INFO viết lại bài...
Mai tôi sẽ đọc kỹ vì giờ ngầy ngật quá!"

Coi kỹ lại đi anh bạn, viết lại đâu mà viết lại, nếu bạn không coi kịp thì mai post cũng được, mắc mớ gì phải thông báo điều đó gấp vậy.
Cái này ban đầu là tui làm bên C++, dùng ứng dụng cấu trúc hàng đợi (queue), chuyển qua vb không có con trỏ nên mới dùng collection, tui cũng đã coi trong vblib và search trên diễn đàn thấy không có nên mới post.

Mấy hằng attribute trên tại sao lại xóa làm gì, đoạn code trên chỉ là demo mẫu cách thức duyệt file thôi, còn tủy mục đích mỗi người muốn dùng như thế nào mà có thể filter lại file thông qua các attribute đó chứ
[size=100][color=#0000FF][b]"The essential in the existence of a man like me is what he thinks and how he thinks, not what he does or suffers."[/b][/color][/size]
[img]http://vn47.com/DKhanh/Images/signature.png[/img]

User avatar
truongphu
VIP
VIP
Posts: 4776
Joined: Sun 04/11/2007 10:57 am
Location: Cam Đức, Khánh hòa
Has thanked: 14 times
Been thanked: 522 times

Re: Duyệt File/Folder theo chiều rộng (không Đệ Quy)

Postby truongphu » Thu 10/04/2008 12:05 am

1- Tôi Thành thật xin lỗi MATH-INFO lời phát biểu ở trên thiếu cẩn trọng, xúc phạm đến MATH-INFO, hy vọng MATH-INFO sẽ bỏ qua việc nầy.
2- Đúng là cấu trúc duyệt Folder và File của MATH-INFO gọn nhẹ hơn của VBLib (tuy kết quả fileCount 2 bên khác nhau trong cùng thư mục C:\Windows, *.*)
3- Function TrimPath có lẽ tương đương với Function StripNulls chăng?:

Code: Select all

  1. Function StripNulls(OriginalStr As String) As String
  2.     If (InStr(OriginalStr, Chr(0)) > 0) Then StripNulls = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
  3. End Function
o0o--truongphu--o0o

.........
Ghé thăm:
Chuyện Linh Tinh

User avatar
MATH-INFO
Thành viên năng nổ
Thành viên năng nổ
Posts: 55
Joined: Fri 15/07/2005 9:58 am
Location: TP.HCM, F12, Gò Vấp
Contact:

Re: Duyệt File/Folder theo chiều rộng (không Đệ Quy)

Postby MATH-INFO » Thu 10/04/2008 3:26 pm

truongphu wrote:tuy kết quả fileCount 2 bên khác nhau trong cùng thư mục C:\Windows, *.*

Mình đã test nhiều thư mục và nó trả về kết quả đúng như so với windows explorer, tuy nhiên đối với thư mục C:\Windows thì đoạn code của mình đếm dư 1 file và 1 folder so với W.Explorer (không hiểu vì sao), còn đoạn code trong vblib thì cho ra kết quả dư nhiều hơn. :-??

truongphu wrote:3- Function TrimPath có lẽ tương đương với Function StripNulls chăng?:

Nếu bạn hay dùng đến các hàm api có liên quan đến chuỗi thì bạn sẽ phải thuờng xuyên dùng đến hàm bên trên.
[size=100][color=#0000FF][b]"The essential in the existence of a man like me is what he thinks and how he thinks, not what he does or suffers."[/b][/color][/size]
[img]http://vn47.com/DKhanh/Images/signature.png[/img]

DoMinhTho
Thành viên tích cực
Thành viên tích cực
Posts: 108
Joined: Sun 11/01/2009 11:40 am
Has thanked: 2 times
Been thanked: 1 time

Re: Duyệt File/Folder theo chiều rộng (không Đệ Quy)

Postby DoMinhTho » Sun 08/03/2009 11:30 am

Nếu mình muốn hiển thị và add các file đang được xét vào 1 listbox thì add giá trị nào bạn?
Dispirited Fact

DoMinhTho
Thành viên tích cực
Thành viên tích cực
Posts: 108
Joined: Sun 11/01/2009 11:40 am
Has thanked: 2 times
Been thanked: 1 time

Re: Duyệt File/Folder theo chiều rộng (không Đệ Quy)

Postby DoMinhTho » Sun 08/03/2009 1:48 pm

Code: Select all

  1. If (fileName <> ".") And (fileName <> "..") Then
  2.            
  3.                 If (FileData.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then
  4.                
  5.                     myFolder.Add (sFolder & "\" & fileName)
  6.                     DirCount = DirCount + 1
  7.                    
  8.                 Else
  9.                
  10.                     fileCount = fileCount + 1
  11.                   'TẠI ĐIỂM NÀY MÌNH THÊM 1 QUY TRÌNH ADD GIÁ TRỊ DÒ ĐƯỢC VÀO 1 LIST.                    listbox1.additem (sFolder & "\" & fileName)
  12.                   'NHUNG SAO KẾT QUẢ HIỂN THỊ CÓ DẠNG : I:\\FOLDER1\EXAM.TXT
  13.                    '                                                         I:\\FOLDER2\EXAM.TXT
  14.                    'CÒN SubFolder chứa 2 folder con la FOLDER1 và FOLDER2 thì ko hiển thị rõ mà chỉ hiển thị dưới dạng :I:\(Sub Folder ko hien thi)\Folder con\ten file.txt
  15.                    End If
  16.  

Hàm này tông kết và liệt kê các folder và file dồn tại 1 thời điểm nên làm cho chương trình bị treo (trong quá trình thực hiện WalkDir) và hơi khó để kiểm soát quá trình quét+list File .Ko biết có cách nào phân qui trình ra từng bước như listing lần lượt từng file trong folder.Nếu tới file cuối cùng của folder đó thì path nhảy ra khỏi folder đó và tới folder tiếp theo để xét tiếp.
Em đang tìm cách làm lại quá trình đó,nếu ai bít thì chỉ cho em với nhé.
Dispirited Fact

newbi
Thành viên chính thức
Thành viên chính thức
Posts: 46
Joined: Thu 20/11/2008 8:01 am

Re: Duyệt File/Folder theo chiều rộng (không Đệ Quy)

Postby newbi » Thu 19/03/2009 5:52 pm

Cũng nhanh thật. Em ứng dụng để làm tiện ích thay đổi thuộc tính cho tất cả thư mục con của thư mục(gồm hình nền , màu chữ , icon, background,...) . Nói chung chạy tốt.Một kclick chuột phải và mọi thứ ok. Chỉ có điều phải thêm hàm nhận biết kí tự unicode( nếu không sẽ lỗi) nên nếu thư mục mà có cỡ 500 thư mục con thì máy chạy è cổ.

User avatar
truongphu
VIP
VIP
Posts: 4776
Joined: Sun 04/11/2007 10:57 am
Location: Cam Đức, Khánh hòa
Has thanked: 14 times
Been thanked: 522 times

Re: Duyệt File/Folder theo chiều rộng (không Đệ Quy)

Postby truongphu » Thu 19/03/2009 6:07 pm

newbi wrote:Chỉ có điều phải thêm hàm nhận biết kí tự unicode( nếu không sẽ lỗi)


Bài viết của anh MATH-INFO chạy nhanh, tôt. Nhưng vì Vb6 nên không hổ trợ Unicode.
Muốn duyệt file và folder hổ trợ Unicode, bạn phải dùng .net hay vbs:

Lấy Danh sách Tập tin trong thư mục

Trong code có dùng list1, bạn phải dùng ListBox1 (MS Form 2.0), set font nhóm unicode,
câu code dòng 9 chỉnh lại : ListBox1.AddItem...
Chỉ thế thôi
o0o--truongphu--o0o

.........
Ghé thăm:
Chuyện Linh Tinh

User avatar
MATH-INFO
Thành viên năng nổ
Thành viên năng nổ
Posts: 55
Joined: Fri 15/07/2005 9:58 am
Location: TP.HCM, F12, Gò Vấp
Contact:

Re: Duyệt File/Folder theo chiều rộng (không Đệ Quy)

Postby MATH-INFO » Fri 20/03/2009 8:56 am

À code của mình sử dùng hàm api có hỗ trợ unicode, nó đọc đọc được và duyệt qua hết cả các tập tin unicode, nhưng do control vb6 không hõ trợ unicode, nên nó sẽ hiện ra không đúng. Nhưng thực sự là nó duyệt đươc hết.
[size=100][color=#0000FF][b]"The essential in the existence of a man like me is what he thinks and how he thinks, not what he does or suffers."[/b][/color][/size]
[img]http://vn47.com/DKhanh/Images/signature.png[/img]

newbi
Thành viên chính thức
Thành viên chính thức
Posts: 46
Joined: Thu 20/11/2008 8:01 am

Re: Duyệt File/Folder theo chiều rộng (không Đệ Quy)

Postby newbi » Fri 20/03/2009 5:24 pm

Đúng vậy, duyệt thì ok rồi. chỉ có điều không thể thao tác với file/folder có path unicode được.Đành phải viết một hàm nhận biết kí tự lạ mà bỏ qua file/folder đó khi chạy thôi.

Function kitula(st As String) As Boolean
Dim i As Integer
kitula = False
For i = 1 To Len(st)
If (InStr(1, " àáúù~qwertyuiopasdfghjklzxcvbnm1234567890\-/.^@*`_:", LCase(Mid(st, i, 1)))) = 0 Then
kitula = True
End If
Next
End Function

Cách này thủ công quá.Ai có cách hay hơn chỉ nha.

User avatar
MATH-INFO
Thành viên năng nổ
Thành viên năng nổ
Posts: 55
Joined: Fri 15/07/2005 9:58 am
Location: TP.HCM, F12, Gò Vấp
Contact:

Re: Duyệt File/Folder theo chiều rộng (không Đệ Quy)

Postby MATH-INFO » Sun 29/03/2009 6:40 pm

Vẫn thao tác được với các file name unicode chứ, tất nhiên là dùng các hàm support unicode (đọc ghi file = api function thay vì hàm đọc file của vb).

Chỉ là hiển thị ra không được thôi.
[size=100][color=#0000FF][b]"The essential in the existence of a man like me is what he thinks and how he thinks, not what he does or suffers."[/b][/color][/size]
[img]http://vn47.com/DKhanh/Images/signature.png[/img]

chipmunk
Thành viên tích cực
Thành viên tích cực
Posts: 125
Joined: Mon 28/03/2011 9:19 am
Has thanked: 2 times
Been thanked: 5 times

Re: Duyệt File/Folder theo chiều rộng (không Đệ Quy)

Postby chipmunk » Thu 07/04/2011 10:36 am

Đọc code không hiểu lắm, có phải là liệt kê file và folder trong sfolder không


Return to “[VB] Hệ thống - Tập tin - Thư mục và Mạng”

Who is online

Users browsing this forum: No registered users and 1 guest