Avatar billede peterfa Nybegynder
05. november 2007 - 15:52 Der er 8 kommentarer og
1 løsning

VB6: Plads forbrug for filer / directories

Hejsa

Jeg prøver at finde en måde hvormed man kan få fat i plads forbruget af en række filer. Jeg har en bunke directories der indeholder en hel masse meget små filer, hvorfor der er meget stor forskel på summen af fil størrelserne, og det faktiske disk plads forbrug. Nogen der kender en måde at få fat på dette tal?
Avatar billede tjacob Juniormester
05. november 2007 - 17:09 #1
Der er forskel på størrelserne, fordi den filstørrelse du får, er den reelle filstørrelse i bytes. Hvorimod pladsforbruget er afhængig af allokeringsenheden.

Allokeringsenheden er en størrelse, man vælger når man formaterer en harddisk. På FAT ligger størrelserne fast, og sættes efter hvor stor disken er. I NTFS kan man selv vælge en værdi.

Du kan se mere om allokeringsenheder her: http://www.praestkjaer.dk/dk/ordbog-it/detaljer/hvad-er-allokeringsenhed.htm

En allokeringsenhed kan f.eks. være 4096 Byte = 4 kB.
Det betyder at filer altid vil fylde minimum 4 kB, og hvis de er større end dette, så et multiplum af 4 kB.

Jeg ved ikke om man kan aflæse allokeringsenheden nogen steder, men en nem måde er at lave en lille tekstfil med nogle få tegn. Højreklik på filen og vælg egenskaber. Nu kan du se at filens størrelse er nogle få bytes, og pladsforbruget er lig allokeringsenheden.

Du skal dog være opmærksom på at du ikke har mere plads på disken, end diskforbruget viser.

Hvis man (som du) har mange små filer, så var det måske en ide at oprette en partition i NTFS, og så sætte allokeringsenheden så lavt som muligt (512 Bytes). Dette vil udnytte pladsen bedre.
Allokeringsenheden kan ikke være mindre en 512 Bytes, da dette er sektorstørrelsen på de fleste harddiske.

MHT til dit spørgsmål:

For at finde pladsforbruget er du altså nødt til at kende allokeringsenheden. Så kan du beregne pladsforbruget ved at sige:

filstørrelse i bytes/allokeringsenhed i bytes >> afkortes til heltal
læg en til dette tal og gang med allokeringsenhed, og du har pladsforbruget.
Avatar billede sjh Nybegynder
05. november 2007 - 17:16 #2
hmm prøv den her :

' ------------------- Form1 -------------------
Option Explicit

Private Sub Form_Load()
Dim strPath As String
  strPath = QualifyPath("C:\Programmer")
  Me.Caption = SearchForFolders(strPath) & " bytes"
End Sub
' ------------------- Form1 -------------------


' ------------------ Module1 ------------------
Option Explicit

Private Const MAX_PATH            As Long = 260
Private Const INVALID_HANDLE_VALUE As Long = (-1)

Private Type FILETIME
        dwLowDateTime  As Long
        dwHighDateTime As Long
End 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 * MAX_PATH
        cAlternate      As String * 14
End Type

