File.ReadAllText/writealltext et gros fichiers

Résolu
surfzoid Messages postés 463 Date d'inscription vendredi 15 août 2003 Statut Membre Dernière intervention 21 avril 2010 - 4 juil. 2007 à 16:18
allthew3 Messages postés 551 Date d'inscription samedi 8 janvier 2005 Statut Membre Dernière intervention 12 avril 2008 - 5 juil. 2007 à 16:17
Bonjour vbfrance community
Je fais un prog Vb qui a pour but de transformer un fichier text formaté windows avec donc des retour chariot  vbcrlf (r\n\)  en format unix/linux vblf (n\) .
Donc je fait un
File.ReadAllText
replace(vbcrlf,vblf)
File.WriteAllText

avec des fichiers de tailles raisonable tout vas bien et ça fonction Nickel sous windows et linux.
Avec des gros fichiers, mon collégue sympas pour qui je fais ça m'en as passé un de 1,7 Giga, j'ai bien evidament un out of memory quand j'essaye de le lire, donc j'ose même pas imaginer la memoire pour le replace et writealltext.

Comment faire pour gerer ça simplement en VB ou C#.
J'image bien un truc déja apperçu comme stream ou lecture/ecriture asynchronne, mais mes compétences s'arrete vraiment au file.read/write.
A voir également:

10 réponses

surfzoid Messages postés 463 Date d'inscription vendredi 15 août 2003 Statut Membre Dernière intervention 21 avril 2010
5 juil. 2007 à 16:16
Oki finalement je vais garder la mienne qui marche quand bien nickel hormis la rapidité,
Donc marci au passage pour le
Dim sb as new StringBuilder

' dans la boucle :
sb.append(streamstr.readline)

que je vais appliquer
3
surfzoid Messages postés 463 Date d'inscription vendredi 15 août 2003 Statut Membre Dernière intervention 21 avril 2010
4 juil. 2007 à 16:19
Voici pour info mon code VB actuel :

