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 Dieser Tipp wurde bereits 14.896 mal aufgerufen. Voriger Tipp | Zufälliger Tipp | Nächster Tipp
Anzeige
Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv Vol.6 (einschl. Beispielprojekt!) Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m. |
vb@rchiv CD Vol.6 Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! Online-Update-Funktion Entwickler-Vollversionen u.v.m. Tipp des Monats September 2024 Dieter Otter Übergabeparameter: String oder Array? Mit der IsArray-Funktion lässt sich prüfen, ob es sich bei einem Übergabeparameter an eine Prozedur um ein Array oder einer "einfachen" Variable handelt. sevGraph (VB/VBA) Grafische Auswertungen Präsentieren Sie Ihre Daten mit wenig Aufwand in grafischer Form. sevGraph unterstützt hierbei Balken-, Linien- und Stapel-Diagramme (Stacked Bars), sowie 2D- und 3D-Tortendiagramme und arbeitet vollständig datenbankunabhängig! |
||||||||||||||||
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein. |