2010-12-16 7 views
13

Je sais que cette question a déjà été posée sur Stackoverflow, mais n'a pas pu trouver d'explication. Lorsque j'essaie de lire une chaîne à partir d'un tableau d'octets compressés, j'obtiens une chaîne vide lors de la première tentative, à la seconde j'obtiens la chaîne.StreamReader ReadToEnd() renvoie une chaîne vide à la première tentative

Exemple de code:

public static string Decompress(byte[] gzBuffer) 
{ 
    if (gzBuffer == null) 
     return null; 
    using (var ms = new MemoryStream(gzBuffer)) 
    { 
     using (var decompress = new GZipStream(ms, CompressionMode.Decompress)) 
     { 
      using (var sr = new StreamReader(decompress, Encoding.UTF8)) 
      { 
       string ret = sr.ReadToEnd(); 
       // this is the extra check that is needed !? 
       if (ret == "") 
        ret = sr.ReadToEnd(); 
       return ret; 
      } 
     } 
    } 
} 

Toutes les suggestions sont appréciés. - Victor Cassel

+0

Je ne pense pas que vous ayez besoin de la vérification, elle semble redondante. – Nick

Répondre

1

essayer d'ajouter ms.Position = 0 avant string ret = sr.ReadToEnd();

+0

J'ai essayé cela et ça n'aide pas, j'ai aussi essayé ms.Seek (0, SeekOrigin.Begin). –

1

The MSDN Page on the function mentions suivantes:

Si la méthode actuelle jette un OutOfMemoryException, la position du lecteur dans l'objet Stream sous-jacent est avancé par le nombre de caractères que la méthode était capable de lire, mais les caractères déjà lus dans le tampon ReadLine interne sont ignorés. Si vous manipulez la position du flux sous-jacent après avoir lu les données dans le tampon, la position du flux sous-jacent peut ne pas correspondre à la position du tampon interne. Pour réinitialiser le tampon interne, appelez la méthode DiscardBufferedData; Cependant, cette méthode ralentit les performances et ne doit être appelée que lorsque cela est absolument nécessaire.

Peut-être essayer d'appeler DiscardBufferedData() avant ReadToEnd() et voir ce qu'il fait (je sais que vous ne recevez pas l'exception, mais il est tout ce que je peux penser ...)?

+0

Non, l'appel de DiscarBufferedData() n'a pas aidé non plus. –

1

J'espère que cela aide.

Pour ByteArray:

static byte[] CompressToByte(string data) 
{ 
    MemoryStream outstream = new MemoryStream(); 
    GZipStream compressionStream = 
    new GZipStream(outstream, CompressionMode.Compress, true); 
    StreamWriter writer = new StreamWriter(compressionStream); 
    writer.Write(data); 
    writer.Close(); 
    return StreamToByte(outstream); 
} 

static string Decompress(byte[] data) 
{ 
    MemoryStream instream = new MemoryStream(data); 
    GZipStream compressionStream = 
    new GZipStream(instream, CompressionMode.Decompress); 
    StreamReader reader = new StreamReader(compressionStream); 
    string outtext = reader.ReadToEnd(); 
    reader.Close(); 
    return outtext; 
} 

public static byte[] StreamToByte(Stream stream) 
{ 
    stream.Position = 0; 
    byte[] buffer = new byte[128]; 
    using (MemoryStream ms = new MemoryStream()) 
    { 
     while (true) 
     { 
      int read = stream.Read(buffer, 0, buffer.Length); 
      if (!(read > 0)) 
       return ms.ToArray(); 
      ms.Write(buffer, 0, read); 
     } 
    } 
}

Vous pouvez remplacer if(!(read > 0)) avec if(read <= 0). Pour certaines raisons, if(read <= 0) n'est pas affiché Corret ci-dessus.

Pour Stream

static Stream CompressToStream(string data) 
{ 
    MemoryStream outstream = new MemoryStream(); 
    GZipStream compressionStream = 
    new GZipStream(outstream, CompressionMode.Compress, true); 
    StreamWriter writer = new StreamWriter(compressionStream); 
    writer.Write(data); 
    writer.Close(); 
    return outstream; 
} 

static string Decompress(Stream data) 
{ 
    data.Position = 0; 
    GZipStream compressionStream = 
    new GZipStream(data, CompressionMode.Decompress); 
    StreamReader reader = new StreamReader(compressionStream); 
    string outtext = reader.ReadToEnd(); 
    reader.Close(); 
    return outtext; 
}
2

Où est gzBuffer vient? Avez-vous aussi écrit le code qui produit les données compressées? Peut-être que les données de tampon que vous avez sont invalides ou incomplètes, ou peut-être qu'il s'agit de plusieurs flux de dégonflage concaténés ensemble.

+0

J'ai trouvé le bug. C'était comme Michael l'a suggéré dans la routine de compression. J'ai manqué d'appeler Close() sur le GZipStream. compress.Write (raw, 0, raw.Length); compress.Fermer(); return ms.ToArray(); Ce qui s'est passé, c'est que les données semblaient être enregistrées dans un mauvais état qui nécessitait deux appels à ReadToEnd() dans la routine de décompression plus tard pour extraire les mêmes données. Très étrange! –

3

J'ai trouvé le bogue. C'était comme Michael l'a suggéré dans la routine de compression. J'ai manqué d'appeler Close() sur le GZipStream.

public static byte[] Compress(string text) 
{ 
    if (string.IsNullOrEmpty(text)) 
     return null; 

    byte[] raw = Encoding.UTF8.GetBytes(text); 
    using (var ms = new MemoryStream()) 
    { 
     using (var compress = new GZipStream (ms, CompressionMode.Compress)) 
     { 
      compress.Write(raw, 0, raw.Length); 
      compress.Close(); 

      return ms.ToArray(); 
     } 
    } 
} 

Ce qui est arrivé est que les données semblait être sauvé dans un mauvais état qui a nécessité deux appels à ReadToEnd() dans la routine de décompression plus tard pour extraire les mêmes données. Très étrange!

Questions connexes