Imports System.IO
Module Module1

    Dim WithBck As Boolean = True

    Sub Main()
        Try
            Console.BackgroundColor = ConsoleColor.Black
            Dim P As Integer = Environment.OSVersion.Platform
            Dim SepOs As String = ""
            Dim DebLog As String = Date.Now & vbCrLf            If P 4 Or P 128 Then
                Console.WriteLine("Sytem Unix/Linux" & vbCrLf)
                DebLog &= "Sytem Unix/Linux" & vbCrLf
                SepOs = "/"
            Else
                Console.WriteLine("Sytem Windows" & vbCrLf)
                DebLog &= "Sytem Windows" & vbCrLf
                SepOs = ""
            End If

            Dim Arg() As String = Environment.GetCommandLineArgs()
            Dim InfDirApp As DirectoryInfo
            Dim DirApp As String = String.Empty
            If Arg.LongLength = 1 Then
                Console.WriteLine("usage : " & My.Application.Info.AssemblyName & _
                ".exe *|file*|*.ext")
                Exit Try
            Else
                Dim CleanArg As String = Arg(1).Replace(My.Application.Info.DirectoryPath & SepOs, "")
                InfDirApp = New DirectoryInfo(My.Application.Info.DirectoryPath & SepOs & CleanArg)
                DirApp = InfDirApp.Parent.FullName & SepOs                If Arg(Arg.LongLength - 1) "Bck" Then WithBck True Else WithBck = False
            End If
            'DirApp = My.Application.Info.DirectoryPath & SepOs

            Dim Separ As String = "-------------------------------------------------------------------------------"
            Dim Frst As Boolean = True

            For Each FArg As String In Arg
                Dim FullFArg As String = FArg
                If FArg.IndexOf(SepOs) > -1 Then
                    Dim Parss() As String = Split(FArg, SepOs)
                    FArg = Parss(Parss.LongLength - 1)
                End If

                If FArg <> My.Application.Info.AssemblyName & ".exe" And File.Exists(FullFArg) = True _
                And FArg <> "Bck" Then
                    If Frst = True Then
                        If Directory.Exists(DirApp & "win") = False Then Directory.CreateDirectory(DirApp & "win")
                        If File.Exists(DirApp & "win" & SepOs & "debug.log") = True Then File.Delete(DirApp & "win" & SepOs & "debug.log")
                        Frst = False
                    End If

                    Dim FInfo As New FileInfo(FullFArg)
                    Console.ForegroundColor = ConsoleColor.White
                    Console.WriteLine("Infos su le fichier " & FArg & " Taille : " & FInfo.Length / 1024 & _
                    " Kb; Date : " & FInfo.LastWriteTime & vbCrLf & Separ)
                    DebLog &= "Infos su le fichier " & FArg & " Taille : " & FInfo.Length / 1024 & _
                    " Kb; Date : " & FInfo.LastWriteTime & vbCrLf & Separ

                    Dim Dest As String = DirApp & "win" & SepOs & FArg
                    Console.ForegroundColor = ConsoleColor.White

                    If WithBck = True Then
                        Console.WriteLine("Vérifions si win" & SepOs & FArg & " n'exite pas déjas." & vbCrLf & Separ)
                        DebLog &= "Vérifions si " & Dest & " n'exite pas déjas" & vbCrLf & Separ & vbCrLf
                        If File.Exists(Dest) = False Then
                            Console.ForegroundColor = ConsoleColor.Green
                            Console.WriteLine("Il n'existe pas, ont peut faire une copie de secours du fichier CR+LF." & vbCrLf & Separ)
                            DebLog &= "Il n'existe pas, ont peut faire une copie de secours du fichier CR+LF." & vbCrLf & Separ & vbCrLf
                            File.Copy(FullFArg, Dest, False)
                        Else
                            Console.ForegroundColor = ConsoleColor.DarkYellow
                            Console.WriteLine("Il exite, je n'y touche pas." & vbCrLf & Separ)
                            DebLog &= "Il exite, je n'y touche pas." & vbCrLf & Separ & vbCrLf
                        End If
                    Else
                        Console.WriteLine("Backup ingnoré." & vbCrLf & Separ)
                        DebLog &= "Backup ingnoré." & vbCrLf & Separ & vbCrLf
                    End If

                    Dim Str As String = File.ReadAllText(FullFArg, System.Text.Encoding.Default)
                    Console.ForegroundColor = ConsoleColor.White
                    Console.WriteLine("Tout les CR+LF vont étre remplacé par des LF." & vbCrLf & Separ)
                    DebLog &= "Tout les CR+LF vont étre remplacé par des LF." & vbCrLf & Separ & vbCrLf
                    Str = Str.Replace(vbCrLf, vbLf)
                    Console.ForegroundColor = ConsoleColor.Blue
                    Console.WriteLine("Tout les CR+LF ont été remplacé par des LF." & vbCrLf & Separ)
                    DebLog &= "Tout les CR+LF ont été remplacé par des LF." & vbCrLf & Separ & vbCrLf
                    File.WriteAllText(FullFArg, Str, System.Text.Encoding.Default)
                    Console.ForegroundColor = ConsoleColor.Green
                    Console.WriteLine("Fichier " & FArg & " écrasé avec succés." & vbCrLf & Separ)
                    DebLog &= "Fichier " & FArg & " écrasé avec succés." & vbCrLf & Separ & vbCrLf

                Else

                    If FArg <> My.Application.Info.AssemblyName & ".exe" Then
                        Console.ForegroundColor = ConsoleColor.Red
                        Console.WriteLine(FArg & " n'existe pas ou est un répertoire ?")
                    End If

                End If
            Next
            File.WriteAllText(DirApp & "win" & SepOs & "debug.log", DebLog, System.Text.Encoding.Default)
        Catch ex As Exception
            Console.ForegroundColor = ConsoleColor.Red
            Console.WriteLine(ex.Message)
        End Try
        Console.ForegroundColor = ConsoleColor.Green
        Console.WriteLine(vbCrLf & "Presses une touche, je disparaitrai!")
        While Console.KeyAvailable = False

        End While
    End Sub
End Module
0
allthew3 Messages postés 551 Date d'inscription samedi 8 janvier 2005 Statut Membre Dernière intervention 12 avril 2008 2
4 juil. 2007 à 20:56
et pourquoi pas faire :

Dim fi as new IO.FileInfo(fichier)

if Cint(fi.length / 1024) <= 20000 then
      ' fichier inferieur a 20 Mo, utilise ton systeme file.writealltexte ...
else
     ' fichier supérieur à 20 Mo :