Private Declare Function FindFirstFileA Lib "kernel32" (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindNextFileA Lib "kernel32" (ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long
Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
Private Declare Function lstrlenW Lib "kernel32" (ByVal lpString As Long) As Long

Private Const vbDot      As Long = 46
Private Const vbAllFiles  As String = "*.*"
Private Const vbBackSlash As String = "\"

Private Function TrimNull(strName As String) As String
  TrimNull = Left$(strName, lstrlenW(StrPtr(strName)))
End Function

Public Function QualifyPath(strPath As String) As String
  If Right$(strPath, 1) <> vbBackSlash Then
        QualifyPath = (strPath & vbBackSlash)
  Else: QualifyPath = strPath
  End If
End Function

Public Function SearchForFiles(strRoot As String) As Double
Dim WFD As WIN32_FIND_DATA
Dim hFile As Long
Dim nSize As Double
Dim strPath As String
  hFile = FindFirstFileA(strRoot & vbAllFiles, WFD)
  If hFile <> INVALID_HANDLE_VALUE Then
    Do
      If Not (WFD.dwFileAttributes And vbDirectory) = vbDirectory Then
        If Asc(WFD.cFileName) <> vbDot Then
          nSize = (nSize + ((WFD.nFileSizeHigh * &HFFFF) + WFD.nFileSizeLow))
        End If
      End If
    Loop While FindNextFileA(hFile, WFD)
  End If
  Call FindClose(hFile)
 
  SearchForFiles = nSize
End Function

Public Function SearchForFolders(strRoot As String, Optional nSize As Double = 0) As Double
Dim WFD As WIN32_FIND_DATA
Dim hFile As Long
Dim strPath As String
  hFile = FindFirstFileA(strRoot & vbAllFiles, WFD)
  If hFile <> INVALID_HANDLE_VALUE Then
    nSize = (nSize + SearchForFiles(strRoot))
    Do
      If (WFD.dwFileAttributes And vbDirectory) = vbDirectory Then
        If Asc(WFD.cFileName) <> vbDot Then
          strPath = TrimNull(WFD.cFileName)
          Call SearchForFolders(strRoot & strPath & vbBackSlash, nSize)
        End If
      End If
    Loop While FindNextFileA(hFile, WFD)
  End If
  Call FindClose(hFile)

  SearchForFolders = nSize
End Function
' ------------------ Module1 ------------------
Avatar billede peterfa Nybegynder
05. november 2007 - 17:23 #3
>> sjh
Jeg kan ikke umiddelbart finde noget om at det er den allokerede plads/optagede plads af filen, fremfor dens "datastørrelse", der er info om i WIN32_FIND_DATA. Ved du om dette er tilfældet?

>> tjacob
Var den samme grundlæggende forståelse jeg var kommet frem til, men tak for at få det sat på plads helt præcist. Dit svar rejser umiddelbart to problemstillinger.

1. Jeg er nød til at tage størrelsen per fil, og derefter finde "plads forbruget", dvs. jeg kan ikke gøre noget for at få størrelsen af en komplet mappe på en gang?

2. Nogen ide om hvordan jeg så finder allokeringsenheden for et drev?
Avatar billede peterfa Nybegynder
05. november 2007 - 17:37 #4
Fandt det her
http://msdn2.microsoft.com/en-us/library/aa364935.aspx

men den skulle i følge en hurtig googling ikke rapportere korrekte værdier for drev over 2gb.
Avatar billede tjacob Juniormester
05. november 2007 - 17:38 #5
Ad 1) Det er det sjh's funktioner gør:

SearchForFolders er en rekursiv funktion der finder alle subfolders i en given mappe.
-Og herunder finder alle filer og tæller deres størrelser op.
Funktionen returnerer den samlede filstørrelse..........

Ad 2) Jeg ved ikke om man kan finde allokeringsenheden "programmelt".
      Mit eneste bud er det jeg skrev i min første kommentar.
Avatar billede peterfa Nybegynder
05. november 2007 - 17:47 #6
Ok. Jeg styrer ikke selv miljøet så kan ikke ændre betingelserne, og er ikke acceptabelt at skulle bestemme allokeringsenheden eksperimentelt. Prøver pt at se om der ikke i WMI er en måde at få fat i informationen.

Smid lige et svar
Avatar billede tjacob Juniormester
05. november 2007 - 18:04 #7
Nej, jeg har ikke løst dit problem, og du var jo selv nået til den samme konklusion.

Jeg ville dog lige teste sjh's funktioner først hvis jeg var dig. Det er er jo en relativ simpel sag at lave en mappe med nogle "undersized" filer, og så se hvad funktionerne returnerer...........

Giv points til sjh hvis det virker, eller tag dem selv...
Avatar billede peterfa Nybegynder
06. november 2007 - 20:13 #8
sjh's løsning er filstørrelsen. Har fundet en løsning ved brug af WMI der giver cluster/allokeringsenheden i win 2003 server, hvilket for nu er acceptabelt. Tak for hjælpen.
Avatar billede sjh Nybegynder
06. november 2007 - 20:26 #9
peterfa : må vi se din løsning ?
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester