Operacje dyskowe w środowisku C (Instrukcja pomocnicza)
Transkrypt
Operacje dyskowe w środowisku C (Instrukcja pomocnicza)
Praktyka programowania
2011/2012
Instrukcja pomocnicza
Operacje dyskowe w środowisku C
(wybrane funkcje wejścia/wyjścia biblioteki “stdio.h”)
Prowadzący: Tomasz Goluch
Wersja: 1.0
I.
Strumienie
Cel: Poznanie pojęcia strumienia oraz rodzajów strumieni standardowych biblioteki ”stdio.h”
oraz jej nowszej wersji <cstdio>.
Strumieniem nazywamy ciąg bajtów informacji o nieokreślonej długości pozwalający na
komunikację pomiędzy procesami1. W środowisku C strumień jest reprezentowany poprzez
typ FILE.
W mamy do dyspozycji następujące strumienie standardowe:
standardowy strumień wejścia – nazwa zmiennej: stdin,
standardowy strumień wyjścia – nazwa zmiennej: stdout,
standardowy strumień błędów – nazwa zmiennej: stderr.
Funkcje pracujące domyślnie na strumieniach standardowych mają swoje ogólniejsze
odpowiedniki pracujące na dowolnych strumieniach, które przekazywane są jako dodatkowy,
pierwszy parametr do danej funkcji. Dodatkowo ich nazwy poprzedzone są przedrostkiem f,
przykładowo uogólnioną wersją funkcji printf() jest funkcja fprintf().
Innymi słowy gdyby do takiej uogólnionej funkcji przekazać jako pierwszy parametr strumień
standardowy na który pracuje jej szczegółowy odpowiednik to ich zachowanie powinno być
identyczne:
W niniejszej instrukcji zostaną omówione
przeznaczonych głównie do pracy z plikami.
II.
jedynie
wersje
funkcji
uogólnionych
Otwieranie i zamykanie strumienia do pliku
Cel: Poznanie różnych trybów pracy strumieni plikowych standardowej biblioteki ”stdio.h”
oraz jej nowszej wersji <cstdio>.
W celu utworzenia strumienia powiązanego z plikiem należy wykorzystać funkcje fopen()
jej bezpieczniejszy odpowiednik fopen_s().
Możemy również użyć funkcji freopen() albo jej bezpieczniejszego odpowiednika
freopen_s()2 – próbują one na początku zamknąć przekazany do nich, jako ostatni parametr,
strumień. Są one przeważnie stosowane do przekierowywania strumieni standardowych.
FILE * fopen(const char * _Filename, const char * _Mode);
errno_t fopen_s(FILE ** _File, const char * _Filename, const char *
_Mode);
1
Procesem nazywamy uruchomiony program któremu zaalokowano pamięć, stos, przydzielono czas procesora itp., nadano
identyfikator PID w systemie.
2
Więcej na temat bezpieczeństwa funkcji biblioteki uruchomieniowej (CRT) można znaleźć tutaj:
http://msdn.microsoft.com/en-us/library/8ef0s5kh.aspx
1
FILE * freopen(const char * _Filename, const char * _Mode,
FILE * _File);
errno_t freopen_s(FILE ** _File, const char * _Filename,
const char * _Mode, FILE * _OldFile);
Przyjmują one cztery parametry:
_File/_OldFile – strumienie z którymi funkcja ma pracować.
_Filename – ścieżka do pliku (względna bądź bezwzględna) + nazwa pliku który ma
zostać otwarty.
_Mode – tryb dostępu do pliku. W tab. 1 przedstawiono dostępne tryby.
Bezpieczniejsze odpowiedniki zwracają wartości typu errno_t na podstawie których można
wywnioskować czy operacja otwarcia zakończyła się powodzeniem.
Tabela 1. Tryby dostępu do pliku
znak
tryb
”r” odczyt
”w” zapis
”a”
dopisywanie
”r+” zapis i odczyt
”w+” zapis i odczyt
”a+”
dopisywanie i odczyt
”t”
”b”
tekstowy
binarny
uwagi
Plik musi istnieć.
Tworzy nowy plik, jeżeli istnieje plik o identycznej nazwie
zostaje on nadpisany.
Tworzy nowy plik, jeżeli istnieje plik o identycznej nazwie
to nowe dane zostają dopisane do końca pliku.
Plik musi istnieć.
Tworzy nowy plik, jeżeli istnieje plik o identycznej nazwie
zostaje on nadpisany.
Tworzy nowy plik, jeżeli istnieje plik o identycznej nazwie
to nowe dane zostają dopisane do końca pliku
Tryb domyślny.
Zapis i odczyt będzie się odbywał w trybie binarnym
(domyślnym jest tryb tekstowy). Jest rozszerzeniem
każdego z sześciu powyższych trybów. Np.: ”w+b” albo
”wb+”.
Aby się upewnić, że są to strumienie analogiczne do standardowych możemy przekierować
deskryptor strumienia wyjściowego tak aby wskazywał na plik. Wykonanie funkcji printf()
spowoduje zapis do pliku zamiast na ekran konsoli:
Jeżeli chcemy dany plik usunąć albo zmienić jego nazwę to z pomocą przychodzą nam
następujące funkcje:
int remove(const char * _Filename); – usuwa plik do którego, jako argument,
została podana ścieżka dostępu.
2
int rename(const char * _OldFilename, const char * _NewFilename);
– zmienia nazwę pliku do którego podana została ścieżka dostępu w pierwszym
argumencie, na nową podaną w drugim.
W celu utworzenia pliku tymczasowego pomocne mogą okazać się funkcje:
FILE * tmpFile(void); – utworzenie pliku tymczasowego.
char * tmpnam( char * _Filename); – wygenerowanie unikalnej nazwy pliku.
Nowo utworzony plik łatwo znaleźć klikająć PPM3 na głównym pliku źródłowym i
wybierając opcję z menu kontekstowego: Open Containing Folder4 – rys. 1.
Rysunek 1. Otwarcie katalogu głównego projektu
Zawsze należy pamiętać aby przed zakończeniem programu pozamykać wszystkie otwarte
pliki. Do zamknięcia jednego, bądź wszystkich plików służą funkcje: fclose()
i fcloseall().
int fclose(FILE * _File);
int fcloseall();
W celu raportowania błędów przydatną może okazać się funkcja perror() która zwraca
informację o błędzie poprzedzoną naszym komentarzem.
void perror(const char * _ErrMsg)
Funkcję tą należy umieszczać zaraz po instrukcji która była przyczyną błędu. W innym
przypadku komunikat błędu może zostać nadpisany przez kolejne wywołanie innej funkcji.
3
4
Prawy przycisk myszy.
Zadziała pod warunkiem, że nie zmieniliśmy domyślnych ustawień projektu.
3
Przykład kodu otwierającego nowy plik w trybie zapisu i odczytu przedstawiono na rys. 2.
Rysunek 2. Przykładowy kod otwierający i zamykający plik
Przy próbie otwarcia nieistniejącego pliku otrzymamy następującą informację wyświetloną na
standardowym wyjściu błędów:
III.
Formatowany zapis i odczyt z pliku
Cel: Poznanie funkcji pozwalających na współpracę ze strumieniem sformatowanym
standardowej biblioteki ”stdio.h” oraz jej nowszej wersji <cstdio>.
Jak wspomniałem w pierwszym rozdziale istnieje kilka rodzajów funkcji działających na
plikach w sposób analogiczny jak odpowiadające im podstawowe funkcje operacji zapisu i
odczytu ze standardowego wejścia/wyjścia. Ich nazwy różnią się dodanym prefiksem f, a
funkcje te dodatkowo jako pierwszy argument otrzymują uchwyt do pliku. Są to między
innymi funkcje fscanf() i fprintf() oraz fscanf_s() i fprintf_s() – które pozwalają
na odczyt i zapis sformatowanego ciągu znaków:
int fscanf(FILE * _File, const char * _Format, ...); – odpowiednik
funkcji scanf().
int fprintf(FILE * _File, const char * _Format, ...); – odpowiednik
funkcji printf().
int fscanf_s(FILE * _File, const char * _Format, ...); – bezpieczny
odpowiednik funkcji fscanf().
int fprintf_s(FILE * _File, const char * _Format, ...); – bezpieczny
odpowiednik funkcji fprintf().
4
Należy pamiętać, że zmienne funkcji fscanf() i fscanf_s() do których będą zapisywane
dane przekazujemy przez referencję używając operatora pozyskania adresu – &. Natomiast do
funkcji fprintf() i fprintf_s zmienne przekazujemy „normalnie” – przez wartość5.
Jak drugi element funkcje te przyjmują ciąg znaków zwany ciągiem formatującym _Format
analogiczne jak w przypadku ich odpowiedników scanf() i printf() pracujących na
strumieniach standardowych.
Tabela 2. Znaki kontrolne używane wewnątrz ciągów formatujących.
sekwencja
\a
\b
\n
\t
\v
\f
\r
\\
\?
\’
\”
\xNN
\DDD
opis
BL – alarm
BS – cofnięcie (backspace)
LF – znak nowej linii
HT – znak tabulacji poziomej
VT – znak tabulacji pionowej
FF – znak powrotu karetki na początek linii
CR – znak powrotu karetki na początek
strony
ukośnik (backslash)
znak zapytania
apostrof
cudzysłów
znak ASCII o kodzie szesnastkowym 0xNN
znak ASCII o kodzie dziesiętnym DDD
Ciąg formatujący to łańcuch znaków ujęty cudzysłowem. Może zawierać: zwykłe znaki,
sekwencje kontrolne (tab. 2) oraz specyfikatory formatowania kolejnych argumentów
przekazanych do funkcji. Specyfikatory formatowania rozpoczynają się od znaku % a ich
składnia jest następująca6:
% [flagi] [szerokość] [.precyzja] [{h|l|ll|I|I32|I64}] typ
Flagi to ciągi znaków określające sposób wyświetlania znaków. Dostępne flagi które można
łączyć ze sobą w ciąg znaków przedstawiono w (tab.2).
Tabela 3. Flagi specyfikatora formatowania.
flaga
+
opis
wyrównanie do lewej wewnątrz pola
znak liczby zawsze będzie drukowany
5
wartość domyślna
wyrównanie do prawej
drukowany jest tylko znak liczby
ujemnej
Sytuacja analogiczna jak ma to miejsce w przypadku funkcji scanf() i printf(). Wartości przekazane do funkcji zostaną
skopiowane do nowopowstałych zmiennych automatycznych które są przechowywane na stosie i stają się niedostępne po
zakończeniu wykonywania funkcji.
6
Więcej szczegółowych informacji na temat pól specyfikujących można znaleźć pod adresem:
http://msdn.microsoft.com/en-us/library/56e442dc.aspx
5
0
(spacja)
#
wypełnienie zerami pola o zadanej
minimalnej szerokości
dodawanie spacji przed wartościami
dodatnimi
w połączeniu ze znakami: o, x i X
powoduje, odpowiednio, dopisanie
prefiksów: 0, 0x i 0X dla nie
niezerowych wartości
w połączeniu ze znakami: f, e, E, a, A,
g i G wymusza pojawienie się znaku
dziesiętnego we wszystkich przypadkach
dodatkowo w połączeniu ze znakami: g
i G zabezpiecza przed obcinaniem
końcowych zer, ignorowane w przypadku
korzystania z c, d, i, u lub s
brak wypełnienia
spacja nie jest dodawana przed
wartościami dodatnimi
znaki puste nie występują
znak dziesiętny pojawia się jedynie w
przypadku występowania po nim liczb
niezerowych
końcowe zera są obcinane
Szerokość określa minimalną liczbę wyświetlanych znaków. przykładowo:
%6d – liczba całkowita drukowana w trybie dziesiętnym przynajmniej na sześciu
znakach,
%.2f – liczba zmiennoprzecinkowa o precyzji dwóch cyfr,
%10f – liczba zmiennoprzecinkowa drukowana przynajmniej na dziesięciu znakach
(licząc włącznie ze znakiem separującym część całkowitą od ułamkowej),
%10.2f – liczba zmiennoprzecinkowa o precyzji dwóch cyfr drukowana przynajmniej
na dziesięciu znakach (licząc włącznie ze znakiem separującym część całkowitą od
ułamkowej).
%20s – drukuje dokładnie 20 znaków z łańcucha. Jeżeli łańcuch jest krótszy w miejsce
pozostałych znaków drukowane są spacje.
W tab. 4 przedstawiono wybrane znaki reprezentujące określone typy danych7:
Tabela 4. Znaki typów specyfikatora konwersji.
sekwencja
c
s
d i
f
e
g
u
x
o
opis
pojedynczy znak
łańcuch znaków, jeśli przekazany argument jest pustym wskaźnikiem
wyświetlany będzie napis "(null)"
liczba dziesiętna ze znakiem
liczba zmiennoprzecinkowa (notacja dziesiętna)
liczba zmiennoprzecinkowa (notacja wykładnicza)
liczba zmiennoprzecinkowa wyświetlana w formacie f albo e w zależności
który z nich jest krótszy dla podanej wartości i precyzji
liczba dziesiętna bez znaku
liczba w kodzie szesnastkowym (bez znaku)
liczba w kodzie ósemkowym (bez znaku)
7
Informacje o dodatkowych (wszystkich) znakach typów danych można znaleźć pod adresem:
http://msdn.microsoft.com/en-us/library/hf4y5e3w.aspx
6
Tabela 5. Znaki typów specyfikatora konwersji.
sekwencja
[…]
[^…]
h
l
ll
%*
opis
nawiasach podawany jest zakres akceptowalnych znaków. Przykładowo: %[az,A-Z,0-9] – oznacza, że do zmiennej typu char* zostaną zapisane ze
strumienia wejściowego wszystkie znaki łacińskie oraz cyfry dziesiętne.
podanie zakresu znaków nieakceptowanych. Przykładowo: %[^a-z] – oznacza,
że zaakceptowane zostaną wszystkie znaki ze strumienia wejściowego z
wyjątkiem małych liczb alfabetu łacińskiego.
flaga precyzująca (short) stosowana przed d u x o
flaga precyzująca (long) stosowana przed d u x o f
flaga precyzująca (long long) stosowana przed: d u x o (nie jest ona
wymagana przed kodem f8)
pominięcie konwersji występującej za flagą
Na rys. 3 pokazano przykładowy kod pomijający dowolny ciąg znaków składający się z:
alfabetu łacińskiego, łącznika oraz znaków diakrytycznych ą i ć, a wczytujący ze strumienia
pierwszą napotkaną w nim liczbę.
Rysunek 3. Pominięcie znaków poprzedzających wczytaną liczbę całkowitą.
Jeżeli chcemy wprowadzić stałą liczbę znaków należy podać tę wartość jako flagę
precyzującą wewnątrz specyfikatora konwersji: %Xs przykładowo:
%20c – do bufora zostanie wprowadzone dokładnie 20 znaków wraz z tzw. białymi
znakami9.
%20s – do bufora zostanie wprowadzone maksymalnie 20 znaków10 plus znak
zakończenia łańcucha wyrazów '\0'.
W przypadku kiedy liczba składa się z mniejszej liczby cyfr niż zadeklarowana jej stała
długość drukowane są poprzedzające ją puste znaki których liczba, razem z liczbą cyfr tej
liczby i ewentualnie znaku separującego część całkowitą od ułamkowej, sumuje się do
sześciu.
8
Zmienna typu Long Double jest utrzymywana w Microsoft Visual C++ tylko dla zapewnienia kompatybilności wstecznej i
nie powinna być aktualnie używana w kodzie. Jej precyzja jest identyczna jak zmiennej Double:
http://msdn.microsoft.com/en-us/library/9cx8xs15.aspx
9
Biały znak to w kodzie ASCII to taki który nie posiada swojej reprezentacji graficznej: '\t' – tabulacja pozioma, '\n' –
znak nowej linii, '\v' – tabulacja pionowa, '\f' – powrót na początek strony '\r' – powrót na początek linii ' ' – spacja.
To czy dany znak jest białym znakiem można sprawdzić za pomocą funkcji isspace() z biblioteki <cctype>.
10
Wystąpienie białego znaku jest traktowane jako zakończenie ciągu znaków i przerywa odczytywanie strumienia
wejściowego.
7
Skanowanie strumienia wejściowego zatrzymuje się jeśli wystąpi:
niezgodność znaku ze strumienia wejściowego ze znakiem z łańcucha znaków
formatujących,
błąd konwersji.
Warto jeszcze wspomnieć że, do współpracy z innymi niż domyślne ustawienia regionalne
służą rozszerzone wersje funkcji fprintf i fscanf:
int _fprintf_l(FILE * _File, const char * _Format, _locale_t _Locale,
...);
int _fscanf_l(FILE * _File, const char * _Format, _locale_t _Locale,
...);
Dodatkowym trzecim argumentem tych funkcji zmienna typu _locale_t oznaczająca
ustawienia międzynarodowe.
IV.
Nieformatowany zapis i odczyt z pliku
Cel: Poznanie funkcji pozwalających na współpracę ze strumieniem niesformatowanym
standardowej biblioteki ”stdio.h” oraz jej nowszej wersji <cstdio>.
Funkcje fgetc() i fputc() oraz _fgetchar() i _fputchar() – pozwalają na odczyt i
zapis pojedynczego znaku.
int fgetc(FILE * _File); – odpowiednik funkcji getc().
int fputc(int _Ch, FILE * _File); – odpowiednik funkcji putc().
Funkcja fputc() analogicznie jak i putc() przyjmuje jako pierwszy parametr int a nie
jakby się mogło wydawać char. To samo dotyczy funkcji _fputchar() i jej odpowiednika
putchar(). Analogicznie funkcja fgetc() analogicznie jak i getc() zwaraca wartość typu
int a nie char. To samo dotyczy funkcji _fgetchar() oraz odpowiadającej jej getchar().
Jest to związane z tym, że funkcje te do swojej pracy wykorzystują znaki specjalne, takie jak
komunikat końca pliku EOF, który jest reprezentowany poprzez wartość -1, a także znaki
nowej linii '\n', które składają się z dwóch znaków typu char i dopiero wewnątrz funkcji
tłumaczone są na właściwy kod ASCII.
int _fgetchar(void); – odczytuje znak ze standardowego wejścia stdin,
int _fputchar(int _Ch); – zapisuje znak do standardowego wyjścia stdout.
Na rys. 4 przedstawiono prosty kod kopiujący zawartość pliku przy pomocy funkcji fgetc()
i fputc().
8
Rysunek 4. Kod kopiujący zawartośd pliku.
Po przeczytaniu znaku można go powrotem zwrócić do strumienia za pomocą funkcji
ungetc(). Do każdego strumienia można zwrócić tylko jeden znak.
int ungetc(int _Ch, FILE * _File);
Funkcje fgets() i fputs() – pozwalają na odczyt i zapis całych ciągów znaków.
char * fgets(char * _Buf, int _MaxCount, FILE * _File);
int fputs(const char * _Str, FILE * _File);
Funkcje fread() i fwrite() – pozwalają na odczyt i zapis w trybie binarnym (nie
sformatowanym) całych bloków bajtów.
size_t fread(void * _DstBuf, size_t _ElementSize,
size_t _Count, FILE * _File);
size_t fwrite(const void * _Str, size_t _Size, size_t _Count,
FILE * _File);
Z powodu bardzo długiego czasu dostępu do dysku dane zapisywane są porcjami. Przed
zapisem na dysk dane przechowywane są w buforze. Aby wymusić zapis do pliku
i opróżnienie bufora możemy posłużyć się następującymi funkcjami fflush() i flushall().
int fflush(FILE * _File);
int flushall();
Ponieważ plik może zawierać dowolnie dużo danych (pomijając ograniczenia sprzętowe i
systemowe) w większości przypadków w trakcie odczytu bądź zapisu nie wiadomo ile jeszcze
bajtów pozostało do jego końca.
Sprawdzenia czy mamy do czynienia z końcem pliku można dokonać sprawdzając czy
wczytaliśmy znak kontrolny końca pliku (ang. End of file). Jest on reprezentowany przez
wartość -1 i nie posiada on swojego odpowiednika w kodzie ASCII dlatego w kodzie
oznaczamy go za pomocą EOF (bez znaków cudzysłowu).
Wymuszenie tego znaku z terminala następuje po wybraniu skrótu klawiaturowego (w
systemie DOS, Windows) Ctrl+Z (w systemie unixowym) Ctrl+D. Możemy również użyć
funkcji feof().
9
int feof(FILE * _File);
W celu sprawdzenia czy ostatnia operacja na pliku wykonana zakończyła się sukcesem można
wykorzystać funkcję ferror.
int ferror(FILE * _File);
Każdy z otwartych plików posiada znacznik miejsca odczytu/zapisu w pliku. W chwili
otwarcia pliku znacznik ten ustawiony jest na początku (wartość 0) a w trybie dopisywania na
końcu (rozmiar pliku).
Podczas zaawansowanych operacji przydatną staje się możliwość manipulacji znacznikiem
pozycji. Funkcje ftell() i fseek() oraz fgetpos() i fsetpos() pozwalają na ustawianie i
zwracanie jego aktualnej pozycji.
long ftell(FILE * _File); – odczytanie aktualnej pozycji wskaźnika względem
początku pliku.
int fseek(FILE * _File, long _Offset, int _Origin); – ustawienie
aktualnej pozycji wskaźnika względem początku, aktualnej pozycji albo końca pliku .
int fgetpos(FILE * _File , fpos_t * _Pos);
int fsetpos(FILE * _File, const fpos_t * _Pos);
Znacznik pozycji można ustawiać w dowolnym miejscu względem początku albo końca
pliku. Pozycjonowanie za końcem pliku jest możliwe ale z przyczyn oczywistych pozwala
tylko na zapis do pliku.
W celu ustawiania pozycji zdefiniowano kilka przydatnych stałych zamieszczonych w tab. 6.
Tabela 6. Znaki kontrolne używane wewnątrz ciągów formatujących.
stała
SEEK_SET
SEEK_CUR
SEEK_END
wartość
0
1
2
opis
początek pliku
bieżąca pozycja w pliku
koniec pliku
Przykładowy kod pozwalający na zbadanie długości pliku przedstawiono na rys. 5.
Rysunek 5. Kod wyświetlający długośd pliku.
Funkcja rewind() pozwala „przewinąć” ten znacznik na początek pliku.
void rewind(FILE * _File);
10
V.
zapis i odczyt z pliku w standardzie UNICODE
Cel: Poznanie funkcji pozwalających na współpracę ze strumieniem sformatowanym
w standardzie UNICODE standardowej biblioteki ”stdio.h” oraz jej nowszej wersji <cstdio>.
Wszystkie funkcje służące do otwarcia pliku, bądź do pracy na sformatowanych danych
posiadają swoje odpowiedniki pracujące w standardzie UNICODE. Przykładowo funkcji
fopen() odpowiada _wfopen(). Funkcje te zamiast zmiennej typu char obsługują zmienną
typu wchar_t oraz wint_t zamiast int reprezentującą pojedynczy dwubajtowy znak
standardu UNICODE.
Tabela 7. Funkcje wspomagające standard UNICODE.
funkcja standardowa
fopen, _fopen_s, _
freopen, _freopen_s
fgetc
fgets
fgetchar,
fprintf, _fprintf_l, fprintf_s,
_fprintf_s_l
fputc
fputs
fputchar
fscanf, fscanf_s, _fscanf_s_l
VI.
funkcja rozszerzona UNICODE
wfopen, wfopen_s
wfreopen, wfreopen_s
fgetwc
fgetws
fgetwchar
fwprintf, fwprintf_l, fwprintf_s,
_fwprintf_s_l
fputwc
fputws
fputwchar
fwscanf, fwscanf_s, _fwscanf_s_l
Przekierowywanie strumieni
Cel: Poznanie możliwości przekierowywania strumienia z poziomu systemu operacyjnego
Windows/Linux.
Z poziomu sytemu operacyjnego możemy łatwo przekierowywać każdy z omawianych w
pierwszym punkcie strumieni. Do tego celu służą nam następujące operatory, zwane
operatorami przekierowywania strumieni:
Tabela 8. Operatory przekierowania strumieni.
operator
<
>
< >
opis
Przekierowanie strumienia wejściowego stdin.
Powoduje pobranie danych wejściowych z pliku zamiast
z okna konsoli użytkownika jako ze standardowego
wejścia.
Przekierowanie strumienia wyjściowego stdout.
Powoduje podanie danych wyjściowych do pliku zamiast
do okna konsoli użytkownika jako do standardowego
wyjścia.
Powyższe operacje można połączyć przekierowywując
jednym poleceniem zarówno standardowe wejście jak i
wyjście.
11
przykład
*.exe11 < in.txt
*.exe > out.txt
*.exe < in.txt > out.txt
W systemie uniksowym pliki wykonywalne różnią się tym, że zamiast rozszerzenia *.exe posiadają specjalną flagę
uprawnień pozwalającą na ich wykonanie.
11
2>
>>
2>>
|
2>&1
Przekierowanie strumienia wyjściowego stderr.
Powoduje podanie informacji o błędach do pliku zamiast
do okna konsoli użytkownika jako do standardowego
strumienia błędów.
Działa podobnie jak w przypadku operatora > różnica
polega na tym, że dane dopisywane są do końca pliku.
Działa podobnie jak w przypadku operatora 2> różnica
polega na tym, że dane dopisywane są do końca pliku.
Stworzenie potoku od stdout jednego procesu do stdin
drugiego procesu.
Połączenie strumieni wyjściowych stdout i stderr.
*.exe 2> out.txt
*.exe >> out.txt
*.exe >>& out.txt
*1.exe | *2.exe
*.exe > out.txt 2>&1
*1.exe 2>&1 | *2.exe
W celu przekierowania strumienia wejściowego i wyjściowego stwórz plik wykonywalny
copier.exe kopiujący dane z wejścia na wyjście (pomocny może okazać się kod z rys. 6).
Rysunek 6. Kod kopiujący dane ze standardowego wejścia na standardowe wyjście.
W katalogu utwórz plik z danymi wejściowymi infile.txt. Uruchom wiersz poleceń i
przejdź do katalogu z plikami12. Wpisz i zatwierdź następującą komendę:
W katalogu bieżącym powinien pojawić się plik tekstowy o nazwie outfile.txt z
zawartością identyczną jak plik infile.txt.
Aby zaobserwować działanie potoku napisz program gen.exe generujące jakieś dane na
standardowe wyjście rys. 7.
Rysunek 7. Kod generujące kolejne liczby alfabetu łacioskiego.
Po skompilowaniu i umieszczeniu pliku w folderze w którym znajduje się wcześniej używany
plik copier.exe zatwierdź następującą komendę:
Na ekranie powinny pojawić się następujące znaki:
12
Aby otworzyć wiersz poleceń w katalogu bieżącym należy przytrzymać klawisz Shift i kliknąć prawym przyciskiem na
wolnym polu w bieżącym oknie. Następnie z menu kontekstowego należy wybrać polecenie: Otwórz okno polecenia tutaj.
12