2009-10-29 3 views
27

Delphi 2010 có một bộ các chức năng truy cập tập tin mới trong IOUtils.pas (Tôi đặc biệt thích các phiên bản UTC của các hàm liên quan đến ngày tháng). Những gì tôi bỏ lỡ cho đến nay là một cái gì đó nhưNhận kích thước của một tệp trong Delphi 2010 trở lên?

TFile.GetSize (const Path : String) 

Delphi 2010-cách nào để có được kích thước của một tệp? Tôi có phải quay lại và sử dụng FindFirst để truy cập TSearchRec.FindData không?

Cảm ơn.

+1

Chỉ cần nhìn vào thư viện mã JEDI tại chức năng FileGetSize của chúng. Nó, trên thực tế, chỉ sử dụng phương pháp FindFirst. –

+0

@J__ tại sao không phải là câu trả lời?thêm liên kết đến JCL wiki và tải xuống JCL - và điều đó sẽ tạo thành một kết quả tốt –

+0

Vui lòng bỏ phiếu cho http://qc.embarcadero.com/wc/qcmain.aspx?d=110073 –

Trả lời

46

Tôi không chắc chắn có cách "Delphi 2010" hay không, nhưng có Windows way that doesn't involve FindFirst and all that jazz.

Tôi đã ném cùng chuyển đổi Delphi này của thường trình đó (và trong quá trình sửa đổi nó để xử lý> tệp kích thước 4GB, bạn nên cần điều đó).

function FileSize(const aFilename: String): Int64; 
    var 
    info: TWin32FileAttributeData; 
    begin 
    result := -1; 

    if NOT GetFileAttributesEx(PWideChar(aFileName), GetFileExInfoStandard, @info) then 
     EXIT; 

    result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32); 
    end; 

Bạn thực sự có thể chỉ cần sử dụng GetFileSize() nhưng điều này đòi hỏi một HANDLE tập tin, không chỉ là một tên tập tin, và tương tự như GetCompressedFileSize() gợi ý, điều này đòi hỏi hai biến để gọi. Cả hai GetFileSize()GetCompressedFileSize() quá tải giá trị trả về của chúng, vì vậy kiểm tra thành công và đảm bảo kết quả hợp lệ chỉ hơi rắc rối hơn một chút.

