Neuer vielversprechender Versuch Datei kopieren, Backgroundworker und Progress

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von picoflop.

    Neuer vielversprechender Versuch Datei kopieren, Backgroundworker und Progress

    Hi

    Beim kopieren einer Datei mit gerade mal 32 MB erhalten ich folgende Fehlermeldung als Errormeldung:

    Die arithmetische Operation hat einen Überlauf verursacht.

    Will damit eigentlich meine eigenen Sicherungen nochmal extern sichern... Die Dateien sind ca. 60 GB Gross. Daher kommt mir das gerade nicht so recht, wenn das Programm dies abbricht...

    Hier mal der Code der Kopiert:

    VB.NET-Quellcode

    1. Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    2. ' Quelldatei auswählen
    3. Dim sourcefile As FileInfo
    4. sourcefile = New FileInfo(Label13.Text)
    5. ' Zielverzeichnis auswählen
    6. Dim target As String
    7. target = Label12.Text
    8. ' Kopiervorgang starten
    9. Copy2(sourcefile, Label12.Text)
    10. End Sub


    VB.NET-Quellcode

    1. Private Sub Copy2(ByVal SourceFile As FileInfo, ByVal Target As String)
    2. ' Progressbar anpassen
    3. ProgressBar2.Value = 0
    4. ' Es gilt hier zu beachten, dass der Maximumwert ein Integer ist und
    5. ' daher die Length-Angabe über dem Bereich des Integer hinaus liegen kann.
    6. ' In so einem Fall müsste man den Maximumwert anders definieren
    7. ProgressBar2.Maximum = SourceFile.Length
    8. Try
    9. ' Quelle
    10. Dim fsmsource As FileStream
    11. ' Zieldatei
    12. Dim fsmtarget As FileStream
    13. ' Größe des bei jedem Durchlauf einzulesenden Datenpaketes
    14. Dim buffersize As Int32 = 1024 * 30 ' (30 KByte)
    15. ' Enthält nacher die in buffersize angegeben Menge an
    16. ' eingelesenen Daten
    17. Dim buffer(buffersize) As Byte
    18. ' Ermittelt die tatsächliche eingelesene Menge an Daten
    19. ' im Bytearray readbyte
    20. Dim readbyte As Int32
    21. ' Quelldatei
    22. fsmsource = New FileStream(SourceFile.FullName, FileMode.Open, _
    23. FileAccess.Read, FileShare.Read)
    24. ' Zieldatei
    25. fsmtarget = New FileStream(Target + "\" + SourceFile.Name, _
    26. FileMode.OpenOrCreate, FileAccess.Write)
    27. ' Daten nach und nach einlesen und im Zielstream wieder zurückschreiben
    28. While fsmsource.Position < fsmsource.Length
    29. ' Quelle einlesen
    30. readbyte = fsmsource.Read(buffer, 0, buffersize)
    31. ' In das Ziel schreiben
    32. fsmtarget.Write(buffer, 0, readbyte)
    33. ' Value Eigenschaft der Progressbar anpassen, das Label gibt
    34. ' den prozentualen Fortschritt an
    35. With ProgressBar2
    36. .Value += readbyte
    37. Label20.Text = CStr(CInt(100 * .Value / .Maximum)) + "%"
    38. End With
    39. ' Reporten
    40. Application.DoEvents()
    41. End While
    42. ' Streams schließen
    43. fsmsource.Close()
    44. fsmtarget.Close()
    45. MsgBox("Datei erfolgreich kopiert", MsgBoxStyle.Information)
    46. ProgressBar2.Value = 0
    47. Label20.Text = "0%"
    48. Catch ex As Exception
    49. MsgBox(ex.Message, MsgBoxStyle.Critical, "Error")
    50. End Try
    51. End Sub


    Ich vermute mal das hat was mit dieser Zeile zu tun?
    ' Größe des bei jedem Durchlauf einzulesenden Datenpaketes
    Dim buffersize As Int32 = 1024 * 30 ' (30 KByte)

    Was müßte ich daran den ändern, daß ich auch Dateien > 50 GB noch kopieren kann??

    lg lris08

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „lris08“ ()

    Read this:

    VB.NET-Quellcode

    1. ' Es gilt hier zu beachten, dass der Maximumwert ein Integer ist und
    2. ' daher die Length-Angabe über dem Bereich des Integer hinaus liegen kann.
    3. ' In so einem Fall müsste man den Maximumwert anders definieren


    Also, Maximumwert anders definieren! Quersumme nehmen zum Beispiel.

    MFG Solaris
    Kennst du eigentlich überhaupt deine IDE?!?
    Normalerweise unterlegt VS dir die Zeile mit dem Fehler gelb...
    Welche ist es?

    -BTW-
    Wenn Solaris Recht hat, dann liegt der Fehler darin, dass du den Progressbar über seinen Maximalwert hinaus fullen Willst, was AFAIK nicht geht.

    Außerdem haben Controls NAMEN verdient.
    ~prgStatus etc.
    Siehe Link "Von Stil und Code" in meiner Sig.

    FAtheone schrieb:

    Kennst du eigentlich überhaupt deine IDE?!?
    Normalerweise unterlegt VS dir die Zeile mit dem Fehler gelb...
    Welche ist es?

    -BTW-
    Wenn Solaris Recht hat, dann liegt der Fehler darin, dass du den Progressbar über seinen Maximalwert hinaus fullen Willst, was AFAIK nicht geht.

    Außerdem haben Controls NAMEN verdient.
    ~prgStatus etc.
    Siehe Link "Von Stil und Code" in meiner Sig.



    Ich hab mit VB gerade mal jetzt 5 Tage zu tun - und bin echt heil froh dass ich es überhaupt so weit geschaffft hab...

    Jetzt hab ich das auch bisserl verstanden, daß ich da einen zu hohen WErt drinnen hab - hab das auch schon versucht mit der Quersumme - aber das haut no ned ganz hin...
    Singu der ist doch nicht hübsch ;)

    Jaja Iris C&P-Code ne? Wenn man schon Code kopiert sollte man sich wenigstens die Kommentare zu Gemüte führen um bei Fragen nicht ganz so dumm da zu stehen.

    Soll jetzt keine Beleidigung deiner Person sein, eher Kritik an deiner Vorgehensweise.

    MFG Solaris
    Quersumme ?
    Ich denke das ist keine gute Lösung. Ich würde die Dateigröße erst auslesen, und je nach Größe die Progressbar auf Byte/KByte/MByte Größe setzen.
    Wenn du du bei 32 MB in 30 KByteschritten die Progressbar hochzählst ist das leicht übertrieben (unabhängig davon das es nicht geht wegen dem Integerüberlauf)

    Wenn du die Dimension des Maximums der Progressbar veränderst musst du dann halt die readbyte ebenfalls anpassen.
    Das ist meine Signatur und sie wird wunderbar sein!

    Neuer vielversprechender Versucht Kopie, Progress und Background...

    Hallo zusammen,

    nach nur 3 Std. Schlaf und ner ordentlicher Session mit Backgroundworker, Progressbar und Datei kopieren - habe ich nun endlich was zusammen gebracht, was ich auch ganz gut verstehe und fast alles nachvollziehen kann.
    Da ich aber immer noch im gegenzug zu euch totaler Anfänger bin - hab natürlich noch eine Frage an euch.

    Habe den unten genannten Code nicht kompl. selbst geschrieben, aber gesucht und gefunden - ausprobiert im Original und dann stück für Stück an meine Bedürfnisse angepasst.

    Es funktioniert soweit ganz gut.
    Sogar das hochzählen der Bytes wärrend des kopierens funz..

    nur meine ProgressBar selbst mag Ihren Dienst noch nicht leisten...
    Wenn ich sie umstelle auf Marquee und ein Kopiervorgang läuft, läuft das Teil so langsam, daß selbst bei fast 300 MB er gerade mal die hälfte seiner Strecke abläuft.
    Wenn Sie auch Bloks gestellt ist, fängt Sie erst gar nicht an zu laufen...

    ich vermute es liegt an diesen Zeilen:

    VB.NET-Quellcode

    1. Private Sub th_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
    2. Dim fi As New FileInfo(Me.lblSource.Text)
    3. Dim inStream As FileStream = Nothing
    4. Dim outStream As FileStream = Nothing
    5. Dim buffer(2048) As Byte
    6. Dim offset As Integer = 0
    7. Try
    8. inStream = New FileStream(fi.FullName, FileMode.Open)
    9. outStream = New FileStream(Me.lblTarget.Text & "\" & fi.Name, FileMode.Create)
    10. lngSourceFileLength = inStream.Length
    11. Do
    12. If th.CancellationPending = True Then
    13. e.Cancel = True
    14. inStream.Close()
    15. outStream.Close()
    16. Exit Sub
    17. End If
    18. offset = inStream.Read(buffer, 0, buffer.Length)
    19. outStream.Write(buffer, 0, offset)
    20. lngBytesCopied += offset
    21. ' WICHTIG: Hier könen wir einen Progress darstellen
    22. th.ReportProgress(offset / inStream.Length * 100)
    23. Loop Until offset = 0
    24. Catch ex As Exception
    25. MessageBox.Show(ex.Message)
    26. Finally
    27. inStream.Close()
    28. outStream.Close()
    29. End Try
    30. End Sub
    31. Private Sub th_ProgressChanged(ByVal sender As Object, _
    32. ByVal e As ProgressChangedEventArgs)
    33. Try
    34. Me.Progress.Text = lngBytesCopied.ToString & " Bytes From " & lngSourceFileLength.ToString & " Copied"
    35. Me.ProgressBar1.Value = e.ProgressPercentage.ToString
    36. Catch ex As Exception
    37. MessageBox.Show(ex.Message)
    38. End Try
    39. End Sub


    Geneuer gesagt an diesen:

    VB.NET-Quellcode

    1. ' WICHTIG: Hier könen wir einen Progress darstellen <- das stand auch im Original und habs versucht zu änder, ohne Erfolg!
    2. th.ReportProgress(offset / inStream.Length * 100)

    VB.NET-Quellcode

    1. Try
    2. Me.Progress.Text = lngBytesCopied.ToString & " Bytes From " & lngSourceFileLength.ToString & " Copied"
    3. Me.ProgressBar1.Value = e.ProgressPercentage.ToString
    4. Catch ex As Exception
    5. MessageBox.Show(ex.Message)
    6. End Try


    Das hochzählen der Bytes klappt aber...

    vielleicht könntet Ihr mir da noch mal weiterhelfen... wäre echt super nett...

    Danke

    lris08 schrieb:

    Me.ProgressBar1.Value = e.ProgressPercentage.ToString

    Aha ...
    EineZahl = IrgendeineZahl.ToString ?
    Dim i as integer = 1.ToString ?

    pb.value = e.ProgressPercentage !

    Außerdem hilft dir natürlich Marquee nicht viel, denn der ist ja für Fälle gedacht, wo man nicht weiß, wie groß der Fortschritt ist. Deswegen zeigt man einfach "Bewegung" unabhängig vom Fortschritt.

    VB.NET-Quellcode

    1. Try
    2. Debug.Print(1)
    3. Exit Sub
    4. Catch ex As Exception
    5. Finally
    6. Debug.Print(2)
    7. End Try

    output:
    1
    2

    Was sagt uns das? Finally wird IMMER ausgeführt, selbst wenn vorher ein "Exit Sub" steht! Im "CancelationPending" kannst du dir also das schließen sparen, da das schließen ja im Finally steht.

    picoflop schrieb:

    Aha ...
    EineZahl = IrgendeineZahl.ToString ?
    Dim i as integer = 1.ToString ?

    pb.value = e.ProgressPercentage !


    ja das mit .tostring - war wirklich unbeabsichtigt.


    Me.ProgressBar1.Value = e.ProgressPercentage

    Hier glaube ich mein Problem:

    VB.NET-Quellcode

    1. offset = inStream.Read(buffer, 0, buffer.Length)
    2. outStream.Write(buffer, 0, offset)
    3. lngBytesCopied += offset
    4. ' WICHTIG: Hier könen wir einen Progress darstellen
    5. th.ReportProgress(offset / inStream.Length * 100)


    offset / inStream.Length müsste ja 0 ergeben wenn ich das richtig nachvollziehe...
    dan * 100 bleibt 0 - somit macht die Prog.Bar auch nix...


    Nachtrag: Bei th.ReportProgress(100) füllt er sie dann ganz schnell aus...
    aber so kanns ja nicht riuchtig sein

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „lris08“ ()

    Mach deine PB mal wieder "normal" (also nicht Marquee). Setze sie auf 0 Min und 100 Max (Prozent!).
    Außerdem darfst du nicht "offset" zur Berechnung verwenden, denn bei dir ist das jedesmal die Länge des gelesenen Streams. du musst also noch was haben wie:
    GeleseneBytes += offset

    Dann berechnest du die Prozentzahl mit:
    Prozent = (GeleseneBytes) / InFileGroesse) * 100
    Und das meldest du dann via ReportProgress, wo du dann die PB auf diesen Wert setzt.

    EDIT: du hast ja schon lngBytesCopied ... du musst es nur verwenden ;)
    Und jetzt funktionierts fast zu 99% :)

    Danke vorab erstmal...

    Diese Werte verwende ich nun: (bereits abgearbeitete Bytes und Filegröße Bytes)

    VB.NET-Quellcode

    1. Me.lblSource.Text = Form2.Label22.Text & "\" & Form2.Label13.Text
    2. Me.lblTarget.Text = Form2.Label11.Tex


    und schon funktionierts...

    VB.NET-Quellcode

    1. ' WICHTIG: Hier könen wir einen Progress darstellen
    2. 'th.ReportProgress(offset / inStream.Length * 100)
    3. th.ReportProgress((lngBytesCopied / lngSourceFileLength) * 100)




    Das einzige was noch ist, am Anfang wenn das Programm gestartet wird, friert es erst mal kurz ein... und die Label's bleiben weis unterlegt - das gibt sich aber dann und es läuft.

    Ist das normal das es einfriert ?



    Nochmals Danke für eure Geduld - ich weis, hab schon echt blöde Fragen gestellt... sorry...