Dosya G/Ç'nin C++'daki çalışması, normal G/Ç'ninkiyle hemen hemen aynıdır (ancak birkaç nüansla).

Dosya G/Ç Sınıfları

Var C++'da üç ana dosya G/Ç sınıfı:

akış dışı(sınıfın çocuğudur);

fstream(iostream sınıfının bir çocuğudur).

Bu sınıflar ile tek yönlü dosya girişi, tek yönlü dosya çıkışı ve çift yönlü dosya G/Ç işlemlerini gerçekleştirebilirsiniz. Bunları kullanmak için fstream'e bağlanmanız yeterlidir.

Hemen kullanılabilen cout, cin, cerr ve clog akışlarının aksine, dosya akışları programcı tarafından açıkça ayarlanmalıdır. Yani, bir dosyayı okumak ve/veya yazmak üzere açmak için, dosya adını parametre olarak belirterek uygun dosya I/O sınıfından bir nesne oluşturmanız gerekir. Ardından, ekleme operatörlerini kullanarak (<<) или извлечения (>>), bir dosyaya veri yazabilir veya bir dosyanın içeriğini okuyabilirsiniz. Bundan sonra, son - dosyayı kapatmanız gerekir: açıkça arayın kapat() yöntemi veya sadece dosya G/Ç değişkeninin kapsam dışına çıkmasına izin verin (dosya G/Ç sınıfı o dosyayı bizim için otomatik olarak kapatacaktır).

Dosya çıktısı

ofstream sınıfı bir dosyaya yazmak için kullanılır. Örneğin:

#Dahil etmek #Dahil etmek #Dahil etmek // çıkış() kullanmak int main() ( std ad alanını kullanarak; // akış bir dosyaya veri yazmak için kullanılır // Bir dosya oluştur SomeText.txt akış çıkışı("SomeText.txt"); // Yapabilirsek if (!outf)'a veri yazmak için bu dosyayı aç ( // Sonra bir hata mesajı yazdır ve exit() cerr komutunu çalıştır<< "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 автоматически закроет наш файл }

#Dahil etmek

#Dahil etmek

#Dahil etmek // çıkış() kullanmak için

int ana()

ad alanı std kullanarak;

// ofstream dosyaya veri yazmak için kullanılır

// SomeText.txt dosyası oluştur

ofstream outf("SomeText.txt" ) ;

// Veri yazmak için bu dosyayı açamazsak

if(!outf)

// Ardından bir hata mesajı yazdırın ve exit()'i yürütün

sertifika<< << endl ;

çıkış(1) ;

// Dosyaya aşağıdaki iki satırı yazın

çıkış<< "See line #1!" << endl ;

çıkış<< "See line #2!" << endl ;

0 döndür;

// outf kapsam dışına çıktığında, ofstream sınıfının yıkıcısı dosyamızı otomatik olarak kapatacaktır.