GetFileSize Ex() tránh nitty gritty của kích thước tập tin xử lý> 4GB và phát hiện kết quả đúng, nhưng cũng đòi hỏi một HANDLE tập tin, chứ không phải là một cái tên, và (như của Delphi 2009 ít nhất, tôi thiên đường 't kiểm tra 2010) không phải là tuyên bố cho bạn trong VCL bất cứ nơi nào, bạn sẽ phải cung cấp tờ khai nhập khẩu của riêng bạn.

+1

-1: Chức năng của bạn không hoạt động trên các tập tin được đánh số –

+1

Smasher không giải thích loại tập tin nào sẽ không nhận được. –

+6

Đối với một tệp nén (zip, rar, 7z v.v.), nó sẽ báo cáo kích thước của tệp lưu trữ theo byte, không phải kích thước của nội dung được giải nén. Nhưng đối với một tệp ZIP, kích thước của tệp là kích thước của tệp lưu trữ. Đối với một tệp trên ổ đĩa nén, nó sẽ báo cáo kích thước của tệp giải nén, đó là những gì bạn muốn vì bạn đang yêu cầu kích thước của đối tượng lưu trữ (tệp) chứ không phải phương tiện lưu trữ vật lý (hệ điều hành được nén). Đối với các tệp <4GB, cách tiếp cận bạn đề xuất khá phức tạp hơn trừ khi bạn ngây thơ và không chính xác * giả sử * rằng tất cả các tệp luôn <4GB – Deltics

4

Bạn cũng có thể sử dụng DSiFileSize từ DSiWin32. Hoạt động trong "tất cả" Delphis. Bên trong nó gọi là CreateFile và GetFileSize.

function DSiFileSize(const fileName: string): int64; 
    var 
    fHandle: DWORD; 
    begin 
    fHandle := CreateFile(PChar(fileName), 0, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); 
    if fHandle = INVALID_HANDLE_VALUE then 
     Result := -1 
    else try 
     Int64Rec(Result).Lo := GetFileSize(fHandle, @Int64Rec(Result).Hi); 
    finally CloseHandle(fHandle); end; 
    end; { DSiFileSize } 
7

Sử dụng một đơn vị Indy:

uses IdGlobalProtocols; 

function FileSizeByName(const AFilename: TIdFileName): Int64; 
+0

trả về 0 trong năm 2010 delphi trên tệp TXT. –

+0

cái này hoạt động tốt cho tôi trong delphi 6.0 trên windows xp – mulllhausen

+2

Nếu 'FileSizeByName()' trả về 0, thì đó là kích thước thực được báo cáo bởi hệ điều hành, vì 'FileSizeByName()' trả về -1 nếu xảy ra lỗi, như thể tệp không tồn tại hoặc không thể truy cập được. –

3

tôi muốn đề cập đến vài tinh khiết Delphi cách. Mặc dù tôi nghĩ rằng Deltics làm một câu trả lời tốc độ hiệu quả nhất cho nền tảng Windows, nhưng đôi khi bạn muốn chỉ dựa vào RTL và cũng làm cho mã xách tay mà có thể làm việc trong Delphi cho hệ điều hành MacOS hoặc trong FreePascal/Virtual Pascal/bất cứ điều gì.


Có chức năng FileSize còn lại từ ngày Turbo Pascal.

Các mẫu ở trên thiếu "read-only" chế độ thiết lập. Bạn sẽ yêu cầu mở tập tin r/o như trên đĩa CD-ROM hoặc trong thư mục với ACL được đặt thành r/o.Trước khi gọi ReSet, không được gán cho FileMode var toàn cầu.

Nó sẽ không hoạt động trên các tập tin trên kích thước 2GB (có thể với tiêu cực đến hồng y đúc - lên đến 4GB) nhưng là "out of the box" một.


Có một cách tiếp cận khác, bạn có thể quen thuộc nếu bạn đã từng lập trình ASM cho MS-DOS. Bạn Seek con trỏ tệp thành byte thứ nhất, sau đó đến byte cuối cùng và kiểm tra sự khác biệt.
Tôi không thể nói chính xác phiên bản Delphi nào đã giới thiệu, nhưng tôi nghĩ nó đã có trong một số phiên bản cũ như D5 hay D7, mặc dù đó chỉ là cảm giác thông thường và tôi không thể kiểm tra nó.
Điều đó sẽ đưa bạn thêm biến THANDLE và khối try-finally để luôn đóng tay cầm sau khi thu được kích thước.

Ngoài cách tiếp cận 1st này được Int64 có khả năng. Nó cũng tương thích với FreePascal, mặc dù với một số hạn chế


Bạn cũng có thể tạo và sử dụng TFileStream -typed đối tượng - đó là chính, chính thức thiên nhiên ưu đãi đường cho các hoạt động tệp từ Delphi 1.0

Như một mặt lưu ý, đại lộ này là tất nhiên kết hợp với nói trên IOUtils đơn vị.

+0

Tôi không chắc chắn nếu TFileStream bị xử phạt để bị lạm dụng cho những gì đã được chính thức một thư mục, không hoạt động tập tin. Findfirst có ý nghĩa hơn là tuyến đường ưu tiên cho việc này. –

+0

Có vấn đề. Tôi không muốn TÌM KIẾM bất cứ điều gì, cũng không phải tôi muốn tạo ra và sau đó xử lý cơ sở hạ tầng tìm kiếm tập tin. Tôi chỉ muốn truy vấn một tập tin cụ thể.Sau đó, nếu tệp đó không đơn độc và bạn thực sự muốn thu thập kích thước cho nhiều tệp (ví dụ danh sách thư mục), thì FindFirst hoặc các phương pháp định hướng thư mục khác sẽ có ý nghĩa hơn (như các nhà phát triển Git đã học theo cách xấu): -)) –

+0

Bạn gọi nó là tìm tệp, nhưng bạn cũng có thể xem xét nó truy vấn các dịch vụ thư mục cho các thuộc tính. Và kích thước là thuộc tính tệp. Bit tạo/xử lý cũng đi cho đối tượng tfilestream và, tệ hơn, để mở tệp chỉ để có kích thước (hệ thống VM có thể [đọc lại toàn bộ tệp). Trên Windows, dĩ nhiên GetFileAttributesEx là một trình hoàn hảo trung gian, nhưng khái niệm về việc nhận các thuộc tính cho một tệp không phải là rất dễ dàng. –

2

Đây là một giải pháp ngắn sử dụng Dung lượng mà không được công việc:

function GetFileSize(p_sFilePath : string) : Int64; 
var 
    oFile : file of Byte; 
begin 
    Result := -1; 
    AssignFile(oFile, p_sFilePath); 
    try 
    Reset(oFile); 
    Result := FileSize(oFile); 
    finally 
    CloseFile(oFile); 
    end; 
end; 

Từ những gì tôi biết, Dung lượng có sẵn chỉ từ XE2.

+0

ngay bây giờ. Tôi có sẵn ngay cả trước khi Delphi 1.0 được phát hành. http://turbopascal.org/system-functions-filepos-and-filesize Tôi đã đề cập đến chức năng đó trong danh sách của tôi ở trên. Vấn đề chính của nó - ngoại trừ LOT của boilerplate là nó pukes trên các tập tin lớn hơn 2GB –

+0

nó hoạt động trên D7 quá, nhưng đã có một lỗi trong tên tham số, nó có nghĩa là nó không được thử nghiệm, thậm chí không một lần;) với các tệp> 2Gb nhưng, như đã nói, nếu đủ, nó hoạt động. – ZioBit

1
uses 
    System.Classes, System.IOUtils; 

function GetFileSize(const FileName : string) : Int64; 
var 
    Reader: TFileStream; 
begin 
    Reader := TFile.OpenRead(FileName); 
    try 
    result := Reader.Size; 
    finally 
    Reader.Free; 
    end; 
end; 
+1

Vui lòng [sửa] để giải thích cách mã của bạn hoạt động. –