Velikost souboru   otázka

VB.NET, Algoritmy, .NET

Dobrý den,

chtěl bych se zeptat na zjišťování velikosti souboru. Jde o to, že když zjistím velikost, vrátí se mi v bytech. Napsal jsem si dvě metody, které mi vrátí velikost+jednotky

    Private Function GetFileLength(ByVal length As Long) As String
        Dim procLength As Long = ProcessLength(length)

        Dim retval As String = String.Empty
        Select Case length
            Case Is < 1024 : retval = " B"
            Case Is > 1073741824 : retval = " GB"
            Case Is > 1048576 : retval = " MB"
            Case Is < 1048576 : retval = " kB"
        End Select

        Return procLength.ToString("0.0") & retval
    End Function

    Private Function ProcessLength(ByVal length As Long) As Double
        Dim retval As Double = CDbl(length)

        If retval > 1024 Then
            retval /= 1024
            retval = ProcessLength(retval)
        End If

        Return retval
    End Function

funguje to ok, ale napadlo mě, jetli ve frameworku na to není přímo funkce. Pokoušel jsem se jí najít, ale nepodařilo se.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

ještě oprava, ten kód má vypadat takhle

    Private Function GetFileLength(ByVal length As Long) As String
        Dim procLength As Double = ProcessLength(CDbl(length))

        Dim retval As String = String.Empty
        Select Case length
            Case Is < 1024 : retval = " B"
            Case Is > 1073741824 : retval = " GB"
            Case Is > 1048576 : retval = " MB"
            Case Is < 1048576 : retval = " kB"
        End Select

        Return procLength.ToString("0.0") & retval
    End Function

    Private Function ProcessLength(ByVal length As Double) As Double
        Dim retval As Double = CDbl(length)

        If retval > 1024 Then
            retval /= 1024
            retval = ProcessLength(retval)
        End If

        Return retval
    End Function

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nechci Vám kazit radost, ale jste přesvědčen, že Vaše funkce skutečně funguje?

Zkuste jí prohnat velikost souboru 1024 resp. 1048576. Určitě Vás vrácená hodnota neuspokojí!

(je to zřejmé již jen letmým pohledem do textu, kde v konstrukci select Case nemáte řešeny hranice jednotlivých pásem)

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

máte pravdu, psal jsem to v noci a nějak jsem to nedomyslel

díky za upozornění

nahlásit spamnahlásit spam 0 odpovědětodpovědět

ještě bych se k tomu vrátil.

Pan Linhart tvrdí, že požadovaná funkce není ve Frameworku implicitně dostupná, proto nezbývá, než si ji doplnit vlastními silami.

Záleží samozřejmě na tom jak konkrétně s danou funkcí pracujete, kde berete vstupní data (velikost souboru), či jak jinak s tím vším pracujete.

Trochu jsem si s tím hrál (protože Vámi popisované využití považuji za celkem časté), a spíše pro inspiraci přidávám jednu z mnoh amožností řešení.

Pokud mne nebude zajímat nějaké obecné řešení (obecný vstup jako parametr) a spíše bych se zaměřil na funkcionalitu takovou, kdy pracuji s informacemi o souborech uložených ve formátu system.IO.Fileinfo, pak bych postupoval nejspíš cestou rozšíření funkcionality této již existující třídy.

Bohužel, jako na potvoru, třída fileinfo je definována jako Noninheritable, tedy nemůžu si ji jednoduše zdědit a doplnit dle potřeby.

Naštěstí ale na tomto Webu je k nalezení mnoho užitečných informací a rad i pro nás - úplné začátečníky. Již nějakou dobu zde visí odkaz na nedávno vyšedší knihu "Inovace v jazyce Visual Basic 2008" a v této knize je popsáno několik zajímavých drobností a jednou z nich jsou i tzv. rozšiřující metody. No a ty jsou pro tento účel jako stvořené.

Takže pokud pro svůj projekt používáte VS 2008, můžete zvážit, nebyl-li by pro Vás zajímavým i následující postup.

Do projektu si přidejte modul a do tohoto modulu si vložte požadovanou metodu, kterou byste chtěl doplnit funkcionalitu vybrané třídy. Mohlo by to vypadat třeba takhle:

Imports System.Runtime.CompilerServices
Imports System.IO

Module Module1
    ''' <summary>
    ''' Rozšiřující funkce třídy FileInfo.
    ''' Můžeme ji dále používat jako každou jinou funkci třídy FileInfo
    ''' </summary>
    ''' <param name="format">Můžeme specifikovat požadovaný formát číselné hodnoty, 
    ''' pokud nespecifikujeme, dosadí se předdefinovaný</param>
    ''' <returns>Vrací textové vyjádření velikosti souboru vč. odpovídající jednotky</returns>
    ''' <remarks></remarks>
    <Extension()> Public Function ToSignedString(ByVal PopisSouboru As FileInfo, Optional ByVal format As String = "#0.##") As String
        Dim text As String = ""


        Select Case PopisSouboru.Length
            Case Is < 1024
                text = PopisSouboru.Length.ToString(format) & " B"

            Case Is < 1024 ^ 2
                text = (PopisSouboru.Length / 1024).ToString(format) & " kB"

            Case Is < 1024 ^ 3
                text = (PopisSouboru.Length / 1024 ^ 2).ToString(format) & " MB"

            Case Else
                text = (PopisSouboru.Length / 1024 ^ 3).ToString(format) & " GB"

        End Select


        Return text

    End Function

