2017-03-07 5 views
1

J'utilise le code suivant pour sérialiser des données, à partir de dataTable. Je remplis les lignes de DataTable et les place dans le dictionnaire. Ne demandez pas pourquoi :)Lire avec BinaryReader ligne par ligne

using(var fileStream = new FileStream(@"D:\temp.bin", FileMode.Create, FileAccess.Write, FileShare.None)) 
using(var bw = new BinaryWriter(fileStream)) 
{ 
    foreach(Dictionary<string, object[]> row in rows) 
    { 
     byte[] bytes = ObjectToByteArray(row); 
     bw.Write(bytes); 
    } 
} 

Avec méthode suivante:

private static byte[] ObjectToByteArray(Dictionary<string, object[]> rows) 
{ 
    var bf = new BinaryFormatter(); 
    using(var ms = new MemoryStream()) 
    { 
     bf.Serialize(ms, rows); 
     return ms.ToArray(); 
    } 
} 

Ce que je suis en train de faire est de désérialiser ligne par ligne, si cela est possible avec BinaryReader. Le problème est que je suis coincé à lire seulement la première rangée.

Ce que je voudrais réaliser est:

using(BinaryReader reader = new BinaryReader(File.Open(@"D:\temp.bin", FileMode.Open))) 
{ 
    int pos = 0; 
    int length = (int)reader.BaseStream.Length; 
    while(pos < length) 
    { 
     byte[] v = reader.ReadBytes(pos); 
     Dictionary<string, object[]> row = FromByteArray(v); 
     // Advance our position variable. 
     pos += row.Count; 
    } 
} 

Le plus gros problème est reader.ReadBytes (XXX) -> ce qui devrait être la valeur à lire? Je ne le sais pas d'avance. Je dois lire la ligne entière et la convertir en dictionnaire. La méthode que je me sers pour la conversion est de retour:

public static Dictionary<string, object[]> FromByteArray(byte[] data) 
{ 
    BinaryFormatter bf = new BinaryFormatter(); 
    using(MemoryStream ms = new MemoryStream(data)) 
    { 
     object obj = bf.Deserialize(ms); 
     return (Dictionary<string, object[]>)obj; 
    } 
} 

Comme je l'ai dit FromByteArray fonctionne très bien pour la première ligne, je ne trouve pas un moyen de lire la ligne suivante.

Lorsque j'utilise BinarryFormatter pour sérialiser un fichier complet, il passe si le fichier n'est pas trop volumineux. Si c'est OOM se produit. La même chose est pour la désérialisation. C'est pourquoi je veux sérialiser/désérialiser partiellement.

Tout essayé et recherché partout. Merci d'aider avec celui-ci.

+2

Quelle est votre définition d'une « ligne » dans un fichier binaire? Dans un fichier texte, les lignes sont délimitées par un retour chariot et un saut de ligne. Peut-être que lorsque vous écrivez les données dans le fichier, vous devez écrire la longueur de chaque «ligne» suivie de ses données. Ensuite, lorsque vous lisez dans le fichier, vous lisez un entier, puis lisez le nombre d'octets spécifié par cet entier pour chaque ligne. –

Répondre

3

Pour chaque itération, enregistrez également dans le fichier la longueur des objets sérialisés suivants.

Lors de la lecture, à chaque itération, lisez d'abord 4 octets (reader.ReadInt32) pour obtenir cette valeur et lisez autant d'octets pour dé-sérialiser.

je pense qu'il devrait ressembler à ceci:

using(var fileStream = new FileStream(@"D:\temp.bin", FileMode.Create, FileAccess.Write, FileShare.None)) 
{ 
    using(var bw = new BinaryWriter(fileStream)) 
    { 
     foreach(Dictionary<string, object[]> row in rows) 
     { 
      byte[] bytes = ObjectToByteArray(row); 
      bw.Write(bytes.Length); 
      bw.Write(bytes); 
     } 
    } 
} 


using(BinaryReader reader = new BinaryReader(File.Open(@"D:\temp.bin", FileMode.Open))) 
{ 
    int length = (int)reader.BaseStream.Length; 
    while(reader.BaseStream.Position != length) 
    { 
     int bytesToRead = reader.ReadInt32(); 
     byte[] v = reader.ReadBytes(bytesToRead); 
     Dictionary<string, object[]> row = FromByteArray(v); 
    } 
}     
+0

MERCI !!! :) Mec je vous possède une bière :) –