vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Top-Preis! AP-Access-Tools-CD Volume 1  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück
Rubrik: Dateisystem · Dateien lesen/schreiben   |   VB-Versionen: VB2005, VB200819.03.10
Datei splitten und wieder zusammenfügen

Dieser Tipp zeigt, wie eine Datei in einzelne Segmente gesplittet und wieder zusammengefügt werden kann.

Autor:   Lars KonschakBewertung:     [ Jetzt bewerten ]Views:  14.616 
ohne HomepageSystem:  Win2k, WinXP, Win7, Win8, Win10, Win11 Beispielprojekt auf CD 

Manchmal ist es nicht möglich, eine Datei aufgrund ihrer Größe als ganzes zu übertragen. Sei es, weil der Emailprovider die Anhanggröße einer Mail beschränkt oder ein Speichermedium nicht über genügend Platz verfügt. Szenarien gibt es viele.

Als Lösung bietet sich ein Splitten der Datei in einzelne Segmenten an. Die einzelnen Dateisegmente können dann bei Bedarf wieder zu einer Datei zusammengefügt werden. Genau dieses demonstriert dieses Beispiel anhand einer einfachen Klasse. Ich habe zugunsten der Lesbarkeit dieses Beispiels auf diverse Absicherungen verzichtet, die man später aber implementieren sollte (die Segmentgröße darf als Beispiel nicht größer als der Bereich eines Int32 sein usw.).

Imports System.IO
 
''' <summary>
''' Größeneinheit des einzelnen Segmentes
''' </summary>
''' <remarks></remarks>
Public Enum SizeUnit
  KByte
  MByte
  GByte
End Enum
 
Public Class SplittingJoining
  ''' <summary>
  ''' Datei in Segmente splitten
  ''' </summary>
  ''' <param name="SourceFile">Quelldatei</param>
  ''' <param name="TargetFolder">Zeilverzeichnis</param>
  ''' <param name="Unit">Dateneinheitgröße</param>
  ''' <param name="Size">Größe der Dateneinheit</param>
  ''' <remarks></remarks>
  Public Sub SplitFile(ByVal SourceFile As String, _
    ByVal TargetFolder As String, _
    ByVal Unit As SizeUnit, _
    ByVal Size As Integer)
 
    ' Dient zur Überprüfung, ob das letzte Segment eingelesen wird
    Dim controlBuffer As Int32 = 0
 
    ' Definiert die Anzahl an Bytes, die Stückweise einzulesen und zu schreiben sind 
    Dim bytesToRead As Int32 = 0
 
    ' Tatsächliche eingelesene Bytes  
    Dim bytesRead As Int32 = 0
 
    ' Wird den Namen des jeden neu zu schreibenden Dateisegmentes beinhalten
    Dim currDstFile As String
 
    ' Zähler für die Dateiendungen
    Dim counter As Int32 = 1
 
    ' Dient zum einlesen der Quelldatei
    Dim srcStream As FileStream
 
    ' Abhängig von der Benutzerangabe bezüglich der Dateiteinheitengröße 
    ' den Lesebuffer festlegen
    If Unit = SizeUnit.KByte Then
      bytesToRead = Size * 1024
    ElseIf Unit = SizeUnit.MByte Then
      bytesToRead = Size * (1024 * 1024)
    ElseIf Unit = SizeUnit.GByte Then
      bytesToRead = Size * (1024 * 1024 * 1024)
    End If
 
    controlBuffer = bytesToRead
 
    ' Filestream aus der Quelldatei erstellen
    srcStream = New FileStream(SourceFile, FileMode.Open, _
      FileAccess.Read, FileShare.None)
 
    Try
      Dim buffer(bytesToRead - 1) As Byte
      Do
        ' Dateiendung ermitteln. 
        ' Diese wird gegebenfalls mit Nullen aufgefüllt.
        If counter < 10 Then
          ' Liegt die Zahl unter 10, so wird der Dateieindung zwei 
          ' Nullen vorangestellt (.001, 002 usw.)
          currDstFile = "00" & counter.ToString()
        ElseIf counter < 100 Then
          ' Liegt die Zahl unter 100, so wird der Dateieindung eine 
          ' Null vorangestellt (.020, 021 usw.)
          currDstFile = "0" & counter.ToString()
        Else
          currDstFile = counter.ToString()
        End If
 
        ' Name des neu zu schreibenden Dateisegmentes
        currDstFile = TargetFolder + "\" + _
          Path.GetFileName(SourceFile) + "." + currDstFile
 
        ' Letztes Segment erstellen?
        If ((srcStream.Length - srcStream.Position) < controlBuffer) _
          OrElse ((srcStream.Length - srcStream.Position) = controlBuffer) Then
 
          ' Einzulesende Restgröße ermitteln
          bytesToRead = CInt((srcStream.Length - srcStream.Position))
 
          If bytesToRead = 0 Then
            ' Es gibt nichts mehr einzulesen
            Exit Do
          End If
        End If
 
        ' Daten einlesen
        bytesRead = srcStream.Read(buffer, 0, bytesToRead)
 
        ' Dateisegment schreiben
        Using dstStream As New FileStream(currDstFile, _
          FileMode.Create, FileAccess.ReadWrite, FileShare.None)
          Try
 
            dstStream.Write(buffer, 0, bytesToRead)
 
          Catch ex As Exception
            MessageBox.Show("Beim schreiben der Daten trat folgender Fehler auf:" + _
              vbCrLf + ex.Message, _
              "Hinweis", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Exit Sub
          End Try
        End Using
 
        ' Zähler erhöhen
        counter += 1
      Loop While bytesRead = controlBuffer AndAlso bytesToRead > 0
 
      MessageBox.Show("Die Datei wurde erfolgreich gesplittet", _
        "Hinweis", MessageBoxButtons.OK, MessageBoxIcon.Information)
 
    Catch ex As Exception
      MessageBox.Show("Beim lesen / schreiben der Daten trat folgender Fehler auf:" + _
        vbCrLf + ex.Message, _
        "Hinweis", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try
  End Sub
  ''' <summary>
  ''' Setzt eine Datei aus Dateifragmenten wieder zusammen.
  ''' </summary>
  ''' <param name="f">Erstes gesplittetes Dateisegment (Extension 001!!)</param>
  ''' <param name="TargetFolder">Zielverzeichnis</param> 
  Public Sub JoinFileSegments(ByVal f As String, _
    ByVal TargetFolder As String)
 
    ' Zähler für die Dateiendungen 
    Dim counter As Integer = 1
 
    ' Bytes, die einzulesen sind
    Dim byteToRead As Integer = 0
 
    ' Beinhaltet die eingelesenen Daten
    Dim byteRead As Integer = 0
 
    ' Liste wird die Dateisegmente enthalten
    Dim fileList As New List(Of String)()
 
    Dim b As String = ""
 
    ' Alle Dateisegmente in einer List(Of String)speichern
    Do
      If counter < 10 Then
        b = "00" & counter.ToString
      ElseIf counter < 100 Then
        b = "0" & counter.ToString
      Else
        b = counter.ToString
      End If
 
      Dim filename As String = Path.GetDirectoryName(f) + "\" + _
        Path.GetFileNameWithoutExtension(f) + "." + b
 
      If File.Exists(filename) Then
        fileList.Add(filename) ' Dateisegment in die Liste aufnehmen
      End If
 
      counter += 1
    Loop While File.Exists(Path.GetDirectoryName(f) + "\" + _
      Path.GetFileNameWithoutExtension(f) + "." + b)
 
    Try
      ' Ziel-FileStream erstellen, durch welchem die Dateisegmente 
      ' in eine Zieldatei geschrieben werden
      Dim dstStream As New FileStream(TargetFolder + "\" + _
        Path.GetFileNameWithoutExtension(f), _
        FileMode.Create, FileAccess.Write, FileShare.None)
 
      ' Enhält die einzulesenden Daten
      Dim filedata As Byte()
 
      ' Alle Dateien aus der Liste auslesen und in eine Zieldatei speichern
      For Each fi As String In fileList
 
        ' FileStream, der das Datei-Segment einliest.
        Using sceStream As New FileStream(fi, FileMode.Open, _
          FileAccess.Read, FileShare.Read)
 
          ' Länge der einzulesenden Daten ermitteln
          byteToRead = CInt(sceStream.Length)
 
          filedata = New Byte(byteToRead - 1) {}
 
          ' Daten einlesen
          byteRead = sceStream.Read(filedata, 0, byteToRead)
 
          ' Daten schreiben
          dstStream.Write(filedata, 0, byteRead)
        End Using
      Next
      dstStream.Close()
    Catch ex As Exception
      MessageBox.Show(ex.Message)
      Exit Sub
    End Try
 
    MessageBox.Show("Datei-Joining wurde erfolgreich beendet")
  End Sub
End Class