End Module

No a krása tohoto řešení je ve skutečnosti, že tato metoda, ač stojí zcela osamocena někde v modulu, se Vám začlení do třídy, která je definována jeko její první parametr, takže již dále prakticky nepoznáte (při práci s danou třídou), pracujete-li s metodami původními, nebo vlastními.

Jasné to je z jednoduchého testovacího příkladu (na form1 přidat OpenFileDialog, 1x tlačítko a 3x label):

Imports System.IO


Public Class Form1

    ' pouze pro testovací a prezentační účely 
    ' ukazuje použití rozšiřující metody
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim InfoOSouboru As FileInfo

        ' vybereme nějaký soubor
        If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then

            'načteme informace o tomto souboru
            InfoOSouboru = New FileInfo(Me.OpenFileDialog1.FileName)

            Me.Label1.Text = InfoOSouboru.Name                  ' kontrolní výpis jména souboru
            Me.Label2.Text = InfoOSouboru.Length                ' výpis hodnoty "standardní" metody třídy FileInfo
            Me.Label3.Text = InfoOSouboru.ToSignedString()      ' výpis hodnoty "rozšiřující" metody

        End If

        

    End Sub


End Class

Je to jistě jenom jedno z velice mnoha možných řešení, ale celkem se mi líbí pro jeho jednoduchost a hlavně pak i snadnost následujícího použití.

Jinak jsem celou Vaši funkcionalitu vrazil do jedné metody, která sice možná není natolik efektní jako ta Vaše (nevyužívám rekurzi), ale měla by plnit stejný účel - určitě by se pro daný účel dala zapracovat i ta Vaše metoda získání výsledku.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Já bych přidal ještě vlastní, malinko pokročilejší verzi, kterou běžně používám:

''' <summary>
''' Určuje jednotku kapacity.
''' </summary>
Public Enum StorageUnits
  ''' <summary>
  ''' Jednotka bude určena automaticky.
  ''' </summary>
  Auto = 0
  ''' <summary>
  ''' Bajty.
  ''' </summary>
  B = 1
  ''' <summary>
  ''' Kilobajty.
  ''' </summary>
  kB = 2
  ''' <summary>
  ''' Megabajty.
  ''' </summary>
  MB = 3
  ''' <summary>
  ''' Gigabajty.
  ''' </summary>
  GB = 4
  ''' <summary>
  ''' Terabajty.
  ''' </summary>
  TB = 5
End Enum
''' <summary>
''' Formátuje velikost v bajtech na požadované jednotky kapacity.
''' </summary>
''' <param name="bytes">Velikost v bajtech.</param>
''' <param name="units">Požadované jednotky kapacity.</param>
Public Function FormatBytes(ByVal bytes As Double, ByVal units As StorageUnits) As String
  Dim includeUnits As Boolean
  Dim result As String = String.Empty
  Select Case units
    Case StorageUnits.Auto
      includeUnits = True
      Select Case bytes
        Case Is < 1024
          GoTo B
        Case 1024 To 1048575
          GoTo kB
        Case 1048576 To 1073741823
          GoTo MB
        Case 1073741824 To 1099511627775
          GoTo GB
        Case Is > 1099511627775
          GoTo TB
      End Select
    Case StorageUnits.B
B:    result = String.Format(My.Application.Culture, _
                             DirectCast(IIf(includeUnits, "{0:N0} B", "{0:N0}"), String), _
                             bytes)
    Case StorageUnits.kB
kB:   result = String.Format(My.Application.Culture, _
                             DirectCast(IIf(includeUnits, "{0:N} kB", "{0:N}"), String), _
                             bytes / 1024)
    Case StorageUnits.MB
MB:   result = String.Format(My.Application.Culture, _
                             DirectCast(IIf(includeUnits, "{0:N} MB", "{0:N}"), String), _
                             bytes / 1048576)
    Case StorageUnits.GB
GB:   result = String.Format(My.Application.Culture, _
                             DirectCast(IIf(includeUnits, "{0:N} GB", "{0:N}"), String), _
                             bytes / 1073741824)
    Case StorageUnits.TB
TB:   result = String.Format(My.Application.Culture, _
                             DirectCast(IIf(includeUnits, "{0:N} TB", "{0:N}"), String), _
                             bytes / 1099511627776)
    Case Else
      GoTo B
  End Select
  Return result
End Function
''' <summary>
''' Formátuje velikost v bajtech.
''' </summary>
''' <param name="bytes">Velikost v bajtech.</param>
Public Function FormatBytes(ByVal bytes As Double) As String
  Return FormatBytes(bytes, StorageUnits.B)
End Function
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Žádná taková funkce ve Frameworku není.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback