Stream - limitation du système de fichiers

Résolu/Fermé
Utilisateur anonyme - 6 nov. 2013 à 13:40
 Utilisateur anonyme - 7 nov. 2013 à 08:22
Bonjour à tous,
J'ai un problème lors de l'écriture sur un gros fichier. Mon application à pour rôle de concaténer deux gros fichiers (>20Go) en retirant les doublons.

Tout se passe correctement jusqu'à ce que le fichier soit devenue assez gros (entre 3.5Go et 4Go), et là j'ai une exception :

Impossible de terminer l opération demandée du fait d'une limitation du système de fichiers.


Le code de la fonction qui se charge de l'écriture est :

private void Ecrire(string sLigne)
{
using(StreamWriter sw = new StreamWriter(sFicDest,true,Encoding.UTF8))
{
sw.WriteLine(sLigne);
}
}

Quelqu'un aurai une idée ?

Pour info, je suis sous un système 64bits, sur un disque en ntfs.

naga


PS : j'ai essayé d'écrire bit à bit et à un moment donné, chaque appel à une methode de stream lève l'exception
A voir également:

1 réponse

ElementW Messages postés 4816 Date d'inscription dimanche 12 juin 2011 Statut Contributeur Dernière intervention 5 octobre 2021 1 228
6 nov. 2013 à 14:21
Salut,
si ton apli utilise le .NET 4, il y a les MemoryMappedFile avec ses streams créés par MemoryMappedFile.CreateViewStream.

Sinon, pour du .NET < 4, j'espère que tu utilises des buffers codés manuellement pour ton appli, car laisser l'OS gérer le buffering de très gros fichiers ça passe pas.
Utiliser un BufferedStream améliore grandement les performances en lisant le fichier bloc par bloc. Ce code lit le fichier ligne par ligne mieux qu'avec un simple FileStream:
using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs))
{
string line;
while ((line = sr.ReadLine()) != null)
{
// Le traitement.
}
}
Les BufferedStream peuvent prendre un 2e argument en constructeur: la taille du buffer, de 4Kio (4096 octets) par défaut; il se peut qu'augmenter ou diminuer cette valeur peut améliorer (ou dégrader) la performance selon le type de support de stockage.

Selon ce que je comprends, ton appli est censée trouver les doublons, ça dépend quels genre de doublons mais tu peux utiliser l'algorithme de Rabin-Karp pour ce genre de tâches.
0
Utilisateur anonyme
6 nov. 2013 à 14:59
merci de ta réponse, mais mon problème ne se situe pas à la lecture, mais durant l'écriture. BufferStream semble cependant utile, j'en prend note ;)

J'ai donc fais ce code :



private long Write(string s, long iPos)
{
FileStream fs = new FileStream(sFicDest, FileMode.Open, FileAccess.ReadWrite);
fs.Position = iPos;
for (int i = 0; i < s.Length; i++)
{
char c = s[i];
fs.WriteByte((byte)c);

}
if (i + 1 == s.Length) fs.WriteByte((byte)'\r');
if(i+1==s.Length) fs.WriteByte((byte)'\n');
iPos = fs.Position;
fs.Dispose();
return iPos;
}

et une fois de plus l'exception apparait (au caractère 4094 ... d'après ce que tu me dis ce n'est peu être pas un hasard ;] )

J'ai donc géré l'exception de cette manière :



private long Write(string s, long iPos)
{
FileStream fs = new FileStream(sFicDest, FileMode.Open, FileAccess.ReadWrite);
fs.Position = iPos;
for (int i = 0; i < s.Length; i++)
{
try
{
char c = s[i];
fs.WriteByte((byte)c);
}
catch (Exception)
{
iPos = fs.Position - 1;
fs.Dispose();
string rest = "";
for (; i < s.Length; i++)
rest += s[i];
Write(rest, iPos);
}
}
if (i + 1 == s.Length) fs.WriteByte((byte)'\r');
if(i+1==s.Length) fs.WriteByte((byte)'\n');
iPos = fs.Position;
fs.Dispose();
return iPos;
}

et il semblerai que là ca passe. J'ai lancé le test, mais bon il faut que j'arrive à environ 13/14 go de données traitées pour qu'il apparaisse. Je te redirai ;)

naga
0
Utilisateur anonyme
7 nov. 2013 à 08:22
re !
Donc non ca ne passait pas, le problème venait bien du buffer ! Je suis toujours en train de tester, mais il semble que cette fois ca fonction. Voilà donc mon code :

private long Write(string s, long iPos)
{
FileStream fs = new FileStream(sFicDest, FileMode.Open, FileAccess.ReadWrite);
fs.Position = iPos;
for (int i = 0; i < s.Length; i++)
{
try
{
if (i >= 4090) throw new Exception();
char c = s[i];
fs.WriteByte((byte)c);

if (i + 1 == s.Length) fs.WriteByte((byte)'\r');
if(i+1==s.Length) fs.WriteByte((byte)'\n');
}
catch (Exception)
{
iPos = fs.Position - 1;
fs.Flush();
fs.Dispose();
string rest = "";
for (; i < s.Length; i++)
rest += s[i];
return Write(rest, iPos);
}
}
iPos = fs.Position;
fs.Dispose();
return iPos;
}

merci pour ton aide, ca m'a beaucoup "éclairé".

naga
0