Cách kiểm tra sự tồn tại của tập tin được nhiều lập trình viên kỳ cựu ưa dùng (1 người xem)

Người dùng đang xem chủ đề này

Tôi tuân thủ nội quy khi đăng bài

nguyendang95

Thành viên bị đình chỉ hoạt động
Thành viên bị đình chỉ hoạt động
Tham gia
25/5/22
Bài viết
211
Được thích
179
Thường thì trong VBA có nhiều cách để kiểm tra sự tồn tại của tập tin:
Bằng thư viện COM, ví dụ:
  • FileSystemObject
  • ...
Bằng một số hàm Win32 API, ví dụ:
  • CreateFile
  • FindFirstFile
  • PathFileExists (Shlwapi)
  • ...
Tuy nhiên những cách trên đều đòi hỏi phải mất vài dòng mã để khai báo và hoàn thành công việc trong khi yêu cầu chỉ là biết được tập tin có tồn tại hay không. Trong giới lập trình Windows, người ta đã thống nhất chỉ cần sử dụng duy nhất một hàm GetFileAttributes là đủ để kiểm tra sự tồn tại của tập tin thông qua tìm kiếm thuộc tính (attribute) FILE_ATRRIBUTE_DIRECTORY có trong tập tin hay không.

Mã:
Private Const INVALID_FILE_ATTRIBUTES = -1
Private Const FILE_ATTRIBUTE_DIRECTORY = &H10
Private Declare PtrSafe Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesW" (ByVal lpFileName As LongPtr) As Long

Private Function FileExists(ByVal Path As String) As Boolean
    If (Path = vbNullString) Then
        FileExists = False
        Exit Function
    End If
    Dim lngAttr As Long
    lngAttr = GetFileAttributes(StrPtr(Path))
    FileExists = (lngAttr <> INVALID_FILE_ATTRIBUTES And Not (lngAttr = FILE_ATTRIBUTE_DIRECTORY))
End Function

Ví dụ, để kiểm tra xem tập tin với đường dẫn Y:\dstockbot.xlsb có đang tồn tại hay không.

Mã:
Private Sub Test()
    Const strPath As String = "Y:\dstockbot.xlsb"
    Dim strAnswer As String
    strAnswer = IIf(FileExists(strPath), strPath & " exists", strPath & " does not exist")
    Debug.Print strAnswer
End Sub

Tham khảo bài viết của Raymond Chen, một trong những kiến trúc sư đời đầu của hệ điều hành Windows.
Superstition: Why is GetFileAttributes the way old-timers test file existence?
 
Lần chỉnh sửa cuối:
Tôi thắc mắc 1 chút là với cách này thì cũng khai báo vài dòng rồi phải chép thêm 1 cái hàm FileExists nữa mới dùng được. Vậy chẳng phải dài dòng hơn sao?
 
Upvote 0
Tôi thắc mắc 1 chút là với cách này thì cũng khai báo vài dòng rồi phải chép thêm 1 cái hàm FileExists nữa mới dùng được. Vậy chẳng phải dài dòng hơn sao?
Cái đáng giá ở đây là chỉ cần gọi một hàm GetFileAttributes duy nhất là xác định được tập tin có tồn tại hay không, còn việc bạn viết code dài hay ngắn để hỗ trợ triển khai logic sử dụng hàm đó thì là do bạn mà.
 
Upvote 0
có nhiều hàm kiểm tra file tốt tuy nhiên thử duyệt 2000 vòng lặp kiểm tra file và đo thời gian xem hàm nào nhanh nhất thì dùng hàm đó
 
Upvote 0
Cái đáng giá ở đây là chỉ cần gọi một hàm GetFileAttributes duy nhất là xác định được tập tin có tồn tại hay không, còn việc bạn viết code dài hay ngắn để hỗ trợ triển khai logic sử dụng hàm đó thì là do bạn mà.
Vậy chỉ cần khai báo 1 dòng cho hàm rồi dùng. Nếu kết quả trả về là 32 thì tập tin tồn tại, còn khác đi là không tồn tại?
 
Upvote 0
Vậy chỉ cần khai báo 1 dòng cho hàm rồi dùng. Nếu kết quả trả về là 32 thì tập tin tồn tại, còn khác đi là không tồn tại?
Điều kiện xác định một tập tin có tồn tại hay không là ở đây:
FileExists = (lngAttr <> INVALID_FILE_ATTRIBUTES And Not (lngAttr = FILE_ATTRIBUTE_DIRECTORY))
Tập tin không tồn tại khi:
  • Giá trị thuộc tính trả về là INVALID_FILE_ATTRIBUTES, tức là hiện không có tập tin nào.
  • Hoặc có thuộc tính FILE_ATTRIBUTE_DIRECTORY (chỉ ra đây là thư mục chứ không phải là tập tin).
 
