mario.deghetto

Visual Basic & .NET
posts - 319, comments - 204, trackbacks - 0

#42: Abbreviare la dimensione di un file con VB.NET

Come tutti i programmatori sanno, in informatica vengono utilizzate delle abbreviazioni per indicare l’unità di misura per la dimensione di un file, della RAM o di un hard disk: per esempio un file di 1.024 byte equivale a un file di 1 “kB”.

Le abbreviazioni utilizzate attualmente sono le seguenti:

  • kiloByte –> kB –> 1.024 (circa 10^3)
  • MegaByte –> MB –> 1.048.576 (circa 10^6)
  • GigaByte –> GB –> 1.073.741.824 (circa 10^9)
  • TeraByte –> TB –> 1.099.511.627.776 (circa 10^12)
  • PetaByte –> PB –> 1.125.899.906.842.620 (circa 10^15)
  • ExaByte –> EB –> 1.152.921.504.606.850.000 ( circa 10^18 )
  • ZettaByte –> ZB –> 1,180.591.620.717.41E+21 (circa 10^21)
  • YottaByte –> YB –> 1,208.925.819.614.63E+24 (circa 10^24)

Per noi programmatori potrebbe quindi essere utile avere una funzione in grado di abbreviare un numero molto grande, così da avere una rappresentazione molto più compatta. Il seguente codice fa proprio questo:

Module Module1
   Public Function ConvertiByte( _
         ByVal strNumero As String) As String
      Dim risultato As String
      Dim potenza As Integer = 0
      Dim nByte As Decimal = 0
      ‘ verifico se è stato passato un parametro:
      ‘ se si, lo converto nel tipo Decimal
      ‘ se no, esco
      ‘TODO: aggiungere verifica se è un numero valido!
      If strNumero <> “” Then
         Try
            nByte = CType(strNumero, Decimal)
         Catch ex As Exception
            Return “Numero troppo grande: Overflow”
         End Try
      Else
         Return “Errore: nessun numero da valutare”
      End If
      ‘ ciclo di riduzione del numero, estraendo
      ‘ il numero di iterazioni effettuate
      Do While ((nByte / 1000) >= 1)
         nByte = nByte / 1024
         potenza += 1
      Loop
      ‘ conversione in stringa con arrotondamento
      risultato = Decimal.Round(nByte, 2).ToString
      ‘ aggiunta della giusta unità di misura
      Select Case potenza
         Case 0
            risultato &= ” byteCase 1
            risultato &= ” KB”
         Case 2
            risultato &= ” MB”
         Case 3
            risultato &= ” GB”
         Case 4
            risultato &= ” TB”
         Case 5
            risultato &= ” PB”
         Case 6
            risultato &= ” EB”
         Case 7
            risultato &= ” ZB”
         Case 8
            risultato &= ” YB”
         Case Else
            risultato = “Non valutabile”
      End Select
      Return risultato
   End Function
End Module

A questo punto basta creare un form, aggiungere una casella di testo e un pulsante. Il codice per gestire l’evento Click del pulsante è il seguente:

Public Class Form1
   Private Sub Button1_Click(ByVal sender As System.Object, _
         ByVal e As System.EventArgs) Handles Button1.Click
      MessageBox.Show(ConvertiByte(Me.TextBox1.Text))
   End Sub
End Class

Semplice vero? Ma proviamo a migliorare un po’ la nostra funzione. E’ sufficiente sostituire tutto il codice seguente al commento “aggiunta della giusta unità di misura”:

‘ aggiunta della giusta unità di misura
Dim misure() As String = _
         {“byte”, “KB”, “MB”, “GB”, “TB”, “PB”, “EB”, “ZB”, “YB”}
If potenza > 8 Then
   risultato &= ” Non valutabile”
Else
   risultato &= ” “ & misure(potenza)
End If
Return risultato

Con una semplice modifica, poi, possiamo fare in modo che la nostra funzione rappresenti un’abbreviazione di potenze di 10^3. Per esempio (i punti di separazione delle migliaia sono inseriti solo per chiarezza visiva):

- 1.000 –> 1 x 10^3
- 1.000.000 –> 1 x 10^6
- 55.555.555.555 –> 55,56 x 10^9

Ecco quindi la nostra funzione modificata:

Module Module1
   Public Function ConvertiByte( _
         ByVal strNumero As String) As String
      Dim risultato As String
      Dim potenza As Integer = 0
      Dim nByte As Decimal = 0
      ‘ verifico se è stato passato un parametro:
      ‘ se si, lo converto nel tipo Decimal
      ‘ se no, esco
      ‘TODO: aggiungere verifica se è un numero valido!
      If strNumero <> “” Then
         Try
            nByte = CType(strNumero, Decimal)
         Catch ex As Exception
            Return “Numero troppo grande: Overflow”
         End Try
      Else
         Return “Errore: nessun numero da valutare”
      End If
      ‘ ciclo di riduzione del numero, estraendo
      ‘ il numero di iterazioni effettuate
      Do While ((nByte / 1000) >= 1)
         nByte = nByte / 1000
         potenza += 1
      Loop
      ‘ conversione in stringa con arrotondamento
      risultato = Decimal.Round(nByte, 2).ToString
      ‘ aggiunta della giusta unità di misura
      risultato &= ” x 10^” & (potenza * 3).ToString
      Return risultato
   End Function
End Module

Come potete vedere, le uniche differenze sono date dal diverso divisore (1000 anziché 1024) e nella parte finale, dove viene composta la stringa che viene restituita dalla funzione al codice chiamante.

Una precisazione, prima che qualcuno possa pensare che si tratti di un errore. Il seguente codice:

Do While ((nByte / 1000) >= 1)
   nByte = nByte / 1024
   potenza += 1
Loop

potrebbe apparire strano o perfino sbagliato. Perché confronto la divisione per 1000 e poi divido per 1024?

E’ molto semplice: nel caso in cui, per esempio, volessi abbreviare 1000 byte, con il confronto per 1024 otterrei la non esecuzione dell’abbreviazione e quindi il risultato sarebbe “1000 byte” anziché “0,98 KB”. Di solito è abbastanza brutto veder superare il valore di 1000 in questi casi e quindi si preferisce comunque arrivare al massimo a 999 (confrontate per esempio con la visualizzazione dell’Esplora Risorse di Windows).

Una curiosità: notate come sia possibile, in VB.NET, scrivere una cosa del genere:

(potenza * 3).ToString

senza dover memorizzare il calcolo matematico in una variabile.

C’è ancora qualcuno che non è convinto a passare a VB.NET?   :-)

Print | posted on venerdì 15 gennaio 2010 5.57 |

Feedback

No comments posted yet.

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 3 and 5 and type the answer here:

Powered by: