2009-10-29 15 views
27

Delphi 2010 ma ładny zestaw nowych funkcji dostępu do plików w IOUtils.pas (szczególnie podoba mi się wersja UTC funkcji związanych z datą). Co tęsknię tak daleko jest cośUzyskiwanie rozmiaru pliku w Delphi 2010 lub nowszym?

TFile.GetSize (const Path : String) 

co jest Delphi 2010-sposób, aby uzyskać rozmiar pliku? Czy muszę wrócić i użyć FindFirst, aby uzyskać dostęp do TSearchRec.FindData?

Dzięki.

+1

Po prostu zajrzałem do biblioteki kodów JEDI w ich funkcji FileGetSize. W rzeczywistości używa tylko metody FindFirst. –

+0

@J__ dlaczego nie odpowiedź?dodaj linki do wiki JCL i pobierania JCL - a to by oznaczało dobry połów –

+0

Proszę, zagłosuj na http://qc.embarcadero.com/wc/qcmain.aspx?d=110073 –

Odpowiedz

46

Nie jestem pewien, czy istnieje sposób "Delphi 2010", ale istnieje Windows way that doesn't involve FindFirst and all that jazz.

Zrzuciłem tę konwersję Delphi tej procedury (iw procesie zmodyfikowałem ją tak, aby obsługiwała pliki o rozmiarach> 4 GB, jeśli tego potrzebujesz).

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; 

Można było rzeczywiście wystarczy użyć GetFileSize() ale wymaga to uchwyt pliku, a nie tylko nazwę pliku, a podobny do GetCompressedFileSize() sugestia ta wymaga dwóch zmiennych zadzwonić. Zarówno GetFileSize() i GetCompressedFileSize() przeciążają ich wartość zwracaną, więc testowanie na sukces i zapewnienie prawidłowego wyniku jest po prostu trochę bardziej niezręczne.