Lần chỉnh sửa cuối:
Upvote 0
Tôi thường dùng hàm UDF này (hình như là của Anh @ NDU 098...) mà chả hiểu gì, chỉ thấy dùng cho kết quả đúng, chưa thấy sai bao giờ. Hay là chưa gặp các trường hợp đặc biệt,...
Mã:
Function FileExists(sFullPath As String) As Boolean
  FileExists = CBool(Len(Dir$(sFullPath)) > 0)
End Function
Kiếm tra sự tồn tại của Sheet thì
Mã:
Public Function WsExit(wsName As String) As Boolean
    On Error Resume Next
    WsExit = CBool(Len(Worksheets(wsName).Name) > 0)
End Function
Xin ý kiến chỉ giáo.
Trân trọng cảm ơn.
 
Upvote 0
Tôi thường dùng hàm UDF này (hình như là của Anh @ NDU 098...) mà chả hiểu gì, chỉ thấy dùng cho kết quả đúng, chưa thấy sai bao giờ. Hay là chưa gặp các trường hợp đặc biệt,...
Mã:
Function FileExists(sFullPath As String) As Boolean
  FileExists = CBool(Len(Dir$(sFullPath)) > 0)
End Function
Kiếm tra sự tồn tại của Sheet thì
Mã:
Public Function WsExit(wsName As String) As Boolean
    On Error Resume Next
    WsExit = CBool(Len(Worksheets(wsName).Name) > 0)
End Function
Xin ý kiến chỉ giáo.
Trân trọng cảm ơn.
Hàm Dir() này không dùng được cho các thư mục, tên file có dấu tiếng Việt đâu bác.
 
Upvote 0
Tôi thường dùng hàm UDF này (hình như là của Anh @ NDU 098...) mà chả hiểu gì, chỉ thấy dùng cho kết quả đúng, chưa thấy sai bao giờ. Hay là chưa gặp các trường hợp đặc biệt,...
Mã:
Function FileExists(sFullPath As String) As Boolean
  FileExists = CBool(Len(Dir$(sFullPath)) > 0)
End Function
Hàm Dir$ không hỗ trợ mã Unicode nên thư mục hoặc file có dấu tiếng Việt thì tịt.
Bài đã được tự động gộp:

Hàm Dir() này không dùng được cho các thư mục, tên file có dấu tiếng Việt đâu bác.
Trả lời xong thấy ông Kẹ ở trên rồi, hoảng hồn --=0
 
Upvote 0
Upvote 0
có nhiều hàm kiểm tra file tốt tuy nhiên thử duyệt 2000 vòng lặp kiểm tra file và đo thời gian xem hàm nào nhanh nhất thì dùng hàm đó
Cứ thử chạy kiểm tra với số lượng tập tin trên một ổ đĩa mạng (network share) là biết hiệu năng ra sao thôi.
 
Upvote 0
Tôi lạy ông, ông chưa đủ kiến thức mà đi chỉ dẫn người ta. Vô tội vạ.
UTF8 còn chưa biết còn đi hướng dẫn mã.
Mã ở trên chẳng chạy được đa nền tảng. Chẳng tương thích ngược.

Học thêm nhé. Mới tập viết mã thì mình bớt đu đưa đăng bài thì mình xem mã đúng chưa chưa đúng mình để là bài hỏi. Sao lại là đi hướng dẫn.

Trót dại đi chép mã ông nội này người ơi. Nó sai mà nó "dốt" sao đâu.
(lngAttr <> INVALID_FILE_ATTRIBUTES And Not (lngAttr = FILE_ATTRIBUTE_DIRECTORY))

Sửa lại dùm tui cái:
(lngAttr <> INVALID_FILE_ATTRIBUTES And (lngAttr AND FILE_ATTRIBUTE_DIRECTORY) = 0)

Các định nghĩa hằng số là bit flags trong Win32 API, trời đất sao mà dùng với NOT và so sánh bằng trong trường hợp này được trời
Khi FILE_ATTRIBUTE_DIRECTORY có trong flag Nếu nó có thêm flag FILE_ATTRIBUTE_ENCRYPTED hoặc FILE_ATTRIBUTE_COMPRESSED thành ra là tệp tồn tại à ông thần.

Diễn đàn xem xét những trường hợp đăng bài chia sẻ kiểu "tào lao", sai không đăng hỏi lại đăng chỉ dẫn là sao?

