Tam Sürümünü Görmek İçin : Dosya Bölme/Birleştirme Programı
Merhaba,
C++'ta bir tane dosya bölme/birleştirme programı yazıyorum. Geldiğim aşamada kaynak dosyayı istediğim sayıda parçaya bölüyor, ardından da birleştiriyorum ancak birleştiğinde hedef dosya kaynak dosyadan 2 byte daha büyük oluyor. Örnek vermek gerekirse, kaynak dosyadaki veri aşağıdaki gibi olsun:
01234567890
01234567890
01234567890
Hedef dosyadaki veri;
01234567890
01234567890
0123456789000
şeklinde çıkıyor.
Yazdığım kodda dosyayı birleştiren MergeFile() fonksiyonundaki şüphelendiğim yeri ekliyorum:
for (int i = 0; i != parNum; ++i) {
ostringstream oss;
oss << "File" << i + 1 << "." << mFileExtension;
ifstream ifs(oss.str().c_str());
char ch;
int byteCounter = 0;
while (byteCounter != parSize && (!ifs.eof())) {
++byteCounter;
ifs.get(ch);
ofs.put(ch);
}
ifs.close();
}
Son parçayı alıp hedef dosyaya yazarken EOF durumunda döngüden çıkacak. Burada şunu sormak istiyorum: C'de örneğin feof() fonksiyonunun EOF durumunu geri döndürmesi için dosya sonuna gelinmiş olması yeterli değil. Bir tane başarısız okuma yapılması gerekiyor. Ardından feof() fonksiyonu sıfır dışı bir değer döndürerek EOF'un gerçekleştiğini iletiyor. C++'ta basic_ios içerisindeki eof() fonksiyonu da C'deki feof() gibi mi davranmaktadır ? Eğer öyleyse hedefe yazılan 2 byte problemini nasıl çözebilirim ?
İyi çalışmalar.
quasimodo
27/09/2007, 23:14
#include <stdio.h>
#include <stdlib.h>
void c_akimi_ile(const char * dosyaAdi)
{
FILE * dosya = fopen(dosyaAdi, "rb");
int karakterSayisi = 0;
bool okumayaCalisinca = 0;
printf("\n--- C akimi ile ---\n");
if (!dosya) {
fprintf(stderr, "HATA: %s acilamadi\n", dosyaAdi);
exit(1);
}
while (!feof(dosya)) {
int sayi;
if (fscanf(dosya, "%d", &sayi) == 1) {
printf("%2d: %d\n", karakterSayisi, sayi);
++karakterSayisi;
}
else if (feof(dosya)) {
okumayaCalisinca = 1;
break;
}
else {
fprintf(stderr, "HATA\n");
exit(1);
}
}
if (okumayaCalisinca) {
printf("OKUMAYA CALISINCA farkettik\n");
}
else {
printf("Okumadan once farkettik\n");
}
}
#include <fstream>
#include <iostream>
#include <iomanip>
using namespace std;
void cpp_akimi_ile(const char * dosyaAdi)
{
ifstream dosya(dosyaAdi, ios::in | ios::binary);
int karakterSayisi = 0;
bool okumayaCalisinca = false;
cout << "\n--- C++ akimi ile ---\n";
if (!dosya) {
cerr << "HATA: " << dosyaAdi << " acilamadi\n";
exit(1);
}
while (!dosya.eof()) {
int sayi;
if (dosya >> sayi) {
cout << setw(2) << karakterSayisi << ": " << sayi << '\n';
++karakterSayisi;
}
else if (dosya.eof()) {
okumayaCalisinca = true;
break;
}
else {
cerr << "HATA\n";
exit(1);
}
}
if (okumayaCalisinca) {
cout << "OKUMAYA CALISINCA farkettik\n";
}
else {
cout << "Okumadan once farkettik\n";
}
}
int main(int argc, char * argv[])
{
if (argc != 2) {
cout << "Kullanim: " << argv[0] << " <dosya_adi>\n";
return 0;
}
const char * dosyaAdi = argv[1];
c_akimi_ile(dosyaAdi);
cpp_akimi_ile(dosyaAdi);
}
Daha once Ali Cehreli tarafindan yazilmis bir kod. Buradan ayni oldugun
anlasiliyor
acehreli
27/09/2007, 23:55
quasimodo'nun gosterdigi (ve anlasilan benim yazmis oldugum) program %d ile okudugu icin icinde sayilar bulunan dosyalarla calisiyor. Denemek icin ornegin soyle bir deneme.txt ile kullanilabilir:
123 45 678 90
Sonra komut satirinda
> deneme deneme.txt
gibi...
Ali
Merhaba quasimodo,
Verdiğiniz kodu çalıştırdım. Aynı dosya için farklı çıktılar verdi. C kodu çıktıyı bazı karakterSayisi değerlerinin karşısına gelecek sayi degerlerini bos bırakarak verirken C++ kodu çıktısında akış düzgündü. Çıktıya göre C ve C++'ta eof fonksiyonları farklı mı davranıyor yoksa çıktıdaki fark formatlı okumadan mı kaynaklanıyor, nasıl yorumlayacağımı bilmiyorum.
Bu arada göndermiş olduğunuz kodda c_akimi_ile() fonksiyonundaki
if (fscanf(dosya, "%d", &sayi) == 1) {
printf("%2d: %d\n", karakterSayisi, sayi);
%d olan format karakterlerini %c yaptım. İlaveten cpp_akimi_ile() fonksiyonunda int türünde tanımlanan sayi değişkenini char türde tanımladım. Diğer türlü, program sistemimde düzgün çalışmıyor.
İyi çalışmalar.
Edit: @acehreli, mesajınızı kendi mesajımı gönderdikten sonra gördüm.
acehreli
28/09/2007, 01:00
fscanf bosluk karakterlerini de okuyor, ama operator<< onlari goz ardi ediyor. Acaba gordugun fark o mu?
eof konusundan ben artik emin degilim. :) O programi yazdigim zaman C akimlarinin okumaya calismadan once bildigini saniyordum ama bu program her iki yontemde de eof olusmasi icin bir okumanin yapilmasinin gerekli oldugunu gosteriyor.
Ali
quasimodo
28/09/2007, 01:11
Benim bildigimde su; file position pointer in aslinda dosyada olmayan
son karakteri gostermesi durumudur. Ama EOF nin set edilmesi icin
dosyadan okuma yapilmasi gerekir.(Galiba yazma yapilabiliyordu) EOF
durumunda position pointerin ofseti dosya uzunluguna esittir.
Bide EOF aslinda int olmasina ragmen aslinda sadece bir bit, flag gibi.
C++ dosya islemlerini daha henuz bilmiyorum... :(
fscanf bosluk karakterlerini de okuyor, ama operator<< onlari goz ardi ediyor. Acaba gordugun fark o mu?
Evet, gördüğüm fark buymuş. Şu an programım hedef dosyaya 2 karakter fazla yazıyor. Bunu koda yama yaparak, okunan parçanın son parça olduğunu tespit ettikten sonra parçanın uzunluğunu alıp o parça için döngüyü iki eksik döndürerek kapatabileceğimi düşünüyorum. Ancak böyle bir yama kodun okunabilirliği açısından pek güzel durmayacak. Daha estetik bir çözüm bulduğumda burada paylaşmak isterim.
İyi çalışmalar.
while (byteCounter != parSize && (!ifs.eof())) {
++byteCounter;
ifs.get(ch); // EOF burada oluşuyor
ofs.put(ch); // EOF kontrol edilmeden yazılıyor
}
EOF kontrolünü döngüden çıkar get den sonra kontrol et eğer EOF değilse
put de
Teşekkür ederim bluekid. Programım şimdi düzgün çalışıyor.
Forum Yazılımı : vBulletin v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.