czwartek, 28 maja 2009

Uwaga na strumienie (i metodę File.OpenWrite)

Promuj

Tym razem będzie o czymś bardzo prostym, chociaż przyznam, że mnie trochę zdziwiło. Zwykle metody w .NET Framework'u działają tak jak podpowiada mi moja intuicja tym razem było trochę inaczej, a ponieważ po rozmowie w gronie znajomych okazało się, że i inni dali się na to złapać, więc opiszę to jako ostrzeżenie ;).

Zacznijmy więc od początku: Jak można w najprostszy sposób wpisać coś do pliku? Chyba najłatwiej jest stworzyć strumień do zapisu, przy pomocy metody File.OpenWrite, a następnie wpisać do niego dowolne dane. Oczywiście jeśli dany plik nie istnieje ta funkcja sama zadba by go sobie utworzyć, proste?, nieprawdaż? Przeanalizujmy jednak poniższy przykład:

static void Main( string[] args )
{
  //mamy dwa bufory
  //pierwszy dłuższy (15 bajtów/znaków)
  byte[] buffer1 = new byte[ 15 ];
  //drugi krótszy (10 bajtów/znaków)
  byte[] buffer2 = new byte[ 10 ];
  for ( int i = 0; i < buffer1.Length; i++ )
    buffer1[ i ] = 65; //litera: A
  for ( int j = 0; j < buffer2.Length; j++ )
    buffer2[ j ] = 66; //litera: B
  // otwieramy plik (tworzony jest jeśli go
  // jeszcze nie ma)
  using ( Stream file = File.OpenWrite( "myfile.txt" ) )
  {
    file.Write( buffer1, 0, buffer1.Length );
  }
  //ponowny raz otwieramy ten plik do zapisu
  using ( Stream file = File.OpenWrite( "myfile.txt" ) )
  {
    file.Write( buffer2, 0, buffer2.Length );
  }
  // kolejny raz otwieramy ten plik (tym razem do odczytu
  using ( StreamReader reader = new StreamReader( "myfile.txt" ) )
  {
    //wypisujemy na ekran to co odczytujemy z pliku
    Console.WriteLine( reader.ReadToEnd() );
  }
  Console.ReadLine();
}

Jak myślicie co się pojawi na ekranie? A) AAAAAAAAAAAAAAA
B) BBBBBBBBBB
C) wyjątek
D) żadna z powyższych

Czy już znacie odpowiedź? ..... oczywiście to odpowiedź.... D

Czy wszyscy podali taką odpowiedź? bo ja dałem się złapać (myślałem że prawidłowa jest odpowiedź B), natomiast na ekranie pojawi się: BBBBBBBBBBAAAAA. Dlaczego? ano dlatego, że za drugim razem otwieramy już istniejący plik, ustawiamy się na jego początku (bynajmniej nie kasujemy starego) i wpisujemy odpoczątku 10 liter B. Pozostała zawartość pliku jest nie zmieniona.

Skąd się wziął mój błąd, ano myślałem, że działa to podobnie jak strumienie w konsoli:
type plik.txt >plik2.txt - przepisuje zawartość plik.txt do plik2.txt (jeśli plik2.txt istniał zostaje on wykasowany)
type plik.txt >>plik2.txt - dopisuje zawartość plik.txt na końcu plik2.txt (jeśli plik2.txt nie istnieje, to go wcześniej tworzy)

Dodatkowo w MSDN nie ma nic na temat takiego zachowania (np. krótkiego "remark" z ostrzeżeniem).

Ktoś z Was (czytelników) też dał się na to złapać?

Promuj

2 komentarze:

  1. Dlatego zawsze jeśli nie jest się pewnym należy ustawić pozycję od której zaczniemy nasze działania. Metoda Seek. Przykład:
    file.Seek(0, SeekOrigin.End);

    OdpowiedzUsuń

Posty powiązane / Related posts