dim lines as new List(Of String)
using sr as new io.streamreader(fichier)
do until sr.endofstream
lines.add(lines)
loop
end using
thread.sleep(0)
using sw as new io.streamwriter(fichier)
for each line as string in lines
sw.writeline(line)
next
end using
end if
0
allthew3 Messages postés 551 Date d'inscription samedi 8 janvier 2005 Statut Membre Dernière intervention 12 avril 2008 2
4 juil. 2007 à 20:56
oups mes espaces sont pas passés
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
surfzoid Messages postés 463 Date d'inscription vendredi 15 août 2003 Statut Membre Dernière intervention 21 avril 2010
5 juil. 2007 à 10:36
Merci allthew3 mais entre tant j'ai trouvé une solution qui consiste aussi a faire du ligne a ligne, mais la je le teste sur une grosse machine, j'en suis a plus de 1 000 000 de lignes du fichier de 1.7 giga qui sont traités et le fichier résultat ne pése que 60 mega au bout de 1 heure, tu pense que ta méthode est plus performante ?
Voici pour info le code que j'ai utilisé :

    Private Sub BigestFile(ByVal FullPath As String)
        Dim Str As String = String.Empty
        Dim RptCr As Long = 0
        Dim RptLine As ULong = 0
        'Dim StrBuf As StreamReader

        If File.Exists(FullPath & ".Nux") = True Then
            Console.ForegroundColor = ConsoleColor.Red
            Console.WriteLine("Le fichier : " & vbCrLf & FullPath & ".Nux" & vbCrLf & _
            "Exist déjas, impossible de l'écrasser" & vbCrLf & Separ & vbCrLf)
            Exit Sub
        End If

        Threading.Thread.Sleep(4000)
        Try
            Dim StreamStr As New System.IO.StreamReader(FullPath, System.Text.Encoding.Default)
            While StreamStr.EndOfStream = False
                Str &= StreamStr.ReadLine & vbLf
                RptLine += 1
                Console.WriteLine("Ligne " & RptLine & " convertie")                If Str.Length >Integer.MaxValue / 1024 Or StreamStr.EndOfStream True Then
                    My.Computer.FileSystem.WriteAllText(FullPath & ".Nux", Str, _
                    True, System.Text.Encoding.Default)
                    RptCr += Str.Length
                    Console.WriteLine(RptCr & " Octets sur " & StreamStr.BaseStream.Length & _
                    " Octets analysé(s)" & vbCrLf & Separ & vbCrLf)
                    Str = String.Empty
                End If
                'Console.WriteLine(Str.Length)
            End While
            StreamStr.Close()

        Catch ex As Exception
            Console.WriteLine(ex.Message)
        End Try
    End Sub
0
allthew3 Messages postés 551 Date d'inscription samedi 8 janvier 2005 Statut Membre Dernière intervention 12 avril 2008 2
5 juil. 2007 à 11:32
oui ma méthode est plus rapide :

Str &= StreamStr.ReadLine : à jamais faire quand dans une boucle ... (les chaines sont immuables, donc tu crées des milliers de copies de ta chaine ... je te dis pas la mémoire derriere !!)
0
surfzoid Messages postés 463 Date d'inscription vendredi 15 août 2003 Statut Membre Dernière intervention 21 avril 2010
5 juil. 2007 à 12:20
Bon je vien d'essayer ta méthode et même si cela peut paraitre plus élegant, les symptomes sont les même car en effet le réel probleme avec un gros fichier c'est de ne pas "gavé" une variable au point de dépasser la quantité de mémoire disponible hors la quand tu ecrit dans une boucle qui englobe la totalité du fichier :
lines.add(lines)
tu as forcément un out of memory lors la taille de lines (lines.length) est supérieur a la mémoire vive disponible, c'est pire encore que d'utilisé la mémoire swap.
0
allthew3 Messages postés 551 Date d'inscription samedi 8 janvier 2005 Statut Membre Dernière intervention 12 avril 2008 2
5 juil. 2007 à 12:25
pour Lines.add : faut s'en servir comme Buffer pour que ce soit bien :

dim lines as new List(Of string)
dim sr as new io.streamreader(fichier)
do until sr.endofstream
lines.add(sr.readline)
loop
sr.close

' ds 1 timer, un thread ou autre :

dim sw as new io.streamwriter(fichier2, true)
for each line as string in lines
sw.writeline(line)
next
sw.flush
sw.close
0
allthew3 Messages postés 551 Date d'inscription samedi 8 janvier 2005 Statut Membre Dernière intervention 12 avril 2008 2
5 juil. 2007 à 12:32
sinon utilise la tienne mais ne fait jamais d'ajout de chaine :
Str &StreamStr.ReadLine> interdit lol

à remplacer par :

Dim sb as new StringBuilder

' dans la boucle :
sb.append(streamstr.readline)

(c'est même beaucoup plus rapide !)

ou sinon 3e méthode le fichier temporaire : 

dim fichier1 as string = ' fichier d'origine
dim fichier2 as string = ' fichier temporaire

dim lines as new list(of string)
Using sr as new io.StreamReader(fichier1)
do until sr.endofstream
lines.add(sr.readline)
if lines.length > 2000 then
WriteNow()
Thread.Sleep(100)
end If
loop
end using
thread.Sleep(100)
' on déplace le fichier temporaire / on le renomme pour qu'il devienne le fichier final

Sub WriteNow()
using sw as new io.streamwriter(fichier2)
for each line as string in lines
sw.writeline(line)
next
sw.fush
end using
end Sub
0
allthew3 Messages postés 551 Date d'inscription samedi 8 janvier 2005 Statut Membre Dernière intervention 12 avril 2008 2
5 juil. 2007 à 16:17
ok @++
0
Rejoignez-nous