surfzoid
Messages postés463Date d'inscriptionvendredi 15 août 2003StatutMembreDernière intervention21 avril 2010
-
4 juil. 2007 à 16:18
allthew3
Messages postés551Date d'inscriptionsamedi 8 janvier 2005StatutMembreDernière intervention12 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.
surfzoid
Messages postés463Date d'inscriptionvendredi 15 août 2003StatutMembreDernière intervention21 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
allthew3
Messages postés551Date d'inscriptionsamedi 8 janvier 2005StatutMembreDernière intervention12 avril 20082 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
surfzoid
Messages postés463Date d'inscriptionvendredi 15 août 2003StatutMembreDernière intervention21 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
allthew3
Messages postés551Date d'inscriptionsamedi 8 janvier 2005StatutMembreDernière intervention12 avril 20082 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 !!)
surfzoid
Messages postés463Date d'inscriptionvendredi 15 août 2003StatutMembreDernière intervention21 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.
allthew3
Messages postés551Date d'inscriptionsamedi 8 janvier 2005StatutMembreDernière intervention12 avril 20082 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