GetFileSize Ex() unika piaszczysty nitty rozmiarów Obsługa plików> 4GB i wykrywanie poprawnych wyników, ale również wymaga dojścia do pliku, zamiast imienia i (od Delphi 2009 przynajmniej ja haven 't checked 2010) nie jest dla ciebie zadeklarowany w VCL, musiałbyś podać swoją własną deklarację importową.

+1

-1: Twoja funkcja nie działa na rozpakowanych plikach –

+1

Smasher nie wyjaśnił, jaki rozmiar pliku przyniesie. –

+6

W przypadku pliku skompresowanego (zip, rar, 7z itd.) Będzie raportował rozmiar archiwum w bajtach, a nie rozmiar zdekompresowanej zawartości. Ale w przypadku pliku ZIP rozmiar pliku JEST wielkości archiwum. W przypadku pliku na skompresowanym woluminie zgłosi rozmiar zdekompresowanego pliku, który jest tym, czego potrzebujesz, ponieważ pytasz o rozmiar obiektu pamięci masowej (pliku), a nie fizycznego nośnika danych (kompresja wymuszona przez system operacyjny). W przypadku plików <4GB sugerowane podejście jest po prostu bardziej skomplikowane, chyba że naiwnie i niepoprawnie * przyjmiesz * że wszystkie pliki są zawsze <4GB – Deltics

4

Możesz również użyć DSiFileSize z DSiWin32. Działa w "wszystkich" Delphis. Wewnętrznie wywołuje CreateFile i 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

Korzystanie z Indy jednostki:

uses IdGlobalProtocols; 

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

zwraca 0 w 2010 delphi na pliku TXT. –

+0

ten dobrze działał dla mnie w delphi 6.0 na windows xp – mulllhausen

+2

Jeśli 'FileSizeByName()' zwróci 0, to jest to rzeczywisty rozmiar zgłaszany przez system operacyjny, ponieważ 'FileSizeByName()' zwraca -1, jeśli wystąpi błąd, na przykład, jeśli plik nie istnieje lub nie można uzyskać do niego dostępu. –

3

Chciałbym wspomnieć kilka Czysta Delphi sposoby. Choć myślę Deltics popełnił największą prędkość efektywną odpowiedź na platformie Windows, ale czasami chcesz po prostu polegać na RTL i również przenośny kod, który będzie działać w Delphi dla MacOS lub w FreePascal/Virtual Pascal/cokolwiek.


Została funkcja FileSize z Turbo Pascal dni.

powyżej Próbka brakuje "tylko do odczytu" ustawienie trybu. Wymagałoby to otwarcia pliku r/o, takiego jak plik na nośniku CD-ROM lub w folderze z listami ACL ustawionymi na r/o.Przed wywołaniem ReSet powinno być przypisane zero do FileMode globalny var.

To nie będzie działać na plikach powyżej wielkości 2 GB (może z negatywnej na kardynalnej obsadą - do 4GB), ale jest "out of the box" jeden.


Jest jeszcze jedno podejście, które może znać, jeśli kiedykolwiek programowanie ASM dla MS-DOS. You Seek Wskaźnik pliku na 1 bajt, a następnie na ostatni bajt i sprawdź różnicę.
Nie mogę powiedzieć dokładnie, która wersja Delphi wprowadziła te, ale myślę, że była już w jakiejś starożytnej wersji, jak D5 lub D7, ale to jest po prostu zdrowy rozsądek i nie mogę tego sprawdzić.
Wymagałoby to dodatkowej zmiennej Thandle i bloku try-finally, aby zawsze zamykać uchwyt po uzyskaniu rozmiaru.

Oprócz 1. podejścia jest to Int64-zdolny. Jest również kompatybilny z FreePascal, choć z pewnymi ograniczeniami


Można również tworzyć i wykorzystywać TFileStream -typed obiekt - co było podstawowym, oficjalnie błogosławiony aleję dla operacji na plikach od Delphi 1.0

marginesie, ścieżka ta jest oczywiście zintegrowany z wyżej IOUtils urządzenia.

+0

Nie jestem pewien, czy TFileStream został ukarany za nadużywanie za to, co oficjalnie było katalogiem, a nie operacja na plikach. Findfirst ma więcej sensu jako preferowana trasa. –

+0

Wątpliwe. Nie chcę ZNAJDOWAĆ niczego, nie chcę też tworzyć, a następnie pozbywać się infrastruktury wyszukiwania plików. Chcę tylko zapytać o jeden konkretny plik.Następnie, jeśli ten plik nie jest sam, a właściwie chcesz zbierać rozmiary dla wielu plików (np. Lista katalogów), to FindFirst lub inne podejścia zorientowane na katalogi miałyby więcej sensu (ponieważ programiści Git nauczyli się w zły sposób: -)) –

+0

Nazywasz to znajdowaniem plików, ale możesz również rozważyć zapytanie do usług katalogowych o atrybuty. Rozmiar jest atrybutem pliku. Bit tworzenia/utylizacji również jest przeznaczony dla obiektu tfilestream, i co gorsza, do otwierania pliku tylko po to, aby uzyskać rozmiar (system VM może [ponownie odczytać cały plik). W systemie Windows oczywiście jest GetFileAttributesEx jako doskonały pośrednik, ale ta koncepcja uzyskiwania atrybutów dla jednego pliku nie jest zbyt przenośna. –

2

Jest to krótki rozwiązanie używając FILESIZE że spełnia swoje zadanie:

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; 

z tego co wiem, FileSize jest dostępny tylko z XE2.

+0

teraz. Jestem dostępny jeszcze przed wydaniem Delphi 1.0. http://turbopascal.org/system-functions-filepos-and-filesize Wspomniałem tę funkcję na powyższej liście. Głównym problemem - z tym wyjątkiem, że partycja z tablicy jest to, że pukes na plikach większych niż 2GB –

+0

działa również na D7, ale wystąpił błąd w nazwie parametru, co oznacza, że ​​nie był testowany, ani razu;) Problemy z plikami> 2 GB, ale, jak powiedział, jeśli to wystarczy, działa. – 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

Proszę [edytuj], aby wyjaśnić działanie swojego kodu. –

Powiązane problemy