JavaScript:
Private Const INVALID_FILE_ATTRIBUTES = -1
Private Const FILE_ATTRIBUTE_DIRECTORY = &H10
#If VBA7 Then
Private Declare PtrSafe Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesW" (ByVal lpFileName As LongPtr) As Long
#Else
Private Declare Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesW" (ByVal lpFileName As Long) As Long
#End If

Private Function FileExists(ByVal Path As String) As Boolean
    If (Path = vbNullString) Then  Exit Function
    Dim lngAttr As Long
    lngAttr = GetFileAttributes(StrPtr(Path))
    FileExists = (lngAttr <> INVALID_FILE_ATTRIBUTES And (lngAttr AND FILE_ATTRIBUTE_DIRECTORY) = 0)
End Function

Thuật ngữ bit flags chưa nắm mà đi hướng dẫn người ta như đúng rồi.

Tất cả Flags đây:

Hằng số/giá trịSự miêu tả
FILE_ATTRIBUTE_READONLY
1 (0x00000001)
Tệp chỉ đọc. Các ứng dụng có thể đọc tệp, nhưng không thể ghi hoặc xóa tệp. Thuộc tính này không được áp dụng cho thư mục.
FILE_ATTRIBUTE_HIDDEN
2 (0x00000002)
Tệp hoặc thư mục này bị ẩn. Nó không được hiển thị trong danh sách thư mục thông thường.
FILE_ATTRIBUTE_SYSTEM
4 (0x00000004)
Một tập tin hoặc thư mục mà hệ điều hành sử dụng một phần hoặc sử dụng độc quyền.
FILE_ATTRIBUTE_DIRECTORY
16 (0x00000010)
Mã định danh cho một thư mục.
FILE_ATTRIBUTE_ARCHIVE
32 (0x00000020)
Tệp hoặc thư mục là tệp hoặc thư mục lưu trữ. Các ứng dụng thường sử dụng thuộc tính này để đánh dấu các tệp cần sao lưu hoặc xóa.
FILE_ATTRIBUTE_DEVICE
64 (0x00000040)
Giá trị này chỉ dành cho mục đích sử dụng của hệ thống.
FILE_ATTRIBUTE_NORMAL
128 (0x00000080)
Một tập tin không có thuộc tính nào khác được thiết lập. Thuộc tính này chỉ hợp lệ khi được sử dụng một mình.
FILE_ATTRIBUTE_TEMPORARY
256 (0x00000100)
Tệp được sử dụng để lưu trữ tạm thời. Hệ thống tệp tránh ghi dữ liệu trở lại bộ nhớ chính nếu có đủ bộ nhớ cache, vì thông thường, ứng dụng sẽ xóa tệp tạm thời sau khi đóng kết nối. Trong trường hợp đó, hệ thống có thể hoàn toàn tránh việc ghi dữ liệu. Ngược lại, dữ liệu sẽ được ghi sau khi kết nối đóng.
FILE_ATTRIBUTE_SPARSE_FILE
512 (0x00000200)
Một tập tin là tập tin thưa.
FILE_ATTRIBUTE_REPARSE_POINT
1024 (0x00000400)
Tệp hoặc thư mục có điểm phân tích lại liên kết, hoặc tệp là liên kết tượng trưng.
FILE_ATTRIBUTE_COMPRESSED
2048 (0x00000800)
Tệp hoặc thư mục được nén. Đối với tệp, toàn bộ dữ liệu trong tệp được nén. Đối với thư mục, nén là chế độ mặc định cho các tệp và thư mục con mới được tạo.
FILE_ATTRIBUTE_OFFLINE
4096 (0x00001000)
Dữ liệu của một tập tin không khả dụng ngay lập tức. Thuộc tính này cho biết dữ liệu tập tin đã được di chuyển vật lý đến bộ nhớ ngoại tuyến. Thuộc tính này được sử dụng bởi Remote Storage, phần mềm quản lý lưu trữ phân cấp. Các ứng dụng không nên tự ý thay đổi thuộc tính này.
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
8192 (0x00002000)
Tệp hoặc thư mục này sẽ không được lập chỉ mục bởi dịch vụ lập chỉ mục nội dung.
FILE_ATTRIBUTE_ENCRYPTED
16384 (0x00004000)
Tệp hoặc thư mục được mã hóa. Đối với tệp, tất cả các luồng dữ liệu trong tệp đều được mã hóa. Đối với thư mục, mã hóa là mặc định cho các tệp và thư mục con mới được tạo.
FILE_ATTRIBUTE_INTEGRITY_STREAM
32768 (0x00008000)
Luồng dữ liệu thư mục hoặc người dùng được cấu hình với tính toàn vẹn (chỉ được hỗ trợ trên các ổ đĩa ReFS). Nó không được bao gồm trong danh sách thư mục thông thường. Cài đặt toàn vẹn vẫn được giữ nguyên với tệp ngay cả khi nó được đổi tên. Nếu một tệp được sao chép, tệp đích sẽ được thiết lập tính toàn vẹn nếu tệp nguồn hoặc thư mục đích được thiết lập tính toàn vẹn.
Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 và Windows XP: Cờ này không được hỗ trợ cho đến Windows Server 2012.
FILE_ATTRIBUTE_VIRTUAL
65536 (0x00010000)
Giá trị này chỉ dành cho mục đích sử dụng của hệ thống.
FILE_ATTRIBUTE_NO_SCRUB_DATA
131072 (0x00020000)
Luồng dữ liệu người dùng không được đọc bởi trình quét tính toàn vẹn dữ liệu nền (còn gọi là trình làm sạch). Khi được thiết lập trên một thư mục, nó chỉ cung cấp tính kế thừa. Cờ này chỉ được hỗ trợ trên Storage Spaces và các ổ đĩa ReFS. Nó không được bao gồm trong danh sách thư mục thông thường.
Windows Server 2008 R2, Windows 7, Windows Server 2008, Windows Vista, Windows Server 2003 và Windows XP: Cờ này không được hỗ trợ cho đến Windows 8 và Windows Server 2012.
FILE_ATTRIBUTE_EA
262144 (0x00040000)
Tệp hoặc thư mục có thuộc tính mở rộng.

QUAN TRỌNG: Hằng số này chỉ dành cho mục đích sử dụng nội bộ.
FILE_ATTRIBUTE_PINNED
524288 (0x00080000)
Thuộc tính này thể hiện ý định của người dùng rằng tệp hoặc thư mục cần được giữ nguyên trạng thái hiện diện cục bộ ngay cả khi không được truy cập tích cực. Thuộc tính này được sử dụng với phần mềm quản lý lưu trữ phân cấp.
FILE_ATTRIBUTE_UNPINNED
1048576 (0x00100000)
Thuộc tính này cho biết tệp hoặc thư mục không nên được lưu trữ đầy đủ cục bộ trừ khi đang được truy cập tích cực. Thuộc tính này được sử dụng với phần mềm quản lý lưu trữ phân cấp.
FILE_ATTRIBUTE_RECALL_ON_OPEN
262144 (0x00040000)
Thuộc tính này chỉ xuất hiện trong các lớp liệt kê thư mục (FILE_DIRECTORY_INFORMATION, FILE_BOTH_DIR_INFORMATION, v.v.). Khi thuộc tính này được thiết lập, điều đó có nghĩa là tệp hoặc thư mục không có hiện diện vật lý trên hệ thống cục bộ; mục này là ảo. Việc mở mục này sẽ tốn kém hơn bình thường, ví dụ: nó sẽ khiến ít nhất một phần của mục đó được lấy từ kho lưu trữ từ xa.
FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS
4194304 (0x00400000)
Khi thuộc tính này được đặt, điều đó có nghĩa là tệp hoặc thư mục không hoàn toàn hiện diện cục bộ. Đối với tệp, điều đó có nghĩa là không phải tất cả dữ liệu của nó đều nằm trên bộ nhớ cục bộ (ví dụ: nó có thể là tệp thưa với một số dữ liệu vẫn còn trên bộ nhớ từ xa). Đối với thư mục, điều đó có nghĩa là một số nội dung thư mục đang được ảo hóa từ một vị trí khác. Việc đọc tệp / liệt kê thư mục sẽ tốn kém hơn bình thường, ví dụ: nó sẽ khiến ít nhất một số nội dung tệp/thư mục được lấy từ bộ nhớ từ xa. Chỉ những người gọi ở chế độ kernel mới có thể đặt bit này.

Các bộ lọc nhỏ của hệ thống tệp dưới phạm vi độ cao 180000 – 189999 (Nhóm thứ tự tải HSM FSFilter) không được thực hiện các thao tác đọc hoặc ghi được lưu vào bộ nhớ cache có mục tiêu đối với các tệp có thuộc tính này được đặt. Điều này có thể dẫn đến ô nhiễm bộ nhớ cache và khả năng làm hỏng tệp
 
Lần chỉnh sửa cuối:
Upvote 0
Yêu cầu 2 thành viên ngưng tranh luận căng thẳng, đặc biệt thành viên HeSanbi đang mạt sát đối phương bằng từ ngữ không hay. Nếu không ngưng ngay lập tức, cả 2 sẽ bị ban nick.
 
Upvote 0

Bài viết mới nhất

Back
Top Bottom