DZWON

Są tacy, którzy czytają tę wiadomość przed tobą.
Zapisz się, aby otrzymywać najnowsze artykuły.
E-mail
Nazwa
Nazwisko
Jak chciałbyś przeczytać The Bell?
Bez spamu

Dla ułatwienia obsługi informacje na urządzeniach pamięci masowej są przechowywane w postaci plików.

Plik - nazwany obszar pamięć zewnętrzna, przeznaczony do przechowywania tablicy danych. Dane zawarte w plikach mają najróżniejszy charakter: programy w języku algorytmicznym lub maszynowym; dane początkowe dotyczące działania programów lub wyniki wykonania programu; teksty arbitralne; obrazy graficzne itp.

Katalog (folder, katalog) - nazwany zbiór bajtów na nośniku pamięci zawierający nazwy podkatalogów i plików, używany w systemie plików w celu uproszczenia organizacji plików.

system plików nazywa część funkcjonalna system operacyjny A, który wykonuje operacje na plikach. Przykładami systemów plików są FAT (FAT - File Allocation Table, tabela alokacji plików), NTFS, UDF (używane na płytach CD).

Istnieją trzy główne wersje FAT: FAT12, FAT16 i FAT32. Różnią się one bitowością zapisów w strukturze dysku, tj. liczba bitów przydzielonych do przechowywania numeru klastra. FAT12 jest używany głównie do dyskietek (do 4 KB), FAT16 do małych dysków, FAT32 do dysków FLASH o dużej pojemności (do 32 GB).

Rozważ strukturę system plików na przykładzie FAT32.

Struktura pliku FAT32

Urządzenia pamięci zewnętrznej w systemie FAT32 nie są adresami bajtowymi, lecz blokowymi. Informacje są zapisywane na zewnętrznym urządzeniu pamięci w blokach lub sektorach.

Sektor - minimalna adresowalna jednostka przechowywania informacji na zewnętrznych urządzeniach pamięci. Zazwyczaj rozmiar sektora jest ustalony na 512 bajtów. Aby zwiększyć przestrzeń adresową zewnętrznych urządzeń pamięci, sektory są łączone w grupy zwane klastrami.

Klaster to stowarzyszenie kilku sektorów, które można uznać za niezależną jednostkę o określonych właściwościach. Główną właściwością klastra jest jego rozmiar mierzony liczbą sektorów lub liczbą bajtów.

System plików FAT32 ma następującą strukturę.

Klastry używane do zapisywania plików są numerowane począwszy od 2. Z reguły klaster nr 2 jest używany przez katalog główny, a począwszy od klastra nr 3 przechowywana jest tablica danych. Sektory używane do przechowywania informacji powyżej katalogu głównego nie są grupowane.
Minimalny rozmiar pliku na dysku to 1 klaster.

Sektor startowy zaczyna się od następujących informacji:

  • EB 58 90 - bezwarunkowy oddział i podpis;
  • 4D 53 44 4F 53 35 2E 30 MSDOS5.0;
  • 00 02 - liczba bajtów w sektorze (zwykle 512);
  • 1 bajt - liczba sektorów w klastrze;
  • 2 bajty - liczba sektorów zapasowych.

Ponadto sektor rozruchowy zawiera następujące ważne informacje:

  • 0x10 (1 bajt) – liczba tablic FAT (zwykle 2);
  • 0x20 (4 bajty) - liczba sektorów na dysku;
  • 0x2C (4 bajty) – numer klastra katalogu głównego;
  • 0x47 (11 bajtów) – etykieta woluminu;
  • 0x1FE (2 bajty) - Sygnatura sektora rozruchowego (55 AA).

Sektor informacji o systemie plików zawiera:

  • 0x00 (4 bajty) – podpis (52 52 61 41 );
  • 0x1E4 (4 bajty) – podpis (72 72 41 61 );
  • 0x1E8 (4 bajty) – liczba wolnych klastrów, -1 jeśli nie jest znana;
  • 0x1EC (4 bajty) – numer ostatniego zarejestrowanego klastra;
  • 0x1FE (2 bajty) - sygnatura (55 AA).

Tabela FAT zawiera informacje o stanie każdego klastra na dysku. Dolne 2 bajty tabeli FAT przechowują F8 FF FF 0F FF FF FF FF (odpowiadające stanowi klastrów 0 i 1, fizycznie nieobecnych). Ponadto stan każdego klastra zawiera numer klastra, w którym bieżący plik jest kontynuowany, lub następujące informacje:

  • 00 00 00 00 – klaster jest bezpłatny;
  • FF FF FF 0F to koniec bieżącego pliku.
  • 8 bajtów - nazwa pliku;
  • 3 bajty - rozszerzenie pliku;

Katalog główny zawiera zestaw 32-bitowych rekordów informacyjnych dla każdego pliku, zawierających następujące informacje:

Podczas pracy z długimi nazwami plików (w tym rosyjskimi) nazwa pliku jest zakodowana w systemie kodowania UTF-16. W tym przypadku do zakodowania każdego znaku przydzielone są 2 bajty. W takim przypadku nazwa pliku jest zapisana w postaci następującej struktury:

  • 1-bajtowa sekwencja;
  • 10 bajtów zawiera 5 dolnych znaków nazwy pliku;
  • Atrybut 1 bajt;
  • 1 bajt zarezerwowany;
  • 1 bajt - sprawdź sumę nazwa DOS;
  • 12 bajtów zawiera 3 dolne znaki nazwy pliku;
  • 2 bajty – numer pierwszego klastra;
  • pozostałe znaki długiej nazwy.

Praca z plikami w C

Dla programisty Otwórz plik reprezentowana jako sekwencja odczytywanych lub zapisywanych danych. Kiedy plik jest otwierany, jest powiązany z Przepływ we/wy. Informacje wyjściowe są zapisywane w strumieniu, informacje wejściowe są odczytywane ze strumienia.

Gdy strumień jest otwierany dla I/O, jest kojarzony ze standardową strukturą typu FILE , która jest zdefiniowana w stdio.h . Struktura FILE zawiera niezbędne informacje o pliku.

Otwarcie pliku odbywa się za pomocą funkcji fopen(), która zwraca wskaźnik do struktury typu FILE , który można wykorzystać do kolejnych operacji na pliku.

PLIK *fopen(nazwa, typ);


nazwa to nazwa otwieranego pliku (wraz ze ścieżką),
type jest wskaźnikiem do ciągu znaków definiujących sposób dostępu do pliku:
  • "r" - otwórz plik do odczytu (plik musi istnieć);
  • "w" - otwórz pusty plik do zapisu; jeśli plik istnieje, jego zawartość jest tracona;
  • "a" - otwórz plik do zapisu do końca (do dołączenia); plik jest tworzony, jeśli nie istnieje;
  • "r+" - otwarty plik do odczytu i zapisu (plik musi istnieć);
  • "w+" - otwórz pusty plik do odczytu i zapisu; jeśli plik istnieje, jego zawartość jest tracona;
  • "a+" - otwórz plik do odczytu i dołączenia, jeśli plik nie istnieje, jest tworzony.

Zwracana wartość jest wskaźnikiem do otwartego strumienia. W przypadku znalezienia błędu zwracana jest wartość NULL.

Funkcja fclose() zamyka strumień lub strumienie powiązane z plikami otwartymi za pomocą fopen(). Strumień do zamknięcia jest określony przez argument funkcji fclose().

Wartość zwracana: wartość 0, jeśli strumień został pomyślnie zamknięty; stała EOF, jeśli wystąpił błąd.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#włączać
int main() (
PLIK *fp;
nazwa znaku = "mój.txt" ;
if ((fp = fopen(nazwa, "r" )) == NULL )
{
drukujf( "Nie można otworzyć pliku");
getchar();
zwróć 0;
}
// otwarcie pliku powiodło się
... // wymagane działania na danych
fzamknij(fp);
getchar();
zwróć 0;
}

Odczytywanie znaku z pliku:

char fgetc(strumień);


Argument funkcji jest wskaźnikiem do strumienia typu FILE . Funkcja zwraca kod czytanego znaku. W przypadku osiągnięcia końca pliku lub wystąpienia błędu zwracana jest stała EOF.

Zapisywanie znaku do pliku:

fputc(znak, strumień);

Argumentami funkcji są znak i wskaźnik do strumienia typu FILE . Funkcja zwraca kod czytanego znaku.

Funkcje fscanf() i fprintf() są podobne do funkcji scanf() i printf(), ale działają na plikach danych i mają wskaźnik pliku jako pierwszy argument.

fscanf(strumień, "InputFormat" , args);

W tym artykule nauczymy się odczytywać dane z plików i zapisywać informacje do plików w programach C. pliki w si są używane do przechowywania wyniku programu w języku C i użycia go po ponownym uruchomieniu programu. Na przykład możesz zapisać wyniki obliczeń, statystyki gry.
Aby pracować z plikami w C, musisz dołączyć bibliotekę stdio.h
#włączać
Pracować z plik w si musisz ustawić wskaźnik do pliku zgodnie ze wzorem
FILE *nazwa wskaźnika pliku;
Na przykład
PLIK *fin;
Ustawia wskaźnik płetwy na plik
Następnie musisz otworzyć plik i powiązać go ze wskaźnikiem pliku. Aby otworzyć plik w C do czytania, użyj polecenia
Nazwa wskaźnika pliku = fopen("ścieżka do pliku", "r");
Na przykład następujące polecenie
fin = fopen("C:\\Użytkownicy\\użytkownik\\Desktop\\data.txt", "r");
otworzy plik data.txt znajdujący się na pulpicie wzdłuż ścieżki C:\\Users\\user\\Desktop Aby znaleźć ścieżkę do pliku, możesz wybrać plik za pomocą myszy, kliknij na prawy przycisk myszy i wybierz właściwości pliku. Sekcja Lokalizacja pokaże ścieżkę do pliku. Zauważ, że w C ścieżka jest określona dwoma ukośnikami.
Po pracy z plikiem w C należy go zamknąć poleceniem
fclose(nazwa wskaźnika pliku)

Odczytywanie informacji z pliku tekstowego w C

Aby móc odczytać rosyjskie znaki z pliku, musisz skonfigurować pracę z cyrylicą za pomocą polecenia
setlocale(LC_ALL, "angielski");

W takim przypadku konieczne jest włączenie #include na początku programu

instrukcja fscanf()

Aby przeczytać słowo z plik w si używane jest polecenie fscanf(). To polecenie jest podobne do polecenia wprowadzania informacji z klawiatury, tylko pierwszy parametr jest wskaźnikiem do pliku
fscanf(wskaźnik do pliku,"%format wejściowy1% format wejściowy2...",&zmienna1,&zmienna2...);
Na przykład polecenie
fscanf(fin,"%d%d%d",&a,&b,&c);
odczytuje z pliku, który jest powiązany ze wskaźnikiem pliku, fin ciąg trzech zmiennych całkowitych
Spójrzmy na przykład programu, który czyta z plik tekstowy data.txt, który zawiera informacje o trzech kolumnach cyfr i zapisuje je w tablicach. Dla każdej kolumny informacji istnieje tablica. Szczegóły na temat.
#włączać
#włączać
Główny()
(wew;
intb;
int c;
wew;
// zdefiniuj wskaźnik pliku
PLIK *fin;
// otwórz plik do odczytu
fin = fopen("C:\\Użytkownicy\\użytkownik\\Desktop\\data.txt", "r");
// odczytaj wiersz po wierszu z pliku
dla (i=0;i<3;i++)
{
// odczytaj ciąg trzech wartości pliku i zapisz do tablic
fscanf(fin,"%d%d%d",&a[i],&b[i],&c[i]);
}
// wyprowadzanie tablic na ekran
dla (i=0;i<3;i++)
{
printf("%d %d %d",a[i],b[i],c[i]);
}
getch();
// zamknij plik
fzamknij(płetwy);
}

Odczytywanie wiersz po wierszu informacji z pliku do C. Funkcja fgets ()

Instrukcja fscanf() odczytuje słowo z pliku, tj. do pierwszego pola żetonu.
Aby odczytać z pliku całą linię z pliku w C, użyj konstrukcji
if (NULL != fgets (zmienna łańcuchowa, długość łańcucha, wskaźnik pliku))
{
akcje podczas czytania ciągu
}

Na przykład program w C, który odczytuje dwa wiersze z pliku i wyświetla je na ekranie.
#włączać
#włączać
#włączać
Główny()
{
// ustaw zmienne łańcuchowe
charst1;
charst2;
//zdefiniuj wskaźnik pliku
PLIK *fin;
// skonfiguruj pracę z cyrylicą
setlocale(LC_ALL, "angielski");
// otwórz plik do odczytu
fin = fopen("C:\\data.txt", "r");
// odczytaj pierwszą linię z pliku
if (NULL != fgets (st1, 100, fin))
{
// wyświetla ciąg na ekranie
printf("%s",st1);)
// odczytaj drugą linię z pliku
if (NULL != fgets (st2, 100, fin))
{
// wyświetla ciąg na ekranie
printf("%s",st2);)
// zamknij plik do odczytu
fzamknij(płetwy);
}

Zapisywanie informacji do pliku tekstowego w C

Aby zapisać dane do pliku w C, musisz otworzyć plik w trybie zapisu
Nazwa wskaźnika pliku = fopen("ścieżka do pliku", "w");
Aby pisać do wiersza pliku tekstowego, używane jest polecenie fprnitf(), które jest podobne do polecenia w C tylko pierwszy parametr jest wskaźnikiem do pliku
fprintf (nazwa wskaźnika pliku „%input format”, zmienne);
Na przykład zapisanie do pliku out.txt wartości zmiennej a
a=10;
fout = fopen("C:\\Użytkownicy\\użytkownik\\Desktop\\out.txt", "w");
fprintf(fout”,%d”, a);

Przykład programu w C, który prosi o dwie liczby i zapisuje obie te liczby oraz ich sumę do pliku out.txt

#włączać
#włączać

Główny()
(wew;
intb;
int c;
PLIK *fout;
fout = fopen("C:\\Użytkownicy\\użytkownik\\Desktop\\out.txt", "w");
printf("Wprowadź pierwszą liczbę");
scanf("%d", &a);
printf("Wprowadź drugą liczbę");
scanf("%d", &b);
c=a+b;
fprintf(fout,"%d %d %d",a,b,c);
getch();
fzamknij(fout);
}

Wcześniej przy wprowadzaniu i wyprowadzaniu danych pracowaliśmy ze standardowymi strumieniami - klawiaturą i monitorem. Przyjrzyjmy się teraz, jak język C implementuje pobieranie danych z plików i zapisywanie ich w nich. Przed wykonaniem tych operacji należy otworzyć i uzyskać dostęp do pliku.

W języku programowania C wskaźnik do pliku jest typu FILE, a jego deklaracja wygląda tak:
PLIK *mojplik;

Z drugiej strony funkcja fopen() otwiera plik pod adresem określonym jako pierwszy argument w trybie odczytu ("r"), zapisu ("w") lub append ("a") i zwraca do niego wskaźnik do programu. Dlatego proces otwierania pliku i łączenia go z programem wygląda mniej więcej tak:
mojplik = fopen("hello.txt", "r");

Podczas odczytywania lub zapisywania danych do pliku, dostęp do nich uzyskuje się za pomocą wskaźnika pliku (w tym przypadku myfile).

Jeżeli z jakiegoś powodu (pod podanym adresem nie ma pliku, dostęp do niego jest zabroniony) funkcja fopen() nie może otworzyć pliku, to zwraca NULL. W prawdziwych programach błąd otwierania pliku jest prawie zawsze obsługiwany w gałęzi if, ale będziemy to dalej pomijać.

Deklaracja funkcji fopen() jest zawarta w pliku nagłówkowym stdio.h, więc jej włączenie jest wymagane. Typ struktury FILE jest również zadeklarowany w stdio.h.

Po zakończeniu pracy z plikiem zwyczajowo zamyka się go w celu uwolnienia bufora od danych iz innych powodów. Jest to szczególnie ważne, jeśli program nadal działa po pracy z plikiem. Zerwanie powiązania między plikiem zewnętrznym a wskaźnikiem do niego z programu odbywa się za pomocą funkcji fclose(). Jako parametr przyjmuje wskaźnik pliku:
fclose(mojplik);

W programie można otworzyć więcej niż jeden plik. W takim przypadku każdy plik musi być powiązany z własnym wskaźnikiem pliku. Jeśli jednak program najpierw działa z jednym plikiem, a następnie go zamyka, to wskaźnika można użyć do otwarcia drugiego pliku.

Odczytywanie i zapisywanie do pliku tekstowego

fscanf()

Funkcja fscanf() ma podobne znaczenie do funkcji scanf(), ale w przeciwieństwie do niej pobiera sformatowane wejście z pliku, a nie ze standardowego wejścia. Funkcja fscanf() przyjmuje parametry: wskaźnik pliku, ciąg formatujący, adresy obszarów pamięci do zapisu danych:
fscanf(mójplik, "%s%d", str, &a);

Zwraca liczbę pomyślnie odczytanych danych lub EOF. Spacje, znaki nowego wiersza są brane pod uwagę jako separatory danych.

Załóżmy, że mamy plik zawierający następujący opis obiektów:

Jabłka 10 23,4 banany 5 25,0 chleb 1 10,3

#włączać main() ( PLIK * plik; struct food ( char name[ 20 ] ; unsigned qty; float price; ) ; struct food shop[ 10 ] ; char i= 0 ; file = fopen ("fscanf.txt" , "r" ) ; while (fscanf (plik, "%s%u%f" , shop[ i] .name , & (shop[ i] .qty ) , & (shop[ i] .price ) ) != EOF) ( printf ("%s %u %.2f \n", sklep[ i] .nazwa , sklep[ i] .ilość , sklep[ i] .cena ); i++; ) )

W takim przypadku deklarowana jest struktura i tablica struktur. Każdy wiersz z pliku odpowiada jednemu elementowi tablicy; element tablicy to struktura zawierająca ciąg znaków i dwa pola numeryczne. Pętla odczytuje jeden wiersz na iterację. Gdy napotkany zostanie koniec pliku, fscanf() zwraca EOF i pętla się kończy.

fgets()

Funkcja fgets() jest podobna do funkcji gets() i wykonuje wejście wiersz po wierszu z pliku. Jedno wywołanie fgets() odczyta jedną linię. W takim przypadku nie można odczytać całej linii, a jedynie jej część od początku. Opcje fgets() wyglądają tak:
fgets (tablica_znaków, liczba_znaków do odczytania, wskaźnik do pliku)

Na przykład:
fgets(str, 50, mój plik)

Takie wywołanie funkcji odczyta z pliku skojarzonego ze wskaźnikiem myfile jeden wiersz tekstu w całości, jeśli jego długość jest mniejsza niż 50 znaków, łącznie ze znakiem "\n", który funkcja będzie również przechowywać w tablicy. Ostatnim (50.) elementem tablicy str będzie znak "\0" dodany przez fgets() . Jeśli ciąg jest dłuższy, funkcja odczyta 49 znaków i napisze "\0" na końcu. W takim przypadku "\n" nie będzie zawarte w czytanej linii.

#włączać #define N 80 main() ( PLIK * plik; char arr[ N] ; plik = fopen ("fscanf.txt" , "r" ) ; while (fgets (arr, N, plik) != NULL) printf (" %s" , arr) ; printf(" \n") ; fclose(plik); )

W tym programie, w przeciwieństwie do poprzedniego, dane są wczytywane wiersz po wierszu do tablicy arr. Kiedy następna linia zostanie przeczytana, poprzednia zostanie utracona. Funkcja fgets() zwraca NULL, jeśli nie może odczytać następnej linii.

getc() lub fgetc()

Funkcja getc() lub fgetc() (obie działają) pozwala na pobranie następnego znaku z pliku.

while ((arr[ i] = fgetc (plik) ) != EOF) ( if (arr[ i] == " \n") ( arr[i] = " \0 " ; printf("%s \n", arr) ; ja = 0 ) w przeciwnym razie i++; ) przyp[i] = " \0 " ; printf("%s \n", arr) ;

Kod podany jako przykład wypisuje dane z pliku na ekran.

Zapisywanie do pliku tekstowego

Podobnie jak wejście, wyjście do pliku może być inne.

  • Sformatowane wyjście. Funkcja fprintf (plik_wskaźnik, format_string, zmienne) .
  • Opublikuj dane wyjściowe. Funkcja fputs(string, filepointer) .
  • Wyjście symboliczne. fputc() lub putc(znak, wskaźnik pliku) .

Poniżej znajdują się przykłady kodu, które wykorzystują trzy sposoby wyprowadzania danych do pliku.

Zapis do każdego wiersza pliku pola jednej struktury:

plik = fopen("fprintf.txt" , "w" ) ; while (scanf ("%s%u%f" , sklep[ i] .nazwa , & (sklep[ i] .qty ) , & (sklep[ i] .cena ) ) != EOF) ( fprintf (plik, " %s %u %.2f \n", sklep[ i] .nazwa , sklep[ i] .ilość , sklep[ i] .cena ); i++; )

Wyjście linia po linii do pliku (fputs() , w przeciwieństwie do samego puts(), nie umieszcza "\n" na końcu linii):

while (pobiera (arr) != NULL) ( fputs (arr, plik) ; fputs (" \n",plik); )

Przykład wyjścia znak po znaku:

while ((i = getchar() ) != EOF) putc (i, plik) ;

Odczytywanie i zapisywanie do pliku binarnego

Możesz pracować z plikiem nie jako sekwencją znaków, ale sekwencją bajtów. W zasadzie nie można pracować z plikami nietekstowymi w inny sposób. Jednak w ten sposób możesz również czytać i zapisywać pliki tekstowe. Zaletą tej metody dostępu do pliku jest szybkość odczytu i zapisu: znaczny blok informacji można odczytać / zapisać podczas jednego dostępu.

Podczas otwierania pliku do dostępu binarnego, drugim argumentem funkcji fopen() jest łańcuch „rb” lub „wb”.

Temat pracy z plikami binarnymi jest dość złożony, jego przestudiowanie wymaga osobnej lekcji. Tutaj zostaną odnotowane tylko cechy funkcji odczytu i zapisu do pliku, który jest uważany za strumień bajtów.

Funkcje fread() i fwrite() przyjmują jako parametry:

  1. adres obszaru pamięci, z którego dane są zapisywane lub odczytywane,
  2. rozmiar jednego podanego dowolnego typu,
  3. ilość danych do odczytu o określonej wielkości,
  4. wskaźnik pliku.

Te funkcje zwracają liczbę pomyślnie odczytanych lub zapisanych danych. Tych. możesz "zamówić" odczyt 50 elementów danych, a otrzymasz tylko 10. Nie będzie błędu.

Przykład użycia funkcji fread() i fwrite():

#włączać #włączać main() ( PLIK * plik; char półka1[ 50 ] , półka2[ 100 ] ; int n, m; plik = fopen ("shelf1.txt" , "rb" ) ; n= fread (shelf1, sizeof(char ) , 50 , plik) ; fclose (plik) ; plik = fopen ("shelf2.txt" , "rb" ) ; m= fread (półka2, sizeof (char ) , 50 , plik) ; fclose (plik) ; półka1[ n] = " \0 " ; półka2[m] = " \n"; półka2[ m+1 ] = " \0 " ; plik = fopen("sklep.txt" , "wb" ); fwrite (strcat (półka2, półka1) , sizeof (char ) , n+ m, plik) ; fclose(plik); )

Tutaj podjęto próbę odczytania 50 znaków z pierwszego pliku. n przechowuje liczbę faktycznie odczytanych znaków. Wartość n może wynosić 50 lub mniej. Dane są umieszczane w ciągu. To samo dzieje się z drugim plikiem. Następnie pierwszy wiersz jest dołączany do drugiego, a dane są zrzucane do trzeciego pliku.

Rozwiązywanie problemów

  1. Napisz program, który pyta użytkownika o nazwę (adres) pliku tekstowego, a następnie otwiera go i liczy w nim liczbę znaków i wierszy.
  2. Napisz program, który zapisuje do pliku dane otrzymane z innego pliku i zmodyfikowane w taki czy inny sposób przed zapisaniem. Każda linia danych otrzymanych z pliku musi być umieszczona w strukturze.

Ostatnia aktualizacja: 31.10.2015

Do pracy z katalogami w przestrzeni nazw System.IO zaprojektowano dwie klasy: Directory i DirectoryInfo .

Klasa katalogu

Klasa Directory udostępnia szereg statycznych metod zarządzania katalogami. Niektóre z tych metod to:

    CreateDirectory(path) : tworzy katalog w określonej ścieżce

    Delete(path) : usuwa katalog w podanej ścieżce

    Exists(path) : określa, czy katalog w określonej ścieżce istnieje. Zwraca prawdę, jeśli istnieje, fałsz, jeśli nie.

    GetDirectories(path) : Pobiera listę katalogów w ścieżce

    GetFiles(path) : Pobiera listę plików w ścieżce katalogu

    Move(sourceDirName, destDirName): przenosi katalog

    GetParent(path) : pobierz katalog nadrzędny

Klasa DirectoryInfo

