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
Post Reply
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)

Post by MATH-INFO »

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

Option Explicit Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileW" (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As LongPrivate Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileW" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As LongPrivate Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long Const FILE_ATTRIBUTE_DIRECTORY = &H10Const FILE_ATTRIBUTE_HIDDEN = &H2Const FILE_ATTRIBUTE_NORMAL = &H80Const FILE_ATTRIBUTE_READONLY = &H1Const FILE_ATTRIBUTE_SYSTEM = &H4 Private Type FILETIME    dwLowDateTime As Long    dwHighDateTime As LongEnd Type  Private Type WIN32_FIND_DATA    dwFileAttributes As Long    ftCreationTime As FILETIME    ftLastAccessTime As FILETIME    ftLastWriteTime As FILETIME    nFileSizeHigh As Long    nFileSizeLow As Long    dwReserved0 As Long    dwReserved1 As Long    cFileName As String * 255    cAlternate As String * 14End Type Private Sub Command1_Click()    Dim DirCount As Integer, fileCount As Integer    WalkDir Text1.Text, DirCount, fileCount    MsgBox "Folder: " & DirCount & " - File: " & fileCountEnd Sub Private Sub WalkDir(sFolder As String, DirCount As Integer, fileCount As Integer)    Dim myFolder As New Collection    Dim FileData As WIN32_FIND_DATA    Dim res As Long, hSearch  As Long, fileName As String        DirCount = 0    fileCount = 0    myFolder.Add (sFolder)        Do While (myFolder.Count)            sFolder = myFolder.Item(1)        myFolder.Remove (1)                hSearch = FindFirstFile(StrConv(sFolder & "\*.*", vbUnicode), FileData)        If (hSearch = -1) Then GoTo 1                Do            fileName = TrimPath(FileData.cFileName)                        If (fileName <> ".") And (fileName <> "..") Then                            If (FileData.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then                                    myFolder.Add (sFolder & "\" & fileName)                    DirCount = DirCount + 1                    '---------------'                    ' do some thing '                    '---------------'                Else                                    fileCount = fileCount + 1                    '---------------'                    ' do some thing '                    '---------------'                End If                            End If                        res = FindNextFile(hSearch, FileData)        Loop Until (res = 0)        1:      FindClose (hSearch)     LoopEnd Sub  Private Function TrimPath(sPath As String) As String    Dim i As Integer        sPath = StrConv(sPath, vbFromUnicode)        i = InStr(sPath, Chr(0))    If i > 0 Then sPath = Left(sPath, i - 1)    TrimPath = sPathEnd Function  
"The essential in the existence of a man like me is what he thinks and how he thinks, not what he does or suffers."
[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)

Post by MATH-INFO »

"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ứ
"The essential in the existence of a man like me is what he thinks and how he thinks, not what he does or suffers."
[img]http://vn47.com/DKhanh/Images/signature.png[/img]
User avatar
truongphu
VIP
VIP
Posts: 4781
Joined: Sun 04/11/2007 10:57 am
Location: Cam Đức, Khánh hòa
Has thanked: 14 times
Been thanked: 525 times

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

Post by truongphu »

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

Function StripNulls(OriginalStr As String) As String    If (InStr(OriginalStr, Chr(0)) > 0) Then StripNulls = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)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)

Post by MATH-INFO »

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.
"The essential in the existence of a man like me is what he thinks and how he thinks, not what he does or suffers."
[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)

Post by DoMinhTho »

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)

Post by DoMinhTho »

Code: Select all

If (fileName <> ".") And (fileName <> "..") Then                            If (FileData.dwFileAttributes And FILE_ATTRIBUTE_DIRECTORY) Then                                    myFolder.Add (sFolder & "\" & fileName)                    DirCount = DirCount + 1                                   Else                                    fileCount = fileCount + 1                  [color=#008000]'TẠI ĐIỂM NÀY MÌNH THÊM 1 QUY TRÌNH ADD GIÁ TRỊ DÒ ĐƯỢC VÀO 1 LIST.[/color]                    [color=#000000]listbox1.additem (sFolder & "\" & fileName)[/color]                  [color=#008000] 'NHUNG SAO KẾT QUẢ HIỂN THỊ CÓ DẠNG : I:\\FOLDER1\EXAM.TXT                   '                                                         I:\\FOLDER2\EXAM.TXT                   '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[/color]                   End If 
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)

Post by newbi »

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: 4781
Joined: Sun 04/11/2007 10:57 am
Location: Cam Đức, Khánh hòa
Has thanked: 14 times
Been thanked: 525 times

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

Post by truongphu »

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)

Post by MATH-INFO »

À 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.
"The essential in the existence of a man like me is what he thinks and how he thinks, not what he does or suffers."
[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)

Post by newbi »

Đú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)

Post by MATH-INFO »

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.
"The essential in the existence of a man like me is what he thinks and how he thinks, not what he does or suffers."
[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)

Post by chipmunk »

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

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