En basit uygulamaların yanı sıra, çoğu programın dosyaları okuması veya yazması gerekir. Yalnızca bir yapılandırma dosyasını veya bir metin ayrıştırıcısını veya daha karmaşık bir şeyi okumak için olabilir. Bu eğitici C'de rasgele erişim dosyaları kullanmaya odaklanmaktadır.
C'de Rasgele Erişim Dosyası G / Ç Programlama
Temel dosya işlemleri:
- fopen - bir dosyayı aç - nasıl açılacağını (okuma / yazma) ve türünü (ikili / metin) belirtin
- fclose - açık bir dosyayı kapat
- fread - bir dosyadan okuma
- fwrite - bir dosyaya yaz
- fseek / fsetpos - dosya işaretçisini dosyadaki herhangi bir yere taşır
- ftell / fgetpos - dosya işaretçisinin nerede olduğunu söyler
İki temel dosya türü metindir ve ikili. Bu iki dosyadan ikili dosyaların ele alınması genellikle daha kolaydır. Bu nedenle ve bir metin dosyasına rastgele erişimin sık sık yapmanız gereken bir şey olmaması nedeniyle, bu eğitici ikili dosyalarla sınırlıdır. Yukarıda listelenen ilk dört işlem hem metin hem de rasgele erişim dosyaları içindir. Son ikisi sadece rastgele erişim için.
Rastgele erişim, dosyanın tamamını okumak zorunda kalmadan dosyanın herhangi bir bölümüne gidip veri okuyabileceğiniz veya yazabileceğiniz anlamına gelir. Yıllar önce, veriler büyük bilgisayar kaset makaralarında depolandı. Kasetteki bir noktaya ulaşmanın tek yolu kasetin tamamını okumaktı. Sonra diskler geldi ve şimdi bir dosyanın herhangi bir bölümünü doğrudan okuyabilirsiniz.
İkili Dosyalarla Programlama
İkili dosya, 0 ile 255 aralığındaki değerleri içeren baytları tutan herhangi bir uzunlukta bir dosyadır. Bu baytların, 13 değerinin satır başı, 10 satır besleme ve 26 dosya sonu anlamına geldiği bir metin dosyasından farklı bir anlamı yoktur. Metin dosyalarını okuyan yazılımların bu diğer anlamları ele alması gerekir.
İkili dosyalar bir bayt akışı oluşturur ve modern diller dosyalar yerine akışlarla çalışma eğilimindedir. Önemli olan, nereden geldiğinden ziyade veri akışıdır. İçinde C, veriler hakkında dosya veya akış olarak düşünebilirsiniz. Rasgele erişimle, dosyanın veya akışın herhangi bir bölümünü okuyabilir veya yazabilirsiniz. Sıralı erişimle, dosyada veya akışta büyük bir bant gibi döngü yapmalısınız.
Bu kod örneği, bir metin dizesi (char *) içine yazılmak üzere yazmak için açılan basit bir ikili dosyayı gösterir. Normalde bunu bir metin dosyasıyla görürsünüz, ancak bir ikili dosyaya metin yazabilirsiniz.
Bu örnek, yazmak için bir ikili dosya açar ve içine bir char * (dize) yazar. FILE * değişkeni fopen () çağrısından döndürülür. Bu başarısız olursa (dosya var olabilir ve açık veya salt okunur olabilir veya dosya adında bir hata olabilir), 0 değerini döndürür.
Fopen () komutu belirtilen dosyayı açmaya çalışır. Bu durumda, test.txt uygulamasıyla aynı klasördedir. Dosya bir yol içeriyorsa, tüm ters eğik çizgiler iki katına çıkarılmalıdır. "c: \ folder \ test.txt" yanlış; "c: \\ klasör \\ test.txt" kullanmalısınız.
Dosya modu "wb" olduğundan, bu kod bir ikili dosyaya yazılır. Dosya mevcut değilse oluşturulur ve varsa, içindeki her şey silinir. Fopen çağrısı başarısız olabilir, belki dosya açık olduğundan veya ad geçersiz karakterler veya geçersiz bir yol içerdiğinden, fopen 0 değerini döndürür.
Ft'nin sıfırdan farklı (başarılı) olup olmadığını kontrol edebilmenize rağmen, bu örnek bunu açıkça yapmak için bir FileSuccess () işlevine sahiptir. Windows'da, çağrının ve dosya adının başarılı / başarısız olduğunu verir. Performans peşindeyseniz biraz zahmetlidir, bu nedenle bunu hata ayıklama ile sınırlandırabilirsiniz. Windows'ta, sistem hata ayıklayıcısına metin çıktısı çok azdır.
Fwrite () çağrıları belirtilen metni verir. İkinci ve üçüncü parametreler karakterlerin boyutu ve dizenin uzunluğudur. Her ikisi de işaretsiz tam sayı olan size_t olarak tanımlanır. Bu aramanın sonucu, belirtilen boyuttaki sayım öğelerini yazmaktır. İkili dosyalarda, bir dize (char *) yazarken bile, satır başı veya satır besleme karakteri eklemediğini unutmayın. Bunları istiyorsanız, bunları açıkça dizeye eklemeniz gerekir.
Dosya Okuma ve Yazma için Dosya Modları
Bir dosyayı açtığınızda, nasıl açılacağını belirlersiniz - yeni dosyadan mı oluşturulacağına, üzerine mi yazılacağına, metin mi yoksa ikili mi, okuyup yazmayacağına ve eklemek isteyip istemediğinizi belirtirsiniz. Bu, diğer harflerle birlikte tekli "r", "b", "w", "a" ve "+" harfleri olan bir veya daha fazla dosya modu belirteci kullanılarak yapılır.
- r - Dosyayı okumak için açar. Dosya yoksa veya bulunamazsa bu başarısız olur.
- w - Dosyayı yazmak için boş bir dosya olarak açar. Dosya varsa, içeriği yok edilir.
- a - Dosyaya yeni veriler yazmadan önce, dosyanın sonunda (ek olarak) EOF işaretleyicisini çıkarmadan dosyayı açmak için açar; bu, ilk önce dosyayı yoksa oluşturur.
Dosya moduna "+" eklemek üç yeni mod oluşturur:
- r + - Dosyayı hem okuma hem de yazma için açar. (Dosya mevcut olmalıdır.)
- w + - Dosyayı hem okuma hem de yazma için boş bir dosya olarak açar. Dosya varsa, içeriği yok edilir.
- a + - Dosyayı okumak ve eklemek için açar; ekleme işlemi, dosyaya yeni veriler yazılmadan önce EOF işaretinin kaldırılmasını ve yazma tamamlandıktan sonra EOF işaretinin geri yüklenmesini içerir. Varsa, önce dosyayı oluşturur. Dosyayı okumak ve eklemek için açar; ekleme işlemi, dosyaya yeni veriler yazılmadan önce EOF işaretinin kaldırılmasını ve yazma tamamlandıktan sonra EOF işaretinin geri yüklenmesini içerir. Varsa, önce dosyayı oluşturur.
Dosya Modu Kombinasyonları
Bu tabloda hem metin hem de ikili dosyalar için dosya modu kombinasyonları gösterilmektedir. Genellikle, bir metin dosyasından okur veya bir metin dosyasına yazarsınız, ancak ikisini aynı anda yazmazsınız. İkili bir dosyayla, aynı dosyayı hem okuyabilir hem de yazabilirsiniz. Aşağıdaki tablo her bir kombinasyonla neler yapabileceğinizi göstermektedir.
- r metni - okunur
- rb + ikili - okuma
- r + metin - okuma, yazma
- r + b ikili - okuma, yazma
- rb + ikili - okuma, yazma
- w metin - yazma, oluşturma, kısaltma
- wb binary - yazma, oluşturma, kısaltma
- w + metin - okuma, yazma, oluşturma, kısaltma
- w + b binary - okuma, yazma, oluşturma, kısaltma
- wb + binary - okuma, yazma, oluşturma, kısaltma
- bir metin - yazma, oluşturma
- ab ikili - yazma, oluşturma
- a + metin - okuma, yazma, oluşturma
- a + b ikili - yazma, oluşturma
- ab + ikili - yazma, oluşturma
Sadece bir dosya oluşturmuyorsanız ("wb" kullanın) ya da sadece bir tane okuyorsanız ("rb" kullanın), "w + b" kullanarak uzaklaşabilirsiniz.
Bazı uygulamalar diğer harflere de izin verir. Microsoft,, örneğin, aşağıdakilere izin verir:
- t - metin modu
- c - taahhüt
- n - taahhütte bulunma
- S - sıralı erişim için önbelleği optimize etme
- R - sıralı olmayan önbelleğe alma (rasgele erişim)
- T - geçici
- D - sil / geçici, kapatıldığında dosyayı öldürür.
Bunlar taşınabilir değildir, bu yüzden bunları kendi tehlikenizde kullanın.
Rasgele Erişimli Dosya Depolama Örneği
İkili dosyaları kullanmanın temel nedeni, dosyanın herhangi bir yerinde okuma veya yazma olanağı sağlayan esnekliktir. Metin dosyaları yalnızca sırayla okumanıza veya yazmanıza izin verir. Gibi ucuz veya ücretsiz veritabanlarının yaygınlığı ile SQLite ve MySQL, ikili dosyalarda rasgele erişim kullanma ihtiyacını azaltır. Ancak, dosya kayıtlarına rastgele erişim biraz eski moda ama yine de faydalıdır.
Bir Örneği İnceleme
Örnekte, dizeleri rasgele erişim dosyasında saklayan bir dizin ve veri dosyası çifti gösterildiğini varsayalım. Dizeler farklı uzunluklardadır ve 0, 1 konumu vb. İle indekslenir.
İki geçersiz işlev vardır: CreateFiles () ve ShowRecord (int recnum). CreateFiles, msg biçim dizesinden ve n'nin 5'ten 1004'e kadar değiştiği n yıldız işaretinden oluşan geçici bir dizeyi tutmak için 1100 boyutunda bir char * arabelleği kullanır. Ftindex ve ftdata değişkenlerinde wb filemode kullanılarak iki DOSYA * oluşturulur. Oluşturulduktan sonra, bunlar dosyaları işlemek için kullanılır. İki dosya
- index.dat
- data.dat
Dizin dosyası 1000 tür dizin türü içerir; bu, iki üye pos (fpos_t türünde) ve boyuta sahip olan yapı dizin tipidir. Döngünün ilk kısmı:
msg dizesini böyle doldurur.
ve bunun gibi. Sonra bu:
yapıyı dizenin uzunluğu ve veri dosyasında dizenin yazılacağı nokta ile doldurur.
Bu noktada, hem indeks dosyası yapısı hem de veri dosyası dizesi ilgili dosyalarına yazılabilir. Bunlar ikili dosyalar olmasına rağmen, sırayla yazılır. Teoride, mevcut dosyanın sonunun ötesinde bir konuma kayıtlar yazabilirsiniz, ancak kullanmak için iyi bir teknik değildir ve muhtemelen hiç taşınabilir değildir.
Son bölüm her iki dosyayı da kapatmaktır. Bu, dosyanın son bölümünün diske yazılmasını sağlar. Dosya yazma işlemleri sırasında, yazma işlemlerinin çoğu doğrudan diske gitmez ancak sabit boyutlu arabelleklerde tutulur. Yazma arabelleği doldurduktan sonra, arabelleğin tüm içeriği diske yazılır.
Dosya temizleme işlevi yıkama işlemini zorlar ve ayrıca dosya temizleme stratejileri de belirleyebilirsiniz, ancak bunlar metin dosyaları için tasarlanmıştır.
Kayıt İşlevini Göster
Veri dosyasından belirtilen herhangi bir kaydın alınabileceğini test etmek için iki şeyi bilmeniz gerekir: veri dosyasında nerede başladığı ve ne kadar büyük olduğu.
Dizin dosyasının yaptığı budur. ShowRecord işlevi her iki dosyayı da açar, uygun noktayı arar (recnum * sizeof (dizin tipi) ve bir dizi bayt = sizeof (dizin) getirir.
SEEK_SET, fseek'in nereden yapıldığını belirten bir sabittir. Bunun için tanımlanmış iki sabit daha vardır.
- SEEK_CUR - geçerli konuma göre ara
- SEEK_END - dosyanın sonundan mutlak arama
- SEEK_SET - dosyanın başından itibaren mutlak arama
Dosya işaretçisini sizeof (index) ile ilerletmek için SEEK_CUR kullanabilirsiniz.
Verilerin boyutunu ve konumunu elde ettikten sonra, onu almak için kalır.
Burada, fpos_t olan index.pos türü nedeniyle fsetpos () kullanın. Alternatif bir yol fgetpos yerine ftell ve fgetpos yerine fsek kullanmaktır. Fseek ve ftell çifti int ile çalışırken fgetpos ve fsetpos fpos_t kullanır.
Kaydı belleğe okuduktan sonra, düzgün bir karaktere dönüştürmek için boş bir karakter eklenir c-string. Unutmayın yoksa bir çarpışma yaşarsınız. Daha önce olduğu gibi, her iki dosyada da fclose çağrılır. Her ne kadar veriyi unutursanız veri kaybetmezseniz de (yazımlardan farklı olarak), bellek sızıntısı yaşarsınız.