Ta klasa zapewnia funkcje tworzenia, usuwania, przenoszenia i innych operacji na katalogach. Pod wieloma względami jest podobny do Katalogu. Niektóre z jego właściwości i metod to:

    Create() : tworzy katalog

    CreateSubdirectory(path) : tworzy podkatalog w określonej ścieżce

    Delete() : usuwa katalog

    Właściwość Exists: określa, czy katalog istnieje

    GetDirectories() : Pobiera listę katalogów

    GetFiles() : pobierz listę plików

    MoveTo(DestDirName) : przenosi katalog

    Właściwość nadrzędna: pobieranie katalogu nadrzędnego

    Właściwość root: pobieranie katalogu głównego

Spójrzmy na przykłady użycia tych klas

Uzyskiwanie listy plików i podkatalogów

string dirName = "C:\\"; if (Directory.Exists(dirName)) ( Console.WriteLine("Podkatalogi:"); string dirs = Directory.GetDirectories(dirName); foreach (string s w katalogach) ( Console.WriteLine(s); ) Console.WriteLine( ); Console.WriteLine("Files:"); string files = Directory.GetFiles(dirName); foreach (ciąg znaków w plikach) ( Console.WriteLine(s; ) )

Zwróć uwagę na użycie ukośników w nazwach plików. Albo używamy podwójnego ukośnika: "C:\\" , albo pojedynczego, ale następnie umieszczamy znak @ przed całą ścieżką: @"C:\Program Files"

Utwórz katalog

ścieżka ciągu = @"C:\SomeDir"; podścieżka ciągu = @"program\avalon"; DirectoryInfo dirInfo = new DirectoryInfo(ścieżka); if (!dirInfo.Istnieje) ( dirInfo.Create(); ) dirInfo.CreateSubdirectory(podścieżka);

Najpierw sprawdzamy, czy taki katalog istnieje, bo jeśli istnieje, to nie będzie można go utworzyć, a aplikacja wyrzuci błąd. W rezultacie otrzymamy następującą ścieżkę: „C:\SomeDir\program\avalon”

Uzyskiwanie informacji o katalogu

string dirName = "C:\\Program Files"; DirectoryInfo dirInfo = new DirectoryInfo(dirName); Console.WriteLine($"Nazwa katalogu: (dirInfo.Name)"); Console.WriteLine($"Pełna nazwa katalogu: (dirInfo.FullName)"); Console.WriteLine($"Czas utworzenia katalogu: (dirInfo.CreationTime)"); Console.WriteLine($"Katalog główny: (dirInfo.Root)");

Usuwanie katalogu

Jeśli po prostu zastosujemy metodę Delete do niepustego folderu, który zawiera jakiekolwiek pliki lub podkatalogi, aplikacja zgłosi błąd. Dlatego do metody Delete musimy przekazać dodatkowy parametr typu logicznego, który wskaże, że folder powinien zostać usunięty wraz z całą jego zawartością:

String dirName = @"C:\SomeFolder"; try ( DirectoryInfo dirInfo = new DirectoryInfo(dirName); dirInfo.Delete(true); Console.WriteLine("Katalog usunięty"); ) catch (wyjątek ex) ( Console.WriteLine(ex.Message); )

String dirName = @"C:\SomeFolder"; Directory.Delete(nazwa_katalogu, prawda);

Przenoszenie katalogu

ciąg oldPath = @"C:\SomeFolder"; string nowaŚcieżka = @"C:\SomeDir"; DirectoryInfo dirInfo = new DirectoryInfo (stara ścieżka); if (dirInfo.Exists && Directory.Exists(nowaPath) == false) ( dirInfo.MoveTo(nowaPath); )

Przy przenoszeniu musimy wziąć pod uwagę, że nowy katalog, do którego chcemy przenieść całą zawartość starego katalogu nie może istnieć.

Operacja operacji we/wy na plikach w C++ jest prawie taka sama jak w przypadku zwykłych operacji we/wy (ale z kilkoma niuansami).

Klasy we/wy pliku

Jest trzy główne klasy I/O w C++:

outstream(jest dzieckiem klasy );

fstream(jest dzieckiem klasy iostream).

Za pomocą tych klas można wykonać jednokierunkowe wejście pliku, jednokierunkowe wyjście pliku i dwukierunkowe wejście/wyjście pliku. Aby z nich skorzystać, wystarczy podłączyć fstream.

W przeciwieństwie do strumieni cout, cin, cerr i clog, które są natychmiast użyteczne, strumienie plików muszą być jawnie ustawione przez programistę. Oznacza to, że aby otworzyć plik do odczytu i/lub zapisu, musisz utworzyć obiekt odpowiedniej klasy wejścia/wyjścia pliku, określając nazwę pliku jako parametr. Następnie za pomocą operatorów wstawiania (<<) или извлечения (>>), możesz zapisać dane do pliku lub odczytać zawartość pliku. Potem finał - musisz zamknąć plik: jawnie zadzwoń metoda close() lub po prostu pozwól zmiennej I/O pliku wyjść poza zakres (klasa I/O pliku automatycznie zamknie ten plik za nas).

Plik wyjściowy

Klasa ofstream służy do zapisu do pliku. Na przykład:

#włączać #włączać #włączać // aby użyć exit() int main() ( używając przestrzeni nazw std; // ofstream służy do zapisywania danych do pliku // Utwórz plik SomeText.txt ofstream outf("SomeText.txt"); // Jeśli możemy nie otwieraj tego pliku, aby zapisać dane do if (!outf) ( // Następnie wypisz komunikat o błędzie i wykonaj exit() cerr<< "Uh oh, SomeText.txt could not be opened for writing!" << endl; exit(1); } // Записываем в файл следующие две строчки outf << "See line #1!" << endl; outf << "See line #2!" << endl; return 0; // Когда outf выйдет из области видимости, то деструктор класса ofstream автоматически закроет наш файл }

#włączać

#włączać

#włączać // aby użyć exit()

int main()

używając przestrzeni nazw std ;

// ofstream służy do zapisywania danych do pliku

// Utwórz plik SomeText.txt

ofstream outf("JakiśTekst.txt" ) ;

// Jeśli nie możemy otworzyć tego pliku, aby zapisać w nim dane

jeśli(!outf)

// Następnie wypisz komunikat o błędzie i wykonaj exit()

zły<< << endl ;

wyjście(1) ;

// Zapisz następujące dwie linie do pliku

outf<< "See line #1!" << endl ;

outf<< "See line #2!" << endl ;

zwróć 0 ;

// Gdy outf wyjdzie poza zakres, destruktor klasy ofstream automatycznie zamknie nasz plik

Jeśli zajrzysz do katalogu swojego projektu ( RMB na karcie z nazwą pliku .cpp w programie Visual Studio > "Otwórz folder zawierający"), zobaczysz plik o nazwie SomeText.txt, który zawiera następujące wiersze:

Zobacz wiersz nr 1!
Zobacz wiersz nr 2!

Pamiętaj, że możemy również użyć metoda put() zapisać jeden znak do pliku.

Wejście do pliku

#włączać #włączać #włączać #włączać // aby użyć exit() int main() ( używając przestrzeni nazw std; // ifstream służy do odczytu zawartości pliku // Spróbuj odczytać zawartość pliku SomeText.txt ifstream inf("SomeText.txt") ; // Jeśli nie możemy otworzyć tego pliku, aby odczytać jego zawartość if (!inf) ( cerr<< "Uh oh, SomeText.txt could not be opened for reading!" << endl; exit(1); } // Пока есть данные, которые мы можем прочитать while (inf) { // То перемещаем эти данные в строку, которую затем выводим на экран string strInput; inf >> strInput; Cout<< strInput << endl; } return 0; }

#włączać

#włączać

#włączać

#włączać // aby użyć exit()

int main()

używając przestrzeni nazw std ;

// ifstream służy do odczytywania zawartości pliku

// Jeśli nie możemy otworzyć tego pliku, aby odczytać jego zawartość

jeśli(!inf)

// Następnie wypisz następujący komunikat o błędzie i wykonaj exit()

zły<< << endl ;

wyjście(1) ;

// Dopóki istnieją dane, które możemy odczytać

podczas(inf)

// Następnie przenosimy te dane do ciągu, który następnie wyświetlamy na ekranie

ciąg strInput ;

inf >> strInput ;

Cout<< strInput << endl ;

zwróć 0 ;

// Gdy inf wyjdzie poza zakres, destruktor klasy ifstream automatycznie zamknie nasz plik

Widzieć
linia
#1!
Widzieć
linia
#2!

Hmm, nie do końca tego chcieliśmy. Jak już wiemy z poprzednich lekcji, operator ekstrakcji pracuje z „danymi sformatowanymi”, tj. ignoruje wszystkie spacje, tabulatory i znaki nowej linii. Aby przeczytać całą treść taką, jaka jest, bez dzielenia jej na części (jak w powyższym przykładzie), musimy użyć metoda getline():

#włączać #włączać #włączać #włączać // aby użyć exit() int main() ( używając przestrzeni nazw std; // ifstream służy do odczytu zawartości plików // Spróbujemy odczytać zawartość pliku SomeText.txt ifstream inf("SomeText.txt") ; // Jeśli nie możemy otworzyć pliku, aby odczytać jego zawartość if (!inf) ( // Następnie wypisz następujący komunikat o błędzie i exit() cerr<< "Uh oh, SomeText.txt could not be opened for reading!" << endl; exit(1); } // Пока есть, что читать while (inf) { // То перемещаем то, что можем прочитать, в строку, а затем выводим эту строку на экран string strInput; getline(inf, strInput); cout << strInput << endl; } return 0; // Когда inf выйдет из области видимости, то деструктор класса ifstream автоматически закроет наш файл }

#włączać

#włączać

#włączać

#włączać // aby użyć exit()

int main()

używając przestrzeni nazw std ;

// ifstream służy do odczytywania zawartości plików

ifstream inf("JakiśTekst.txt" ) ;

// Jeśli nie możemy otworzyć pliku, aby odczytać jego zawartość

jeśli(!inf)

// Następnie wypisz następujący komunikat o błędzie i wykonaj exit()

zły<< "Uh oh, SomeText.txt nie może być otwarty do czytania!"<< endl ;

wyjście(1) ;

podczas(inf)

ciąg strInput ;

getline (inf , strInput ) ;

Cout<< strInput << endl ;

zwróć 0 ;

// Gdy inf wyjdzie poza zakres, destruktor klasy ifstream automatycznie zamknie nasz plik

Efektem uruchomienia powyższego programu jest:

buforowane wyjście

Dane wyjściowe w C++ mogą być buforowane. Oznacza to, że wszystko, co jest wyprowadzane do strumienia plików, nie może być natychmiast zapisane na dysku (w określonym pliku). Odbywa się to przede wszystkim ze względu na wydajność. Kiedy dane bufora są zapisywane na dysku, nazywa się to czyszczenie bufora. Jednym ze sposobów na wyczyszczenie bufora jest zamknięcie pliku. W takim przypadku cała zawartość bufora zostanie przeniesiona na dysk, a następnie plik zostanie zamknięty.

Buforowanie wyjścia zwykle nie stanowi problemu, ale w pewnych okolicznościach może powodować problemy dla nieostrożnych nowicjuszy. Na przykład, gdy dane są przechowywane w buforze, a program przedwcześnie kończy wykonywanie (w wyniku awarii lub przez wywołanie ). W takich przypadkach destruktory klasy I/O plików nie są wykonywane, pliki nigdy nie są zamykane, bufory nie są opróżniane, a nasze dane są tracone na zawsze. Dlatego dobrym pomysłem jest jawne zamknięcie wszystkich otwartych plików przed wywołaniem exit().

Możesz także wyczyścić bufor ręcznie, używając Metoda ostream::flush() lub wysyłając std::płukany do strumienia wyjściowego. Każda z tych metod może być przydatna do zapewnienia, że ​​zawartość bufora zostanie natychmiast zapisana na dysku w przypadku awarii programu.

Ciekawy niuans: Ponieważ std::endl; również czyści strumień wyjściowy, a następnie nadużywanie go (powodujące niepotrzebne opróżnianie bufora) może wpłynąć na wydajność programu (ponieważ w niektórych przypadkach opróżnianie bufora może być kosztowne). Z tego powodu programiści dbający o wydajność często używają \n zamiast std::endl, aby wstawić znak nowej linii do strumienia wyjściowego, aby uniknąć niepotrzebnego opróżniania bufora.

Tryby otwierania plików

Co się stanie, jeśli spróbujemy zapisać dane do już istniejącego pliku? Ponowne uruchomienie powyższego programu (pierwszego) pokazuje, że oryginalny plik jest całkowicie nadpisywany po ponownym uruchomieniu programu. Ale co, jeśli musimy dodać dane na końcu pliku? Okazuje się, że strumień pliku przyjmuje opcjonalny drugi parametr, który pozwala poinformować programistę, jak otworzyć plik. Jako ten parametr możesz przekazać następujące flagi(które są w klasie ios):

aplikacja- otwiera plik w trybie dołączania;

jedli- przechodzi na koniec pliku przed odczytem/zapisem;

dwójkowy- otwiera plik w trybie binarnym (zamiast w trybie tekstowym);

w- otwiera plik w trybie odczytu (domyślnie dla ifstream);

na zewnątrz- otwiera plik w trybie zapisu (domyślnie dla ofstream);

obcinać- usuwa plik, jeśli już istnieje.

Możesz określić wiele flag na raz, używając .

ifstream domyślnie działa w trybie ios::in;

ofstream domyślnie działa w trybie ios::out;

fstream domyślnie działa w trybie ios::in LUB ios::out, co oznacza, że ​​możesz albo odczytać zawartość pliku, albo zapisać dane do pliku.

Napiszmy teraz program, który doda dwie linie do utworzonego wcześniej pliku SomeText.txt:

#włączać #włączać // aby użyć exit() #include int main() ( używając namespace std; // Przekazanie flagi ios:app, aby poinformować fstream, że dodamy nasze dane do już istniejących danych w pliku, // nie zamierzamy nadpisywać pliku. nie trzeba przekazywać flagi ios::out , // ponieważ ofstream domyślnie ma wartość ios::out ofstream outf("SomeText.txt", ios::app); // Jeśli nie możemy otworzyć pliku do zapisu danych, jeśli (!outf) ( // Następnie wypisz następujący komunikat o błędzie i exit() cerr<< "Uh oh, SomeText.txt could not be opened for writing!" << endl; exit(1); } outf << "See line #3!" << endl; outf << "See line #4!" << endl; return 0; // Когда outf выйдет из области видимости, то деструктор класса ofstream автоматически закроет наш файл }

#włączać

#włączać // aby użyć exit()

#włączać

int main()

używając przestrzeni nazw std ;

// Przekazanie flagi ios:app, aby poinformować fstream, że zamierzamy dodać nasze dane do już istniejących danych pliku,

// nie nadpiszemy pliku. Nie musimy przekazywać flagi ios::out,

// ponieważ ofstream domyślnie ustawiony jest na tryb ios::out

ofstream outf("JakiśTekst.txt" , ios::app ) ;

// Jeśli nie możemy otworzyć pliku do zapisu danych

jeśli(!outf)

// Następnie wypisz następujący komunikat o błędzie i wykonaj exit()

zły<< "Och, nie można otworzyć pliku SomeText.txt do zapisu!"<< endl ;

wyjście(1) ;

DZWON

Są tacy, którzy czytają tę wiadomość przed tobą.
Zapisz się, aby otrzymywać najnowsze artykuły.
E-mail
Nazwa
Nazwisko
Jak chciałbyś przeczytać The Bell?
Bez spamu