2010-04-03 4 views
8

Mam metodęStreamReader.ReadToEnd() wraca pusty ciąg

private static String DecompressAndDecode(byte[] data) 
{ 
    GZipStream decompressor = new GZipStream(new MemoryStream(data), CompressionMode.Decompress); 
    StreamReader decompressed = new StreamReader(decompressor, Encoding.UTF8); 
    String result = decompressed.ReadToEnd(); 
    return result; 
} 

mam jakiś tekst zgzipowanego jako wejście, a wynik ma być reprezentacja String tego tekstu. Problem polega na tym, że metoda zwraca pusty ciąg znaków. Zastanawiające jest to, że kiedy przechodzę przez metodę w trybie debugowania i dochodzę do instrukcji return, zmienna wynikowa jest pustym ciągiem, ale jeśli utworzę zegarek dla wyrażenia decompressed.ReadToEnd(), zwróci mi tekst. To, czego oczekiwałbym w tym momencie, to zmienna wynikowa zawierająca wyrażenie tekstowe i wyrażenie dekompresji.ReadToEnd() oceniające pusty ciąg znaków. (Ponowna ocena wyrażenia decompressed.ReadToEnd() zwraca pusty łańcuch zgodnie z oczekiwaniami).

@Edit: I odkryli, że w moim przypadku ReadToEnd() zwraca tekst na drugim wywołaniu zwrotach pustych strun na pierwsze wezwanie, a po drugie wezwanie.

Musi być coś oczywistego, czego tu brakuje.

+0

Czy kodowanie jest w rzeczywistości UTF8? –

+0

Tak, jest to UTF8. – axk

Odpowiedz

21

Myślę, że problem jest pozycja kursora w pary. Za każdym razem po wykonaniu ReadToEnd wskaźnik jest ustawiony na koniec, dlatego możesz go obejrzeć po raz pierwszy.

Uruchom następujący kod przed ReadToEnd, aby ustawić wskaźnik na początek. someStream.Seek(0, SeekOrigin.Begin)

+0

Rozwiązało to problem dla mnie – Aaronontheweb

+0

Nie ma funkcji członka wyszukiwania dla streamReader – stackptr

+0

@stackptr you trzeba go użyć w strumieniu, który podajesz do swojego streamReadera –

1

"Musi być coś oczywistego, czego tu brakuje". - może i ja też ;-)
Zacznijmy od małego, samodzielnego przykładu i zobaczmy, gdzie różni się ono od rzeczywistego kodu.

class SOTest 
{ 
    private static String DecompressAndDecode(byte[] data) 
    { 
    GZipStream decompressor = new GZipStream(new MemoryStream(data), CompressionMode.Decompress); 
    StreamReader decompressed = new StreamReader(decompressor, Encoding.UTF8); 
    String result = decompressed.ReadToEnd(); 
    return result; 
    } 

    private static byte[] foo(string data) 
    { 
    MemoryStream dest = new MemoryStream(); 
    using (GZipStream compressor = new GZipStream(dest, CompressionMode.Compress)) 
    { 
     using (StreamWriter sw = new StreamWriter(compressor)) 
     { 
     sw.Write(data); 
     } 
    } 
    return dest.GetBuffer(); 
    } 


    static void Main() 
    { 
    System.Console.WriteLine(
     DecompressAndDecode(foo("Mary had a little lamb.")) 
    ); 
    return; 
    } 
} 

drukuje Mary had a little lamb.

+0

Dzięki za pomoc! Twój przykład działa. Jedyną różnicą w moim przypadku jest uzyskanie danych z bazy danych SQL przy pomocy SqlDataReader, a tekst jest nieco dłuższy i ma kilka znaków spoza ASCII. Odkryłem, że w moim przypadku ReadToEnd zwraca tekst w drugim wywołaniu. – axk

+0

Czy dzieje się to tylko przy dłuższych danych lub czy można zmniejszyć ilość danych (przekazywanych do DecompressAndDecode (byte []) w celu debugowania? – VolkerK

1

Utwórz własną niestandardową funkcję. To zajmie ścieżkę jako parametr:

static string read(string path) 
    { 
     StreamReader sr = new StreamReader(@path); 
     string txt = ""; 
     while (!sr.EndOfStream) { 
      txt += sr.ReadLine() + "\n"; 
     } 
     sr.Close(); 
     return txt; 
    } 

Następnie nazwać zamiast wezwania do ReadToEnd(). Przetestowałem to i zadziałało.