Partage
  • Partager sur Facebook
  • Partager sur Twitter

Copie d'un fichier avec un progressbar

Sujet résolu
    5 mai 2011 à 11:07:16

    Bonjours les zéros! j'ai créer un code qui copie un fichier vers un autre destination avec un progress bar qui s'incrémente à chaque fois qu'un octet est transmis vers le nouveaux flux. Et je rencontre 2 soucis:
    1- D'abord Comment allouer une mémoire à un tableau car je suis obligé de réserver trop d'espace mémoire
    =>ce qui montre que le nouveau fichier a une taille 150 Mo
    2- Le copie met trop de temps (même pour un fichier de 24o) et le progressbar défile lentement.
    Besoin d'aide svp voici le code:
    Imports System.IO
    Public Class Form1
        Private source, dest As String
        Private taille, vitesse As Integer
        Private fichier, fichier2 As FileStream
        Private tabl(150000000) As Byte
        Private Sub btncopie_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btncopie.Click
            source = txtnom.Text
            dest = txtdest.Text
            If File.Exists(source) Then
                fichier = New FileStream(source, FileMode.Open, FileAccess.Read)
                fichier2 = New FileStream(dest, FileMode.Create, FileAccess.ReadWrite)
                taille = fichier.Length
                Dim tab(taille) As Byte
                Dim i As Integer
                If fichier.CanRead Then
                    fichier.Position = 0
                    fichier.Read(tab, 0, taille)
                End If
                For Each b As Byte In tab
                    tabl(i) = b
                    i += 1
                Next
                fichier.Dispose()
                txttaille.Text = taille.ToString + "o"
                prgbar.Value = 0
                tim.Enabled = True
            End If
        End Sub
    
        Private Sub tim_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tim.Tick
            txtvitesse.Text = tim.Interval
            If fichier2.CanWrite Then
                fichier2.Position = 0
                For Each b As Byte In tabl
                    If prgbar.Value = 150000000 - taille Then
                        tim.Enabled = False
                    Else
                        prgbar.Value += 1
                        fichier2.WriteByte(b)
                    End If
                Next
            End If
            fichier2.Dispose()
        End Sub
    
       
    End Class
    
    • Partager sur Facebook
    • Partager sur Twitter
      6 mai 2011 à 17:58:47

      Que dire ? Tu t'y prends un peu n'importe comment :euh:
      - Il n'y a pas de raison de copier le fichier en mémoire avant d'écrire le fichier de destination.
      - Copier le fichier octet par octet prend effectivement un temps dingue.
      - Tu devrais effectuer la copie en arrière plan grâce à un BackgroundWorker, pas dans le thread principal.
      - Pourquoi utiliser un timer pour déclencher l'écriture ?
      Voilà déjà quelques points à améliorer :)
      • Partager sur Facebook
      • Partager sur Twitter
        11 mai 2011 à 8:49:30

        ben je croyais qu'en utilisant un timer je pourrais avoir la vitesse du copie ou le temps restant mais en vain j'y arrive pas...je vais essayer cette nouvelle classe.
        - Tu as dis que "copier le fichier en mémoire avant d'ecrire le fichier de destination"est inutile; si je comprend bien je devrais tout simplement utiliser la méthode copy du classe file?
        - Alors si je fais cela comment puis je avoir la progression du copie?
        • Partager sur Facebook
        • Partager sur Twitter
          11 mai 2011 à 13:08:54

          Les timers servent à déclencher une certaine opération après un temps donné, pas à mesurer le temps écoulé.

          Tu peux très bien ouvrir en même temps un flux en lecture sur le fichier source, et un flux en écriture sur le fichier de destination. Tu peux alors lire le fichier par paquets d'octets (et pas par octet) et envoyer immédiatement chaque paquet dans le flux de destination sans avoir à le garder en mémoire :)
          • Partager sur Facebook
          • Partager sur Twitter
            11 mai 2011 à 22:07:36

            j'ai refais mon code en se basent de ce que tu as dit:
            - copie par paquets de 4 octets
            - utilisant le backgroundworker class
            mais ça ne marche pas!!!
            j'obtiens en finale un fichier 15 fois plus grand que l'originale
            Imports System.IO
            Imports System.ComponentModel
            Public Class Form1
                Private source, dest As String
                Private taille As Integer
                Private fichier, fichier2 As FileStream
                Private Sub btncopie_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btncopie.Click
                    Dim bw As New BackgroundWorker
                    bw.RunWorkerAsync()
                    source = txtnom.Text
                    dest = txtdest.Text
                    If File.Exists(source) Then
                        fichier = New FileStream(source, FileMode.Open, FileAccess.Read)
                        fichier2 = New FileStream(dest, FileMode.Create, FileAccess.ReadWrite)
                        taille = fichier.Length
                        Dim tab(4) As Byte
                        fichier.Position = 0
                        fichier2.Position = 0
                        If fichier.CanRead Then
                            While fichier.Position <> taille
                                fichier.Read(tab, 0, 4)
                                fichier2.Write(tab, 0, 4)
                                fichier.Position += 4
                                fichier2.Position += 4
                            End While
                        End If
                    End If
                    While bw.IsBusy
                        prgbar.Increment(1)
                    End While
                    If Not bw.IsBusy Then
                        fichier.Dispose()
                        fichier2.Dispose()
                    End If
                End Sub
            End Class
            
            • Partager sur Facebook
            • Partager sur Twitter
              11 mai 2011 à 22:48:28

              - Ce n'est pas comme ça qu'on utilise un BackgroundWorker, vérifie la doc :)
              - Quand je parlais de paquets d'octets, je pensais à des paquets de plusiers milliers d'octets ;)
              - Les méthodes Read et Write des FileStream ajustent déjà la position après la lecture/l'écriture, il ne faut pas la modifier manuellement.
              • Partager sur Facebook
              • Partager sur Twitter
                16 mai 2011 à 9:47:26

                salut j'ai assez compris le doc
                voici le code:
                Imports System.IO
                Imports System.ComponentModel
                Public Class Form1
                    Private source, dest As String
                    Private fichier, fichier2 As FileStream
                    Private Sub btncopie_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btncopie.Click
                        source = txtnom.Text
                        dest = txtdest.Text
                        If File.Exists(source) Then
                            fichier = New FileStream(source, FileMode.Open, FileAccess.Read)
                            fichier2 = New FileStream(dest, FileMode.Create, FileAccess.ReadWrite)
                        End If
                        bw.RunWorkerAsync()
                    End Sub
                
                    Private Sub bw_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bw.DoWork
                        Dim rapport As Decimal
                        Dim n As Integer = 1
                        rapport = Math.Ceiling(fichier.Length / 1024)
                        Dim tab(1024) As Byte
                        fichier.Position = 0
                        fichier2.Position = 0
                        If fichier.CanRead Then
                            While n <= rapport
                                fichier.Read(tab, 0, 1024)
                                fichier2.Write(tab, 0, 1024)
                                bw.ReportProgress(((n * 1024) / (rapport * 1024))*100)
                                n += 1
                            End While
                        End If
                    End Sub
                    Private Sub bw_ProgressChanged(ByVal sender As System.Object, ByVal e As ProgressChangedEventArgs) Handles bw.ProgressChanged
                        prgbar.Value = e.ProgressPercentage
                    End Sub
                    Private Sub bw_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted
                        fichier.Dispose()
                        fichier2.Dispose()
                    End Sub
                End Class
                

                mais ça prend toujours un peu moins de temps. alors comment fait windows pour copier un fichier asser rapidement?
                • Partager sur Facebook
                • Partager sur Twitter
                  16 mai 2011 à 13:25:33

                  Ca m'a l'air bien mieux :)

                  Une petite remarque cependant: actuellement tu lis le fichier par blocs de 1024 octets et tu calcules ainsi le nombre de blocs à lire. Ca fonctionne bien, mais personnellement j'aurais plutôt fait l'inverse: fixer le nombre de blocs à 50 ou 100, et en déduire la taille des blocs. Après tout tu peux te contenter de faire avancer ta progressbar à chaque pourcent de progression, donc à chaque bloc copié s'il y a 100 blocs.

                  Mon approche fonctionnera mieux pour les gros fichiers, mais moins bien pour les petits car la taille des blocs risque de devenir trop petite et ça ralentira la copie.

                  Du coup tu peux combiner les deux approches: commence par diviser la taille du fichier en 100 ou en 50 pour déduire la taille d'un bloc, et ensuite majore ou minore cette taille de bloc à ta convenance. Par exemple tu peux imposer une taille de bloc minimum de 1024 octets et une taille maximum de 5 Mega. ^^ Si la taille de bloc calculée n'est pas dans cette plage acceptable, tu la ramènes à la valeur acceptable la plus proche.
                  Enfin, maintenant que tu connais la taille des blocs, tu recalcules le nombres de blocs correspondants et tu lances ta copie ;)
                  • Partager sur Facebook
                  • Partager sur Twitter
                    18 mai 2011 à 11:49:37

                    salut, j'y arrive toujours pas car je copie un fichier de 700Mo et voici mes temps de copie:
                    - avec la copie de windows t=43 secondes
                    - copie de 100 blocs de n octets t=56 secondes
                    - copie de 50 blocs de n octets t=1 minute 14 secondes
                    Mais ce t=56s est quand plus rapide de ce que j'avais avant.(merci à toi)
                    Y a t il d'autres moyen de depasser ce 43 secondes??
                    • Partager sur Facebook
                    • Partager sur Twitter
                      18 mai 2011 à 14:47:36

                      La copie Windows est une fonctionnalité "native" de Windows, tu arriveras pas à faire mieux avec un programme en .net
                      • Partager sur Facebook
                      • Partager sur Twitter
                        20 mai 2011 à 7:40:29

                        Est il possible d'utiliser 2 backgroundworker en même temps, est ce que ça ne ralentira pas la mémoire?
                        • Partager sur Facebook
                        • Partager sur Twitter

                        Copie d'un fichier avec un progressbar

                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                        • Editeur
                        • Markdown