Standardowe strumienie – standardowe kanały komunikacji między komputerem a otoczeniem (zwykle terminalem). Występują w Uniksie i systemach uniksopodobnych, w środowisku uruchomieniowym C, C++ i ich pochodnych. Trzy podstawowe połączenia I/O noszą nazwy: standard input (stdin, standardowy strumień wejścia), standard output (stdout, standardowy strumień wyjścia) i standard error (stderr, standardowy strumień błędów).
Historia
W większości systemów operacyjnych starszych od Uniksa program musiał samodzielnie podłączać się do odpowiednich urządzeń obsługi wejścia/wyjścia.
Unix zapewniał kilka przełomowych możliwości, jedną z nich były tzw. urządzenia abstrakcyjne (ang. abstract devices), co zdjęło z programisty potrzebę znajomości specyfikacji urządzenia, z którym się komunikował. Starsze systemy wymagały od programisty znajomości sposobu składowania i wymiany danych. Unix wyeliminował tę konieczność poprzez koncepcję strumienia danych – uporządkowanej sekwencji bajtów zakończonych znakiem końca pliku (EOF). Program może również zapisywać bajty, jak chce i nie musi deklarować, ile ich będzie, ani jak będą uporządkowane.
Inną możliwością było automatyczne zapewnienie programowi łączności ze standardowymi strumieniami – w starszych systemach programista musiał się o to samodzielnie zatroszczyć.
Unix obsługiwał strumienie, więc biblioteka standardowa języka C też musiała zapewniać ich obsługę. W wyniku większość standardowych bibliotek C umożliwia wykorzystanie strumieni, nawet jeżeli system operacyjny nie zapewnia takiego rozwiązania.
Standardowy strumień wejścia (stdin)
Standardowy strumień wejścia to dane (zwykle tekst) przekazywane do programu. Pobiera on dane poprzez użycie funkcji read. Nie wszystkie programy wymagają danych wejściowych. Przykładowo, dir albo ls wykonują swoją funkcję, nie pobierając żadnych danych ze stdin.
O ile strumień nie jest przekierowany, dane są pobierane z terminala, z którego został uruchomiony program.
Deskryptor pliku standardowego strumienia wejścia wynosi 0 (zero); odpowiadającą mu zmienną z <stdio.h> jest FILE* stdin, a z <iostream> jest std::cin.
Przykład
bash < skrypt.sh # spowoduje wykonanie instrukcji zawartych w pliku # skrypt.sh przez interpretator bash cat < plik.txt # taki sam efekt jak cat plik.txt
Standardowy strumień wyjścia (stdout)
Standardowy strumień wyjścia to strumień, do którego program zapisuje dane wynikowe. Robi to za pomocą funkcji write. Niektóre programy nie zwracają danych wynikowych – na przykład mv nic nie wypisuje, jeżeli przeniesienie się powiodło.
Jeżeli strumień nie jest przekierowany, dane są wysyłane do terminala, z którego uruchomiono program.
Deskryptor pliku standardowego strumienia wyjścia wynosi 1 (jeden); odpowiadającą mu zmienną z <stdio.h> jest FILE* stdout, a z <iostream> jest std::cout. Aby przekierować strumień wyjścia w powłokach bazujących na sh, należy użyć znaków > (jeżeli chcemy zastąpić adres docelowy danymi ze strumienia) lub >> (jeżeli chcemy dopisać dane na końcu pliku docelowego).
Przykład
echo "ABC" > plik.txt # spowoduje wyczyszczenie pliku plik.txt (lub utworzenie # jeśli nie istnieje) i dopisanie znaków ABC echo "CBA" >> plik.txt # spowoduje dopisanie znaków CBA na koniec pliku plik.txt # lub jego utworzenie i dopisanie tych znaków cat plik1.txt > plik2.txt # efekt identyczny jak w przypadku polecenia # cp plik1.txt plik2.txt
Standardowy strumień błędów (stderr)
Standardowy strumień błędów jest zwykle wykorzystywany do wyświetlania komunikatów o błędach i informacjach przydatnych do debugowania. Jest on niezależny od strumienia wyjścia. Zwykle celem strumienia jest, podobnie jak przy stdout terminal, z którego uruchomiono program, aby umożliwić zobaczenie błędu nawet wtedy, gdy strumień wyjścia jest przekierowany. Jeżeli używamy potoku, aby użyć danych wynikowych jakiegoś programu jako danych wejściowych dla innego, to błędy i tak zostaną wypisane na terminalu.
Gdy strumienie wyjścia i błędów mają ten sam cel (np. terminal), to są wyświetlane w takiej kolejności, w jakiej wypisuje je program, o ile nie korzysta się z buforowanego wyjścia. W takim wypadku dane ze stderr wyświetlają się wcześniej, gdyż są zwykle niebuforowane, w przeciwieństwie do stdout, które są zwykle zapisywane w buforze przed wyświetleniem.
Deskryptor pliku standardowego strumienia błędów wynosi 2 (dwa); odpowiadającą mu zmienną z <stdio.h> jest FILE* stderr. <iostream> zapewnia dwie zmienne do obsługi strumienia błędów – std::cerr (niebuforowana) std::clog (buforowana). Aby przekierować strumień błędów w powłokach bazujących na sh, należy użyć znaków 2>.
Przykład
$ rm -rf /tmp # spowoduje usunięcie wszystkich plików z katalogu /tmp, # do których dany użytkownik ma prawa pisania ("w") oraz # wyświetlenie komunikatów o tym, że nie można usunąć # tych plików, do których użytkownik nie posiada praw ("w") $ rm -rf /tmp 2> /dev/null # spowoduje usunięcie wszystkich plików z katalogu /tmp, # do których dany użytkownik ma prawa pisania ("w"), # a komunikaty o błędach zostaną przekierowane # do /dev/null, czyli śmietnika
Biblioteka iostream
Biblioteka iostream używa innych nazw standardowych strumieni niż stdio.h. Różnią się one tylko tym, że zamiast prefiksu std mamy c, i dostępny jest strumień clog, który jest analogiczny do cerr, ale jest buforowany.
Zobacz też
Bibliografia
- KRONOS 2.1 Reference Manual, Control Data Corporation, Part Number 60407000, 1974 (ang.)
- NOS Version 1 Applications Programmer's Instant, Control Data Corporation, Part Number 60436000, 1978 (ang.)
- Level 68 Introduction to Programming on MULTICS, Honeywell Corporation, 1981 (ang.)
- Lions' Commentary on UNIX® Sixth Edition, John Lions, ISBN 1-57398-013-7, 1977 (ang.)