Proje dizininize bakarsanız ( Visual Studio'da .cpp dosyanızın adını içeren sekmedeki RMB > "Dosyayı içeren klasörü açınız"), aşağıdaki satırları içeren SomeText.txt adlı bir dosya göreceksiniz:

1. satıra bakın!
2. satıra bakın!

Ayrıca kullanabileceğimizi lütfen unutmayın put() yöntemi bir dosyaya bir karakter yazmak için.

Dosya girişi

#Dahil etmek #Dahil etmek #Dahil etmek #Dahil etmek // çıkış() kullanmak int main() ( std ad alanını kullanarak; // dosyanın içeriğini okumak için ifstream kullanılır // SomeText.txt dosyasının içeriğini okumaya çalışın ifstream inf("SomeText.txt") ; // İçeriğini okumak için bu dosyayı açamazsak 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; }

#Dahil etmek

#Dahil etmek

#Dahil etmek

#Dahil etmek // çıkış() kullanmak için

int ana()

ad alanı std kullanarak;

// ifstream dosyanın içeriğini okumak için kullanılır

// İçeriğini okumak için bu dosyayı açamazsak

eğer(!inf)

// Ardından aşağıdaki hata mesajını yazdırın ve exit()'i yürütün

sertifika<< << endl ;

çıkış(1) ;

// Okuyabileceğimiz veri olduğu sürece

süre(inf)

// Daha sonra bu verileri bir dizgeye taşırız ve daha sonra ekranda gösteririz.

string strInput ;

inf >> strInput ;

cout<< strInput << endl ;

0 döndür;

// inf kapsam dışına çıktığında ifstream sınıfının yıkıcısı dosyamızı otomatik olarak kapatacaktır.

Görmek
astar
#1!
Görmek
astar
#2!

Hmm, tam olarak istediğimiz bu değildi. Önceki derslerden zaten bildiğimiz gibi, çıkarma operatörü "biçimlendirilmiş veriler" ile çalışır, yani. tüm boşlukları, sekmeleri ve yeni satırları yok sayar. Tüm içeriği olduğu gibi, parçalara ayırmadan okumak için (yukarıdaki örnekte olduğu gibi) kullanmamız gerekir. getline() yöntemi:

#Dahil etmek #Dahil etmek #Dahil etmek #Dahil etmek // çıkış() kullanmak int main() ( std ad alanını kullanarak; // dosyaların içeriğini okumak için ifstream kullanılır // SomeText.txt dosyasının içeriğini okumaya çalışacağız ifstream inf("SomeText.txt") ; // Bir dosyayı içeriğini okumak için açamazsak if (!inf) ( // Ardından aşağıdaki hata mesajını yazdırın ve 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 автоматически закроет наш файл }

#Dahil etmek

#Dahil etmek

#Dahil etmek

#Dahil etmek // çıkış() kullanmak için

int ana()

ad alanı std kullanarak;

// ifstream dosyaların içeriğini okumak için kullanılır

ifstream inf("SomeText.txt" ) ;

// İçeriğini okumak için dosyayı açamazsak

eğer(!inf)

// Ardından aşağıdaki hata mesajını yazdırın ve exit()'i yürütün

sertifika<< "Ah, SomeText.txt okumak için açılamadı!"<< endl ;

çıkış(1) ;

süre(inf)

string strInput ;

getline (inf, strInput);

cout<< strInput << endl ;

0 döndür;

// inf kapsam dışına çıktığında ifstream sınıfının yıkıcısı dosyamızı otomatik olarak kapatacaktır.

Yukarıdaki programı çalıştırmanın sonucu:

arabelleğe alınmış çıktı

C++ çıktısı arabelleğe alınabilir. Bu, dosya akışına gönderilen her şeyin hemen diske (belirli bir dosyaya) yazılamadığı anlamına gelir. Bu öncelikle performans nedenleriyle yapılır. Arabellek verileri diske yazıldığında buna denir. arabelleği temizleme. Arabelleği temizlemenin bir yolu dosyayı kapatmaktır. Bu durumda, arabelleğin tüm içeriği diske taşınacak ve ardından dosya kapatılacaktır.

Çıktı arabelleğe alma genellikle bir sorun değildir, ancak belirli koşullar altında dikkatsiz yeni başlayanlar için sorunlara neden olabilir. Örneğin, veriler arabellekte depolandığında ve program yürütmesini zamanından önce sonlandırdığında (ya bir çökmenin sonucu olarak ya da . Bu gibi durumlarda, dosya G/Ç sınıfı yıkıcılar yürütülmez, dosyalar asla kapatılmaz, arabellekler boşaltılmaz ve verilerimiz sonsuza kadar kaybolur. Bu nedenle, çıkış()'ı çağırmadan önce tüm açık dosyaları açıkça kapatmak iyi bir fikirdir.

Ayrıca kullanarak arabelleği manuel olarak da temizleyebilirsiniz. ostream::flush() yöntemi veya göndererek standart::gömmeçıkış akışına. Bu yöntemlerden herhangi biri, bir program çökmesi durumunda arabellek içeriğinin hemen diske yazılmasını sağlamak için yararlı olabilir.

ilginç bir nüans: Çünkü std::endl; ayrıca çıktı akışını temizler, ardından aşırı kullanılması (gereksiz arabellek temizlemelerine neden olur) program performansını etkileyebilir (çünkü arabellek temizleme bazı durumlarda pahalı olabilir). Bu nedenle, performans bilincine sahip programcılar, gereksiz arabellek temizlemesini önlemek için çıktı akışına yeni satır karakteri eklemek için genellikle std::endl yerine \n kullanır.

Dosya açma modları

Zaten var olan bir dosyaya veri yazmaya çalışırsak ne olur? Yukarıdaki programı yeniden çalıştırmak (ilk olanı), programı yeniden çalıştırdığınızda orijinal dosyanın tamamen üzerine yazıldığını gösterir. Peki ya dosyanın sonuna veri eklememiz gerekirse? Dosya akışının, programcıya dosyayı nasıl açacağını söylemenize izin veren isteğe bağlı ikinci bir parametre aldığı ortaya çıktı. Bu parametre olarak, geçebilirsiniz aşağıdaki bayraklar(kiler ios sınıfındadır):

uygulama- dosyayı ekleme modunda açar;

yemek yedi- okuma/yazma işleminden önce dosyanın sonuna gider;

ikili- dosyayı ikili modda açar (metin modu yerine);

içinde- dosyayı okuma modunda açar (ifstream için varsayılan);

dışarı- dosyayı yazma modunda açar (akış için varsayılan);

gövde- zaten varsa dosyayı siler.

kullanarak aynı anda birden çok bayrak belirtebilirsiniz.

ifstream varsayılan olarak ios::in modunda çalışır;

ofstream varsayılan olarak ios::out modunda çalışır;

fstream varsayılan olarak ios::in VEYA ios::out modunda çalışır; bu, bir dosyanın içeriğini okuyabileceğiniz veya bir dosyaya veri yazabileceğiniz anlamına gelir.

Şimdi daha önce oluşturulan SomeText.txt dosyasına iki satır ekleyecek bir program yazalım:

#Dahil etmek #Dahil etmek // çıkış() #include kullanmak için int main() ( namespace std kullanarak; // fstream'e verilerimizi dosyanın zaten var olan verilerine ekleyeceğimizi söylemek için ios:app bayrağını iletiyoruz, // dosyanın üzerine yazmayacağız. ios::out bayrağını geçirmemiz gerekiyor // çünkü ofstream varsayılanı ios::out ofstream'dir outf("SomeText.txt", ios::app); // Veri yazmak için bir dosyayı açamıyorsak, (!outf) ( // Ardından hata mesajının ardından çıktı alın ve çıkış() 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 автоматически закроет наш файл }

#Dahil etmek

#Dahil etmek // çıkış() kullanmak için

#Dahil etmek

int ana()

ad alanı std kullanarak;

// fstream'e verilerimizi dosyanın zaten var olan verilerine ekleyeceğimizi söylemek için ios:app bayrağını iletmek,

// dosyanın üzerine yazmayacağız. ios::out bayrağını geçmemize gerek yok,

// çünkü akış varsayılanı ios::out modudur

ofstream outf("SomeText.txt" , ios::app ) ;

// Veri yazmak için dosyayı açamazsak

if(!outf)

// Ardından aşağıdaki hata mesajını yazdırın ve exit()'i yürütün

sertifika<< "Ah, SomeText.txt yazmak için açılamadı!"<< endl ;

çıkış(1) ;

tarafından geliştirilen G/Ç mekanizması, günümüzde genel kabul görmüş nesne yönelimli programlama stiline tekabül etmemekte, ayrıca modern güvenli kod yürütme ortamlarında potansiyel olarak güvenli olmadığı düşünülen işaretçi işlemlerini aktif olarak kullanmaktadır. Uygulama geliştirme için bir alternatif, C++ dil standardı tarafından sağlanan standart G/Ç sınıfı mekanizmasıdır.

Dosyaları açma

En sık kullanılan sınıflar, okuma için ifstream, yazma için ofstream ve dosyaları değiştirmek için fstream'dir.

Tüm iş parçacıklı G/Ç sınıfları, işlevselliğini tamamen devralan ios ortak atasından dolaylı olarak türetilir. Örneğin, open_mode numaralandırılmış veri üyesi, aşağıdaki gibi tanımlanan dosya açma modunu belirtir:

Enum open_mode (uygulama, ikili, içeri, dışarı, trunc, yedi);

Bayrakların olası değerleri ve amaçları aşağıdadır.

Örneğin, ikili verileri okumak üzere test.txt adlı bir dosyayı açmak için şunu yazarsınız:

ifstream dosyası; file.open("test.txt", ios::in | ios::binary);

Mantıksal VEYA operatörü (|), herhangi bir bayrak kombinasyonuyla bir mod oluşturmanıza olanak tanır. Yazarak bir dosyayı açarken, yanlışlıkla aynı isimli mevcut bir dosyanın üzerine yazmamak için aşağıdaki formu kullanmanız gerekir:

akış dışı dosya; file.open("test.txt", ios::out | ios::app);

Uygun başlık dosyasının projeye bağlı olduğu varsayılır:

#Dahil etmek

Dosyanın başarıyla açılıp açılmadığını kontrol etmek için yapıyı kullanabilirsiniz.

If (!file) ( // Bir dosya açma hatasının işlenmesi )

Dahil Etme ve Çıkarma Operatörleri

Dosya işleme sınıflarında geçersiz kılındı operatörü dahil et (<<) записывает данные в файловый поток. Как только вы открыли файл для записи, можно записывать в него текстовую строку целиком:

dosya<< "Это строка текста";

Parçalar halinde bir metin dizesi de yazabilirsiniz:

dosya<< "Это " << "строка " << "текста";

endl ifadesi satır girişini bir satır başı ile bitirir:

dosya<< "Это строка текста" << endl;

Dahil etme operatörünü kullanarak, değişkenlerin veya dizi öğelerinin değerlerini bir dosyaya yazmak kolaydır:

Akış dosyası ("Temp.txt"); char buff = "Metin dizisi değişkenler içeriyor"; int vx = 100; kayan nokta pi = 3.14159; dosya<< buff << endl << vx << endl << pi << endl;

Kod yürütmenin bir sonucu olarak, Temp.txt metin dosyasının üç satırı oluşturulur:

Metin dizisi değişkenler içeriyor 100 3.14159

Sayısal değerlerin dosyaya ikili değerler olarak değil metin dizeleri olarak yazıldığını unutmayın.

çıkarma operatörü(>>) tersini yapar. Daha önce yazılmış Temp.txt dosyasından karakterleri çıkarmak için aşağıdaki gibi bir kod yazmanız gerekiyor gibi görünüyor:

ifstream dosyası ("Temp.txt"); karakter tutkunu; intvx; floatpi; dosya >> buff >> vx >> pi;

Ancak çıkarma operatörü karşılaştığı ilk sınırlayıcıda (boşluk, sekme veya yeni satır) duracaktır. Böylece, "Metin dizisi değişkenler içerir" cümlesini ayrıştırırken, dizi buff'ına sadece "Metin" kelimesi yazılacak, boşluk yok sayılacak ve "dizi" kelimesi, vx tamsayı değişkeninin ve kodun değeri olacaktır. yürütme, veri yapısının kaçınılmaz bir ihlali ile "çarpık" olacaktır. Daha sonra, ifstream sınıfını tartışırken, önceki örnekten dosya okumasının nasıl doğru bir şekilde düzenleneceğini göstereceğiz.

ifstream sınıfı: dosyaları okuma

Adından da anlaşılacağı gibi, ifstream sınıfı bir dosya akışını girmek için tasarlanmıştır. Sınıfın ana yöntemleri aşağıda listelenmiştir. Çoğu, istream sınıfından miras alınır ve üst işlevlerle aşırı yüklenir. Örneğin, call parametresine bağlı olarak get işlevi yalnızca tek bir karakteri değil, aynı zamanda bir karakter bloğunu da okuyabilir.

Şimdi, veri çıkarma operatörünü kullanmanın beklenen sonucu vermesi için önceki örneği nasıl değiştirmeniz gerektiği açıktır:

ifstream dosyası ("Temp.txt"); karakter tutkunu; intvx; floatpi; file.getline(buff, sizeof(buff)); dosya >> vx >> pi:

getline yöntemi dosyanın ilk satırını sonuna kadar okuyacak ve >> operatörü değişkenlere değer atayacaktır.

Aşağıdaki örnek, bir metin dosyasına veri eklemeyi ve ardından tüm dosyayı okumayı gösterir. içinde açıklanan nedenlerle while(!file2.eof()) yerine while (1) döngüsü kullanılır.

#Dahil etmek #Dahil etmek ad alanı std kullanarak; int main() ( akış dosyası; file.open("test.txt",ios::out|ios::app); if (!file) ( cout<< "File error - can"t open to write data!"; cin.sync(); cin.get(); return 1; } for (int i=0; i<10; i++) file << i << endl; file.close(); ifstream file2; file2.open("test.txt", ios::in); if (!file2) { cout << "File error - can"t open to read data!"; cin.sync(); cin.get(); return 2; } int a,k=0; while (1) { file2 >>a; if (file2.eof()) kırılması; cout<< a << " "; k++; } cout << endl << "K=" << k << endl; file2.close(); cin.sync(); cin.get(); return 0; }

Aşağıdaki örnek, test.txt dosyasındaki satırları okuyarak ve bunları konsolda görüntüleyerek döner.

#Dahil etmek #Dahil etmek ad alanı std kullanarak; int main() ( ifstream dosyası; // bir akış nesnesi dosyası oluştur file.open("test.txt"); // dosyayı okumak için aç (!file) return 1; // char str'yi açarken hataya dön; / / statik satır arabelleği // eof while (!file.getline(str, sizeof(str)).eof()) cout'a kadar bir döngüdeki satırları okuyun ve görüntüleyin<< str << endl; // вывод прочитанной строки на экран cin.sync(); cin.get(); return 0; }

Windows işletim sistemi altındaki bu kod, dosyanın son satırında yeni satır karakterinin varlığına da bağlıdır, bunu yapmak daha güvenilir olacaktır:

while (1) ( if (file.eof()) break; file.getline(str, sizeof(str)); cout<< str << endl; }

Açık ve kapalı yöntemlere yapılan açık çağrılar isteğe bağlıdır. Aslında, yapıcıyı bir argümanla çağırmak, dosya akışı nesnesi oluşturulduğu anda dosyayı hemen açmanıza izin verir:

ifstream dosyası ("test.txt");

Kapat yöntemi yerine, dosya nesnesinin yıkıcısını otomatik olarak çağıracak ve dosyayı kapatacak olan silme operatörünü kullanabilirsiniz. while döngü kodu, uygun dosya sonu denetimi sağlar.

ofstream sınıfı: dosya yazma

ofstream sınıfı, bir dosya akışından veri çıktısı almak için tasarlanmıştır. Bu sınıfın ana yöntemleri aşağıda listelenmiştir.

Daha önce açıklanan içerme operatörü, bir metin dosyasına yazmayı düzenlemek için uygundur:

Akış dosyası ("temp.txt"); eğer (!file) dönerse; for (int i=1; ben<=3; i++) file << "Строка " << i << endl; file.close();

ikili dosyalar

Prensipte, ikili veriler metin verileri gibi sunulur. Aradaki fark, eğer ikili veriler belirli bir mantıksal yapıda yazılırsa, dosyadan aynı yapı tipindeki bir değişkene okunmaları gerektiğidir.

Yazma ve okuma yöntemlerinin ilk parametresi (yazma/okuma bloğunun adresi) karakter işaretçisi char * türünde olmalıdır, bu nedenle void * yapısının adres türünü açıkça dönüştürmek gerekir. İkinci parametre, dosyanın ikili bloklarının gerçek kayıt uzunluğundan bağımsız olarak sabit bir bayt boyutuna sahip olduğunu belirtir. Aşağıdaki ek, basit bir not defterinde verilerin nasıl oluşturulacağına ve görüntüleneceğine ilişkin bir örnek verir. Dosyanın kayıtları daha sonra sırayla okunur ve konsolda görüntülenir.

#Dahil etmek #Dahil etmek #Dahil etmek ad alanı std kullanarak; struct Notlar ( // not defterinin veri yapısı char Name; // tam ad char Phone; // phone int Yaş; // yaş ); int main() ( setlocale(LC_ALL, "Rus"); Notes Note1= ("Grozny Ioann Vasilyevich", "kurulu değil", 60 ); Notes Note2= ("Godunov Boris Fedorovich", "095-111-2233 ", 30 ); Notlar Note3= ("Peter Romanov ", "812-333-2211 ", 20 ); ofstream ofile("Notebook.dat", ios::binary); ofile.write((char*)&Note1, sizeof ( Notes)); // 1. blok ofile.write((char*)&Note2, sizeof(Notes)); // 2. blok ofile.write((char*)&Note3, sizeof(Notes)); / / 3. blok ofile. close(); // yazılan dosyayı kapat ifstream ifile("Notebook.dat", ios::binary); Notes Note; // yapısal değişken char str; // statik dize arabelleği // Şuna kadar satırları bir döngüde oku ve görüntüle eof while (!ifile.read((char*)&Note, sizeof(Notes))).eof()) ( sprintf(str, "%s\tBody: %s\tAge: %d" , Note.Name, Note. Telefon, Note.Age); cout<< str << endl; } ifile.close(); // закрыть прочитанный файл cin.sync(); cin.get(); return 0; }

Bu kodun yürütülmesinin bir sonucu olarak, her biri 80 baytlık üç bloktan (karakterlerin tek bayt olduğu varsayılarak) bir ikili dosya Notebook.dat oluşturulur. Doğal olarak, diğer akış yöntemlerini kullanabilir ve belirli bir veri yapısının alanları üzerinde herhangi bir işlemi gerçekleştirebilirsiniz.

fstream sınıfı: rastgele dosya erişimi

Not defterimizin 100 giriş biriktirdiğini ve 50'sini saymak istediğimizi varsayalım. Tabii ki, bir döngü düzenleyebilir ve ilkinden verilene kadar tüm kayıtları okuyabilirsiniz. Açıkçası, daha hedefli bir çözüm, pos dosyası konum işaretçisini doğrudan 50 girişine ayarlamak ve okumaktır:

ifstream ifile("Notebook.dat", ios::binary); int konum = 49 * sizeof(Notlar); ifile aramak(konum); // 50. girişi arayın Notlar Not; //Notlar - yukarıda açıklanan "kayıt" yapısı ifile.read((char*)&Note, sizeof(Notes));

Bu tür arama işlemleri, dosya bilinen ve sabit boyuttaki kayıtlardan oluşuyorsa etkilidir. Rastgele bir girdinin içeriğini değiştirmek için çıktı akışını değiştirme modunda açmanız gerekir:

Ofstream ofile("Notebook.dat", ios::binary | ios::ate); int konum = 49 * sizeof(Notlar); ofile searchp(konum); // 50. notayı ara Notes Note50 = ("Yeltsin Boris Nikolaevich", "095-222-3322", 64); ofile.write((char*)&Not, sizeof(Notlar)); // yenisiyle değiştirme

ios::ate (veya ios::app) bayrağını belirtmezseniz, Notebook.dat ikili dosyasını açtığınızda, önceki içeriği silinecektir!

Son olarak, fstream akış sınıfının öncüllerinden miras aldığı yöntemleri kullanarak, bir dosyayı okuma/yazma için aynı anda açmak mümkündür. fstream sınıfı istream ve ostream'den (sırasıyla ifstream ve ofstream'in üst öğeleri) türetildiği için, daha önce bahsedilen yöntemlerin tümü uygulama için kullanılabilir hale gelir.

Aşağıdaki örnek, Notebook.dat dosyasındaki birinci ve üçüncü girdileri değiştirir.

#Dahil etmek #Dahil etmek #Dahil etmek ad alanı std kullanarak; struct Notlar ( char Adı; char Telefon; int Yaş; ); int main() ( setlocale(LC_ALL, "Rus"); Notes Note1, Note3; // Dosyayı aynı anda okumak/yazmak için aç fstream file("Notebook.dat", ios::binary | ios::in | ios:: out); file.seekg(2 * sizeof(Notes)); // Note3'ü bulup okuyun file.read((char*)&Note3, sizeof(Notes)); file.seekg(0); // Note1'i bulup okuyun file.read((char*)&Note1, sizeof(Notes)); file.seekg(0); // Not1<== Note3 file.write((char*)&Note3, sizeof(Notes)); file.seekg(2 * sizeof(Notes)); // Note3 <== Note1 file.write((char*)&Note1, sizeof(Notes)); char str; // Считывать и отображать записи в цикле, пока не eof file.seekg(0); // вернуться к началу файла while (!file.read((char*)&Note1, sizeof(Notes)).eof()) { sprintf(str, "%s\tТел: %s\tВозраст: %d", Note1.Name, Note1.Phone, Note1.Age); cout << str << endl; } file.close(); cin.sync(); cin.get(); return 0; }

ios::in ve ios::out bayrakları, eşzamanlı okuma ve yazma işlemlerine izin vermek için dosya nesnesinin yapıcısında belirtilmelidir. Bu kodun yürütülmesi sonucunda Notebook.dat ikili dosyasının birinci ve üçüncü kayıtları değiştirilir.

Konuyla ilgili ek örnekler var.

Çoğu bilgisayar programı dosyalarla çalışır ve bu nedenle dosyaları oluşturmaya, silmeye, yazmaya, okumaya, açmaya ihtiyaç vardır. Dosya nedir? Dosya, bazı depolama aygıtlarında depolanabilen adlandırılmış bir bayt koleksiyonudur. Şimdi, bir dosyanın, .txt dosyası gibi kendine özgü bir adı olan bir bayt dizisi olduğu açıktır. Aynı ada sahip dosyalar aynı dizinde olamaz. Dosya adı yalnızca adı olarak değil, aynı zamanda bir uzantı olarak da anlaşılır, örneğin: file.txt ve file.dat Aynı ada sahip olmalarına rağmen farklı dosyalar. Dosyaların tam adı diye bir şey vardır - bu, dosya adıyla birlikte dosya dizininin tam adresidir, örneğin: D:\docs\file.txt . Bu temel kavramları anlamak önemlidir, aksi takdirde dosyalarla çalışmak zor olacaktır.

Dosyalarla çalışmak için bir başlık dosyası eklemeniz gerekir . AT tanımlanmış birkaç sınıf ve başlık dosyaları dahil dosya girişi ve dosya çıktısı.

Dosya G/Ç, standart G/Ç'ye benzer, tek fark, G/Ç'nin ekrana değil bir dosyaya yapılmasıdır. Standart cihazlara giriş/çıkış cin ve cout nesneleri kullanılarak yapılıyorsa, dosya G/Ç'sini düzenlemek için cin ve cout operatörlerine benzer şekilde kullanılabilecek kendi nesnelerinizi oluşturmanız yeterlidir.

Örneğin, bir metin dosyası oluşturmanız ve içine C++'da Dosyalarla Çalışma satırını yazmanız gerekir. Bunu yapmak için aşağıdaki adımları yapmanız gerekir:

  1. akış sınıfının bir nesnesini yarat ;
  2. bir sınıf nesnesini yazılacak dosyayla ilişkilendirin;
  3. bir dosyaya bir satır yazın;
  4. dosyayı kapatın.

Neden ifstream sınıfı değil de ofstream sınıfından bir nesne yaratmak gerekiyor? Bir dosyaya yazmanız gerektiğinden ve bir dosyadan veri okumanız gerekirse, ifstream sınıfının bir nesnesi oluşturulur.

// akış dosyasına yazılacak bir nesne yarat /*nesne adı*/; // akış sınıfının nesnesi

Nesneyi çağıralım - fout , İşte olan şey:

Akış dışı maç;

Neden bir nesneye ihtiyacımız var? Nesnenin dosyaya yazabilmesi için gereklidir. Nesne zaten oluşturuldu, ancak dizenin yazılacağı dosyayla ilişkili değil.

fout.open("cppstudio.txt"); // nesneyi dosyayla ilişkilendir

Nokta işlemi ile parantez içinde dosya adını belirttiğimiz open() sınıf yöntemine erişiriz. Belirtilen dosya, programla birlikte geçerli dizinde oluşturulacaktır. Aynı ada sahip bir dosya varsa, mevcut dosya yenisiyle değiştirilecektir. Böylece dosya açılır, içine istenen satırı yazmak kalır. Şu şekilde yapılır:

Fout<< "Работа с файлами в С++"; // запись строки в файл

fout nesnesiyle bağlantılı olarak yayına aktarma işlemini kullanarak, C++'da Dosya İşleme dizesi bir dosyaya yazılır. Dosyanın içeriğini değiştirmek artık gerekli olmadığı için kapatılmalıdır, yani nesne dosyadan ayrılmalıdır.

fout.close(); // dosyayı kapat

Sonuç olarak, Working with files in C++ satırına sahip bir dosya oluşturuldu.

Adım 1 ve 2 birleştirilebilir, yani bir satırda bir nesne oluşturun ve onu bir dosyayla ilişkilendirin. Şu şekilde yapılır:

Akış dışı fout("cppstudio.txt"); // ofstream sınıfından bir nesne oluşturun ve onu cppstudio.txt dosyasıyla ilişkilendirin

Tüm kodları birleştirelim ve aşağıdaki programı elde edelim.

// file.cpp: konsol uygulaması için giriş noktasını tanımlar. #include "stdafx.h" #include ad alanı std kullanarak; int main(int argc, char* argv) ( ofstream fout("cppstudio.txt"); // yazmak için ofstream sınıfından bir nesne oluşturun ve onu cppstudio.txt fout dosyasıyla ilişkilendirin<< "Работа с файлами в С++"; // запись строки в файл fout.close(); // закрываем файл system("pause"); return 0; }

Programın doğru çalışmasını kontrol etmeye devam ediyor ve bunun için dosyayı açıyoruz. cppstudio.txt ve içeriğine bakın, olması gereken - C++'da dosyalarla çalışma.

  1. ifstream sınıfının bir nesnesini oluşturun ve onu okunacak dosyayla ilişkilendirin;
  2. dosyayı oku;
  3. dosyayı kapatın.
// file_read.cpp: konsol uygulaması için giriş noktasını tanımlar. #include "stdafx.h" #include #Dahil etmek ad alanı std kullanarak; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // Kiril alfabesi karakter buff'ının doğru gösterimi; // ifstream fin("cppstudio.txt) dosyasından okunan metnin ara depolama tamponu "); // fin'i okumak için dosyayı açtı >><< buff << endl; // напечатали это слово fin.getline(buff, 50); // считали строку из файла fin.close(); // закрываем файл cout << buff << endl; // напечатали эту строку system("pause"); return 0; }

Program bir dosyadan okumanın iki yolunu gösterir, ilki akışa aktarım işlemini kullanmak, ikincisi işlevi kullanmaktır. hat almak() . İlk durumda, yalnızca ilk kelime okunur ve ikinci durumda, 50 karakterlik bir dize okunur. Ancak dosyada 50'den az karakter kaldığından, karakterler sonuncusu da dahil olmak üzere okunur. İkinci kez okumanın (17. satır) ilk kelime okunduğundan beri, baştan değil, ilk kelimeden sonra devam etti.14. satır. Programın sonucu Şekil 1'de gösterilmektedir.

C++'da Dosyalarla Çalışma Devam etmek için herhangi bir tuşa basın. . .

Şekil 1 - C++'da dosyalarla çalışma

Program doğru çalıştı, ancak her şey kodla uyumlu olsa bile bu her zaman böyle değildir. Örneğin var olmayan bir dosyanın adı programa geçirilmiş veya adında bir hata yapılmıştır. Sonra ne? Bu durumda, hiçbir şey olmayacak. Dosya bulunmayacak, bu da onu okumanın mümkün olmadığı anlamına geliyor. Bu nedenle derleyici, dosyanın değiştirildiği satırları yok sayar. Sonuç olarak, program doğru bir şekilde çıkacaktır, ancak ekranda hiçbir şey gösterilmeyecektir. Bunun böyle bir duruma tamamen normal bir tepki olduğu anlaşılıyor. Ancak basit bir kullanıcı, sorunun ne olduğunu ve neden dosyadan bir satırın ekranda görünmediğini anlamayacaktır. Bu nedenle, her şeyi açıklığa kavuşturmak için, C++ böyle bir işlev sağlar - is_open() , tamsayı değerleri döndürür: 1 - dosya başarıyla açıldıysa, 0 - dosya açılmadıysa. Dosyanın açılmasıyla programı sonlandıralım, öyle ki dosya açılmazsa ilgili mesaj ekrana gelsin.

// file_read.cpp: konsol uygulaması için giriş noktasını tanımlar. #include "stdafx.h" #include #Dahil etmek ad alanı std kullanarak; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // Kiril karakter güçlendirmesinin doğru gösterimi; // ifstream fin("cppstudio.doc") dosyasından okunan metnin ara bellek arabelleği; / / ( HATALI DOSYA ADI GİRİLDİ) if (!fin.is_open()) // dosya açık değilse cout<< "Файл не может быть открыт!\n"; // сообщить об этом else { fin >> tutku; // cout dosyasındaki ilk kelimeyi oku<< buff << endl; // напечатали это слово fin.getline(buff, 50); // считали строку из файла fin.close(); // закрываем файл cout << buff << endl; // напечатали эту строку } system("pause"); return 0; }

Programın sonucu Şekil 2'de gösterilmektedir.

Dosya açılamıyor! Devam etmek için herhangi bir tuşa basın. . .

Şekil 2 - C++'da dosyalarla çalışma

Şekil 2'den de görebileceğiniz gibi program dosyanın açılamadığını bildirdi. Bu nedenle, program dosyalarla çalışıyorsa, dosyanın var olduğundan emin olsanız bile is_open() adlı bu işlevi kullanmanız önerilir.

Dosya açma modları

Dosya açma modları, dosyaların nasıl kullanıldığını belirler. Modu ayarlamak için ios_base sınıfı, dosya açma modunu belirleyen sabitler sağlar (bkz. Tablo 1).

Dosya açma modları, bir nesne oluşturulurken veya open() işlevi çağrılırken doğrudan ayarlanabilir. .

Akış dışı fout("cppstudio.txt", ios_base::app); // dosyanın sonuna bilgi eklemek için dosyayı açın fout.open("cppstudio.txt", ios_base::app); // dosyanın sonuna bilgi eklemek için dosyayı aç

Dosya açma modları, bit düzeyinde boole işlemi kullanılarak birleştirilebilir veya| , örneğin: ios_base::out | ios_base::trunc - temizledikten sonra bir dosyayı yazmak için açın.

ofstream sınıfının nesneleri, dosyalarla ilişkilendirildiğinde varsayılan olarak dosya açma modlarını içerir ios_base::out | ios_base::trunc . Yani, dosya yoksa oluşturulacaktır. Dosya varsa, içeriği silinecek ve dosyanın kendisi kayıt için hazır olacaktır. ifstream sınıfının nesneleri, bir dosyayla ilişkilendirildiğinde, varsayılan olarak dosya açma moduna sahiptir ios_base::in - dosya salt okunurdur. Dosya açma modu ayrıca bayrak olarak da adlandırılır, okunabilirlik için gelecekte bu terimi kullanacağız. Tablo 1 tüm bayrakları listelemiyor, ancak bunlar başlamanız için yeterli olmalıdır.

Lütfen not edin, ate ve app bayrakları açıklamada çok benzerdir, ikisi de işaretçiyi dosyanın sonuna taşır, ancak uygulama bayrağı yalnızca dosyanın sonuna yazmaya izin verir ve ate bayrağı bayrağı basitçe yeniden düzenler. dosyanın sonu ve kayıt alanını sınırlamaz.

Sizeof() işlemini kullanarak, C++'daki ana veri türlerinin özelliklerini hesaplayacak ve bir dosyaya yazacak bir program geliştirelim. Özellikler:

  1. veri türü için ayrılan bayt sayısı
  2. belirli bir veri türünün saklayabileceği maksimum değer.

Bir dosyaya yazma aşağıdaki biçimde olmalıdır:

/* veri türü bayt maksimum değer bool = 1 255,00 karakter = 1 255.00 kısa int = 2 32767.00 unsigned kısa int = 2 65535.00 int = 4 2147483647.00 unsigned int = 4 4294967295.00 long int = 4 2147483647.00 unsigned uzun int = 4 4294967485.00 float = 4 2 uzun kayan nokta = 8 9223372036854775800.00 çift = 8 9223372036854775800.00 */

Böyle bir program bölümün başlarında zaten geliştirilmiştir, ancak veri türleri hakkındaki tüm bilgiler standart çıktı aygıtına çıktı ve bilgilerin bir dosyaya yazılması için programı yeniden oluşturmamız gerekiyor. Bunu yapmak için, mevcut dosya bilgilerinin ön kesilmesi ile dosyayı yazma modunda açmanız gerekir ( 14. satır). Dosya oluşturulduktan ve başarıyla açıldıktan sonra (satır 16 - 20), cout ifadesi yerine 22. satır fout nesnesini kullanın. böylece bir ekran yerine veri türleri ile ilgili bilgiler bir dosyaya yazılacaktır.

// write_file.cpp: konsol uygulaması için giriş noktasını tanımlar. #include "stdafx.h" #include #Dahil etmek // dosyalarla çalış #include // std ad alanını kullanan G/Ç manipülatörleri; int main(int argc, char* argv) ( setlocale(LC_ALL, "rus"); // nesneyi dosyaya bağla, dosyayı yazma modunda açarken ilk önce tüm verileri silerek fout("data_types.txt) ", ios_base::out | ios_base::trunc); if (!fout.is_open()) // dosya açılmadıysa ( cout<< "Файл не может быть открыт или создан\n"; // напечатать соответствующее сообщение return 1; // выполнить выход из программы } fout << " data type " << "byte" << " " << " max value "<< endl // sütun başlıkları <<"bool = " << sizeof(bool) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных bool*/ << (pow(2,sizeof(bool) * 8.0) - 1) << endl << "char = " << sizeof(char) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных char*/ << (pow(2,sizeof(char) * 8.0) - 1) << endl << "short int = " << sizeof(short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных short int*/ << (pow(2,sizeof(short int) * 8.0 - 1) - 1) << endl << "unsigned short int = " << sizeof(unsigned short int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned short int*/ << (pow(2,sizeof(unsigned short int) * 8.0) - 1) << endl << "int = " << sizeof(int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных int*/ << (pow(2,sizeof(int) * 8.0 - 1) - 1) << endl << "unsigned int = " << sizeof(unsigned int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных unsigned int*/ << (pow(2,sizeof(unsigned int) * 8.0) - 1) << endl << "long int = " << sizeof(long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long int*/ << (pow(2,sizeof(long int) * 8.0 - 1) - 1) << endl << "unsigned long int = " << sizeof(unsigned long int) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных undigned long int*/ << (pow(2,sizeof(unsigned long int) * 8.0) - 1) << endl << "float = " << sizeof(float) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных float*/ << (pow(2,sizeof(float) * 8.0 - 1) - 1) << endl << "long float = " << sizeof(long float) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных long float*/ << (pow(2,sizeof(long float) * 8.0 - 1) - 1) << endl << "double = " << sizeof(double) << " " << fixed << setprecision(2) /*вычисляем максимальное значение для типа данных double*/ << (pow(2,sizeof(double) * 8.0 - 1) - 1) << endl; fout.close(); // программа больше не использует файл, поэтому его нужно закрыть cout << "Данные успешно записаны в файл data_types.txt\n"; system("pause"); return 0; }

Standart giriş/çıkış ve dosya giriş/çıkışlarının birebir aynı şekilde kullanılması sayesinde programdaki değişikliklerin minimum düzeyde olduğunu fark etmemek mümkün değil. Programın sonunda,hat 45Dosyayı açıkça kapattık, bu gerekli olmasa da iyi bir programlama uygulaması olarak kabul ediliyor. Standart girdi/çıktıları biçimlendirmek için kullanılan tüm işlevlerin ve manipülatörlerin dosya girdi/çıktıları için de geçerli olduğunu belirtmekte fayda var. Bu nedenle, operatör çalışırken herhangi bir hata oluşmadı. cout bir nesne ile değiştirildi fout.

Son güncelleme: 31.10.2015

System.IO ad alanındaki dizinlerle çalışmak üzere iki sınıf tasarlanmıştır: Directory ve DirectoryInfo .

dizin sınıfı

Directory sınıfı, dizinleri yönetmek için bir dizi statik yöntem sağlar. Bu yöntemlerden bazıları şunlardır:

    CreateDirectory(path) : belirtilen yolda bir dizin oluşturur

    Sil(yol) : verilen yoldaki dizini siler

    Exists(path) : Belirtilen yoldaki dizinin mevcut olup olmadığını belirler. Varsa true, yoksa false döndürür.

    GetDirectories(path) : Yoldaki dizinlerin bir listesini alır

    GetFiles(path) : Dizin yolundaki dosyaların bir listesini alır

    Taşı(sourceDirName, destDirName): dizini taşır

    GetParent(path) : ana dizini al

DirectoryInfo sınıfı

Bu sınıf, oluşturma, silme, taşıma ve diğer dizin işlemleri için işlevsellik sağlar. Birçok yönden, Dizin'e benzer. Bazı özellikleri ve yöntemleri şunlardır:

    Create() : bir dizin oluşturur

    CreateSubdirectory(path) : belirtilen yolda bir alt dizin oluşturur

    Delete() : bir dizini siler

    Exists özelliği: dizinin var olup olmadığını belirler

    GetDirectories() : Dizinlerin bir listesini alır

    GetFiles() : dosyaların bir listesini alın

    MoveTo(destDirName) : bir dizini taşır

    Ana özellik: ana dizini alma

    Kök özelliği: kök dizini alma

Bu sınıfların kullanımına ilişkin örneklere bakalım

Dosyaların ve alt dizinlerin bir listesini alma

string dirName = "C:\\"; if (Directory.Exists(dirName)) ( Console.WriteLine("Altdizinler:"); string dirs = Directory.GetDirectories(dirName); foreach (dizilerdeki dizgeler) ( Console.WriteLine(s); ) Console.WriteLine( ); Console.WriteLine("Files:"); string dosyaları = Directory.GetFiles(dirName); foreach (dosyalardaki stringler) ( Console.WriteLine(s); ) )

Dosya adlarında eğik çizgi kullanımına dikkat edin. Ya çift eğik çizgi kullanırız: "C:\\" ya da tek bir çizgi, ancak sonra @ işaretini tüm yolun önüne koyarız: @"C:\Program Files"

Bir dizin oluşturun

string yolu = @"C:\SomeDir"; string subpath = @"program\avalon"; DirectoryInfo dirInfo = yeni DirectoryInfo(yol); if (!dirInfo.Exists) ( dirInfo.Create(); ) dirInfo.CreateSubdirectory(alt yol);

İlk önce böyle bir dizin olup olmadığını kontrol ediyoruz çünkü varsa onu oluşturmak mümkün olmayacak ve uygulama hata verecektir. Sonuç olarak şu yolu elde edeceğiz: "C:\SomeDir\program\avalon"

Bir dizin hakkında bilgi alma

string dirName = "C:\\Program Dosyaları"; DirectoryInfo dirInfo = yeni DirectoryInfo(dirName); Console.WriteLine($"Dizin adı: (dirInfo.Name)"); Console.WriteLine($"Tam dizin adı: (dirInfo.FullName)"); Console.WriteLine($"Dizin oluşturma zamanı: (dirInfo.CreationTime)"); Console.WriteLine($"Kök dizin: (dirInfo.Root)");

Bir dizini silme

Silme yöntemini, herhangi bir dosya veya alt dizin içeren boş olmayan bir klasöre uygularsak, uygulama bir hata verir. Bu nedenle, klasörün tüm içeriğiyle birlikte silinmesi gerektiğini gösterecek olan Delete yöntemine ek bir boole tipi parametre iletmemiz gerekiyor:

String dirName = @"C:\SomeFolder"; try ( DirectoryInfo dirInfo = new DirectoryInfo(dirName); dirInfo.Delete(true); Console.WriteLine("Dizin silindi"); ) catch (ex İstisna) ( Console.WriteLine(ex.Message); )

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

Bir dizini taşıma

string oldPath = @"C:\SomeFolder"; string newPath = @"C:\SomeDir"; DirectoryInfo dirInfo = yeni DirectoryInfo(eskiYol); if (dirInfo.Exists && Directory.Exists(newPath) == false) ( dirInfo.MoveTo(newPath); )

Taşınırken, eski dizinin tüm içeriğini taşımak istediğimiz yeni dizinin olmaması gerektiğini dikkate almalıyız.

Kullanım kolaylığı için, depolama aygıtlarındaki bilgiler dosya biçiminde saklanır.

Dosya, bir dizi veriyi depolamak için ayrılmış, adlandırılmış bir harici bellek alanıdır. Dosyalarda bulunan veriler çok çeşitli niteliktedir: algoritmik veya makine dilinde programlar; programların çalışması veya program yürütme sonuçları için ilk veriler; keyfi metinler; grafikler vb.

Dizin (klasör, dizin) - dosyaların organizasyonunu basitleştirmek için dosya sisteminde kullanılan, alt dizinlerin ve dosyaların adlarını içeren bir depolama ortamında adlandırılmış bir bayt koleksiyonu.

dosya sistemi dosyalar üzerinde işlem sağlayan işletim sisteminin işlevsel bir parçasıdır. Dosya sistemlerine örnek olarak FAT (FAT - Dosya Ayırma Tablosu, dosya ayırma tablosu), NTFS, UDF (CD'lerde kullanılır) verilebilir.

FAT'nin üç ana sürümü vardır: FAT12, FAT16 ve FAT32. Disk yapısındaki kayıtların bitliği bakımından farklılık gösterirler, yani. küme numarasını depolamak için ayrılan bit sayısı. FAT12 esas olarak disketler (4 KB'ye kadar), küçük diskler için FAT16, yüksek kapasiteli FLASH sürücüler (32 GB'a kadar) için FAT32 kullanılır.

Örnek olarak FAT32 kullanan dosya sisteminin yapısını düşünün.

FAT32 dosya yapısı

FAT32 sistemindeki harici bellek aygıtları bayt değil, blok adreslemedir. Bilgiler, bloklar veya sektörler halinde harici bir bellek aygıtına yazılır.

Sektör - harici depolama aygıtlarında adreslenebilir minimum bilgi depolama birimi. Tipik olarak, sektör boyutu 512 bayt olarak sabitlenir. Harici bellek aygıtlarının adres alanını artırmak için sektörler, küme adı verilen gruplar halinde birleştirilir.

Bir küme, belirli özelliklere sahip bağımsız bir birim olarak kabul edilebilecek birkaç sektörün bir birleşimidir. Bir kümenin ana özelliği, sektör sayısı veya bayt sayısı ile ölçülen boyutudur.

FAT32 dosya sistemi aşağıdaki yapıya sahiptir.

Dosya yazmak için kullanılan kümeler 2'den başlayarak numaralandırılır. Kural olarak, küme #2 kök dizin tarafından kullanılır ve küme #3'ten başlayarak veri dizisi depolanır. Kök dizinin üzerinde bilgi depolamak için kullanılan sektörler kümelenmez.
Diskteki minimum dosya boyutu 1 kümedir.

Önyükleme sektörü aşağıdaki bilgilerle başlar:

  • EB 58 90 - koşulsuz şube ve imza;
  • 4D 53 44 4F 53 35 2E 30 MSDOS5.0;
  • 00 02 - sektördeki bayt sayısı (genellikle 512);
  • 1 bayt - kümedeki sektör sayısı;
  • 2 bayt - yedek sektör sayısı.

Ayrıca, önyükleme sektörü aşağıdaki önemli bilgileri içerir:

  • 0x10 (1 bayt) – FAT tablolarının sayısı (genellikle 2);
  • 0x20 (4 bayt) - diskteki sektör sayısı;
  • 0x2C (4 bayt) – kök dizin küme numarası;
  • 0x47 (11 bayt) – birim etiketi;
  • 0x1FE (2 bayt) - Önyükleme sektörü imzası (55 AA).

Dosya sistemi bilgi sektörü şunları içerir:

  • 0x00 (4 bayt) – imza (52 52 61 41 );
  • 0x1E4 (4 bayt) – imza (72 72 41 61);
  • 0x1E8 (4 bayt) – serbest küme sayısı, bilinmiyorsa -1;
  • 0x1EC (4 bayt) – son kaydedilen kümenin numarası;
  • 0x1FE (2 bayt) - imza (55 AA).

FAT tablosu, diskteki her kümenin durumu hakkında bilgi içerir. FAT tablosunun alt 2 baytı, F8 FF FF 0F FF FF FF FF (0 ve 1 kümelerinin durumuna karşılık gelir, fiziksel olarak yoktur) depolar. Ayrıca, her kümenin durumu, mevcut dosyanın devam ettiği kümenin numarasını veya aşağıdaki bilgileri içerir:

  • 00 00 00 00 – küme ücretsizdir;
  • FF FF FF 0F, geçerli dosyanın sonudur.
  • 8 bayt - dosya adı;
  • 3 bayt - dosya uzantısı;

Kök dizin, aşağıdaki bilgileri içeren her dosya için bir dizi 32 bit bilgi kaydı içerir:

Uzun dosya adlarıyla (Rusça adlar dahil) çalışırken, dosya adı UTF-16 kodlama sisteminde kodlanır. Bu durumda, her karakterin kodlanması için 2 bayt tahsis edilir. Bu durumda dosya adı aşağıdaki yapı şeklinde yazılır:

  • 1 bayt dizisi;
  • 10 bayt, dosya adının alt 5 karakterini içerir;
  • 1 bayt özniteliği;
  • 1 bayt ayrılmış;
  • 1 bayt - DOS adı sağlama toplamı;
  • 12 bayt, dosya adının en alttaki 3 karakterini içerir;
  • 2 bayt – ilk kümenin numarası;
  • uzun adın kalan karakterleri.

C'de Dosyalarla Çalışmak

Programcı için açık bir dosya, okunan veya yazılan bir veri dizisi olarak temsil edilir. Bir dosya açıldığında, bununla ilişkilendirilir. G/Ç akışı. Çıkış bilgileri akışa yazılır, giriş bilgileri akıştan okunur.

G/Ç için bir akış açıldığında, stdio.h içinde tanımlanan FILE türünün standart yapısıyla ilişkilendirilir. FILE yapısı, dosya hakkında gerekli bilgileri içerir.

Bir dosyanın açılması, dosya üzerinde sonraki işlemler için kullanılabilecek FILE türünde bir yapıya bir işaretçi döndüren fopen() işlevi kullanılarak yapılır.

DOSYA *fopen(isim, tür);


name, açılacak dosyanın adıdır (yol dahil),
type, dosyaya nasıl erişildiğini tanımlayan bir karakter dizisine yönelik bir işaretçidir:
  • "r" - dosyayı okumak için aç (dosya mevcut olmalıdır);
  • "w" - yazmak için boş bir dosya açın; dosya varsa, içeriği kaybolur;
  • "a" - sonuna kadar yazmak için dosyayı aç (eklemek için); dosya yoksa oluşturulur;
  • "r+" - dosyayı okumak ve yazmak için açın (dosya mevcut olmalıdır);
  • "w+" - okuma ve yazma için boş bir dosya açın; dosya varsa, içeriği kaybolur;
  • "a+" - dosyayı okumak ve eklemek için açın, dosya yoksa oluşturulur.

Dönüş değeri, açık akışa yönelik bir işaretçidir. Bir hata bulunursa, NULL döndürülür.

fclose() işlevi, fopen() ile açılan dosyalarla ilişkili akışı veya akışları kapatır. Kapatılacak akış, fclose() işlevinin argümanı tarafından belirlenir.

Dönüş değeri: akış başarıyla kapatılmışsa 0 değeri; bir hata oluştuğunda EOF sabiti.

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

#Dahil etmek
int ana() (
DOSYA *fp;
karakter adı = "benim.txt" ;
if ((fp = fopen(isim, "r" )) == NULL )
{
yazdırf( "Dosya açılamadı");
getchar();
0 döndür;
}
// dosyayı açma başarılı
... // veriler üzerinde gerekli işlemler
fclose(fp);
getchar();
0 döndür;
}

Dosyadan karakter okuma:

char fgetc(akım);


İşlev bağımsız değişkeni, FILE türünde bir akışın işaretçisidir. İşlev, okunan karakterin kodunu döndürür. Dosyanın sonuna ulaşılırsa veya bir hata oluşursa, EOF sabiti döndürülür.

Dosyaya karakter yazma:

fputc(karakter, akış);

İşlevin argümanları, bir karakter ve FILE türündeki bir akışın işaretçisidir. İşlev, okunan karakterin kodunu döndürür.

fscanf() ve fprintf() işlevleri, scanf() ve printf() işlevlerine benzer, ancak veri dosyaları üzerinde çalışır ve ilk argüman olarak bir dosya işaretçisine sahiptir.

fscanf(akış, "InputFormat", argümanlar);