Şimdi Ara

Dosyanın bellirli yerinden itibaren byte'ları kaydırma

Daha Fazla
Bu Konudaki Kullanıcılar: Daha Az
2 Misafir (1 Mobil) - 1 Masaüstü1 Mobil
5 sn
11
Cevap
0
Favori
305
Tıklama
Daha Fazla
İstatistik
  • Konu İstatistikleri Yükleniyor
0 oy
Öne Çıkar
Sayfa: 1
Giriş
Mesaj
  • merhaba arkadaşlar nedemek istediğim zaten konu başlığındanda anlaşılmıştır örneğin bir dosyamız var 100 mb büyüklüğünde ve biz bu dosyanın atıyorum 1000. baytından itibaren tüm baytları 100 adım kaydıracağız ben bunu yapan bir fonksiyon yazdım fakat sorun şuki fonksiyon karakter bazında işlem yapıyor dosyanın kaydırmak istenilen yerinden itibaren olan baytları belleğe alarak yapmak istedim fakat en fazla 1 - 1.5 mb büyüklüğünde dizi oluyor yani 100 hatta 400 500 mb diziye ihtiyaç duyuyorum geri kalan baytları belleğe alıp dosyanın belirli yerine tekrar yazmak için ama bukadar büyük bir dizi yapmaya çalıştığım zamanda seg fault yiyorum bu sorunu nasıl aşacağım oysaki pythonda 700 mb büyüklüğündeki bir dosyayı belleğe alabiliyoruz ama C de bunu nasıl yapabileceğimi bilmiyorum yardımcı olursanız çok sevinirim şimdiden teşekkürler



  • quote:

    Orijinalden alıntı: Harun2525

    merhaba arkadaşlar nedemek istediğim zaten konu başlığındanda anlaşılmıştır örneğin bir dosyamız var 100 mb büyüklüğünde ve biz bu dosyanın atıyorum 1000. baytından itibaren tüm baytları 100 adım kaydıracağız ben bunu yapan bir fonksiyon yazdım fakat sorun şuki fonksiyon karakter bazında işlem yapıyor dosyanın kaydırmak istenilen yerinden itibaren olan baytları belleğe alarak yapmak istedim fakat en fazla 1 - 1.5 mb büyüklüğünde dizi oluyor yani 100 hatta 400 500 mb diziye ihtiyaç duyuyorum geri kalan baytları belleğe alıp dosyanın belirli yerine tekrar yazmak için ama bukadar büyük bir dizi yapmaya çalıştığım zamanda seg fault yiyorum bu sorunu nasıl aşacağım oysaki pythonda 700 mb büyüklüğündeki bir dosyayı belleğe alabiliyoruz ama C de bunu nasıl yapabileceğimi bilmiyorum yardımcı olursanız çok sevinirim şimdiden teşekkürler

    C veya C++ da ayıramadığın tek parça büyüklükteki bellek bloğunu Python dili de ayıramıyordur. Çünkü C ve C++ dillerini assembly/makine dili seviyesinde diller diye saysan olur özellikle bu hafızaya erişim işlerinde.

    Ha ama şöyle birşey oluyordur Python'da; Python kesin daha yüksek seviyeli bir dil olduğu için sana "Ayırmış say abi buyur gel çalış kocaman diziyle" diye sana kolaylık sağlarken daha arka planda sana farkettirmemeye çalışarak bu hafıza denetimi ve yönetimi işlerini kotarmaya çalışıyordur. Zaten üst seviye dillerin en büyük avantajlarından biri sana bu şekilde daha steril bir çalışma ortamı sağlaması ve teknik detaylardan seni mahsus uzak tutmaya çalışmasıdır. Ben Python bilmem bu arada. Tek bildiğim dil C++'dır.

    Yani bunları niye yazdım ? Ha demek ki sen de bu Python'un yaptığı hafıza yönetimi işini yapacak fonksiyonlar yazacaksın ki ilerde her türlü boyutlarda dizilerle rahatça çalışabilesin diye.

    Dosyanın byte'larının kaydırılma hususunda bir yorumda bulunmayacağım ama hemen aklıma gelen fikir ise şu oldu: 5 ila 10 megabayt büyüklüğünde tek bir dizi oluştur. Dosyayı fasılalı olarak bu diziye okut ondan sonra okuttuğun şeyi nereye tekrar yazılacaksa oraya yazdır. Tabiyatıyle 500 megabayt büyüklüğündeki bir disk dosyası için bu işlem belki 50 kere tekrarlanması gerekecek. Tabii birde dosyadaki bilgileri öne kaydırmakla arkaya kaydırmak arasında fark var. Yazacağın algoritma her ikisini de desteklerse daha güzel olur. Öne kaydırma algoritması daha kolay olacaktır diye tahmin ediyorum bu arada.

    5 ila 10 Megabaytın özelliği ise şu: Günümüz işlemcilerinin çoğunun belleğe hızlı erişim için sahip oldukları "kaşe/cache"ler de bu büyüklüklerde oluyor. Dolayısıyla bu okuma yazma işlerinde belki performans açısından bir faydası olur diye bir fikir yürüttüm şimdi. Yani mesela senin makinenin işlemcisinin kaşesi atıyorum 12 megabayt ise senin programda tampon olarak yaratacağın dizi atıyorum bu kaşe değerinden biraz daha az olsun.. Ne olsun 8 megabayt olsun mesela. Bu fikri ben denemedim bu arada ama sen yüksek çözünürlükte "timer" lar kullanarak bu fikri deneyebilirsin bu arada. Ama tabii belki bunlar hiçbir işe yaramayabilir, belki teker teker karakter karakter kopyalama belki daha hızlı olacaktır. Dediğim gibi ben hiç denemedim bu tarz işleri önceden.

    Ne kadar büyüklükte tek parça belleği şu şekilde çok kaba bir fonksiyon/algoritma ile öğrenebilirsin mesela:

     

    unsigned int GetMaxAllocSize() /* Bu fonksiyon sürekli 1'er megabayt arttırarak ayırılabilinecek en büyük dizi boyutunun değerini döndürür, dönüş değeri "unsigned int" olduğu için 32bit makinede teorik olarak 4 gigabyte'e kadar değer döndürebilir*/
    {
    const int kilobyte = 1024;
    const int megabyte = kilobyte * kilobyte;

    unsigned int max =0;

    for (unsigned int sz = megabyte; ;sz = sz + megabyte)
    {
    void* p = malloc (sz);

    if (p == 0)
    {
    return max;
    }
    else
    {
    max = sz;
    free (p);
    }
    }

    return 0;
    }





    Benim makinede mesela bu fonksiyon 545 Megabyte (571473920 Byte) değerini döndürüyor. Hiç de fena sayılmaz doğrusu. Makine 64bit i7 930 işlemcili 64Bit Windows 8.1 sürümü. Makinede 12 GB hafıza modülü takılı bu arada. Senin makinende de bu tarz değerler görebiliyor olman lazım bu arada. Hiç olmadı günümüz makineleri hiç zorlanmadan sana tek parça 100mb bloğu rahatça temin edebilecektir diye tahmin ediyorum. 1 ~1.5 mb dizi boyutu gerçekten çok küçükmüş. Bi hata olsa gerek.




  • Buzz Lightyear B kullanıcısına yanıt
    hocam bayağı uğraşmışsınız yinede çok sağolun bu arada bir dizinin 1-1.5 mb olması normal hatta fazla bile çünki C standartlarında sanırım c99 standarıydı çok emin değilim bir değişken en fazla 32 kilobayt olabilir diyor ben sorunu şu şekilde çözdüm "char *dizi = malloc(1000000000)" şeklinde bu şekilde yapınca bellekten 1 gb bile yer ayırıyor. yani sorun çözüldü malloc syaesinde
  • quote:

    Orijinalden alıntı: Harun2525

    hocam bayağı uğraşmışsınız yinede çok sağolun bu arada bir dizinin 1-1.5 mb olması normal hatta fazla bile çünki C standartlarında sanırım c99 standarıydı çok emin değilim bir değişken en fazla 32 kilobayt olabilir diyor ben sorunu şu şekilde çözdüm "char *dizi = malloc(1000000000)" şeklinde bu şekilde yapınca bellekten 1 gb bile yer ayırıyor. yani sorun çözüldü malloc syaesinde

    Benim makinede char *dizi = malloc(1000000000) kodu "sıfır" değerini döndürüyor yani benim makinede bu kadar büyüklükte dizi ayrılınımıyor. Sen emin misin malloc fonksiyonunun geri dönüş değerinin sıfır olup olmadığını iyi kontrol ettiğine ?

    Bu arada 1000000000 değeri hakiki 1 GB değildir. Hakiki 1 GB değeri şudur: 1073741824. Yani 1024 x 1024 x 1024 değeridir.

    Yukarda sana yazdığım fonksiyonu senin makinede bir program içersinde çalıştır bakalım ne değer döndürecek. Dikkat edersen o fonksiyon içersinde bende senin için hususi malloc ve free fonksiyonlarını kullandım mahsus.




  • Buzz Lightyear B kullanıcısına yanıt
    eminim hocam kaç defa denedim zaten okadar büyük belleği işgal eden bir diziyi kimsenin döndüreceğini sanmıyorum fonksiyon en fazla 400 - 500 mb döndürse bile yeter zten bir program için 400-500 mb bile fazla bu arada ben linux üzerinden denedim siz windowstan denemiş olabilrisiniz

    bu arada bende malloc fonksiyonu bellekten yer ayıramadığı zaman seg fault yiyorum ayırdığı zaman normal sıfır mıfır döndürme işleri olmuyor bu doğruluğunu denemek için 700 mb büyüklüğündeki bir dosyayı belleğe aldım hata mata vermedi sizde nasıl oluyorda 0 döndürüyor hata vermiyor bende direk seg fault oluyor ordan



    < Bu mesaj bu kişi tarafından değiştirildi Harun2525 -- 4 Ağustos 2015; 2:02:14 >
  • quote:

    Orijinalden alıntı: Harun2525

    eminim hocam kaç defa denedim zaten okadar büyük belleği işgal eden bir diziyi kimsenin döndüreceğini sanmıyorum fonksiyon en fazla 400 - 500 mb döndürse bile yeter zten bir program için 400-500 mb bile fazla bu arada ben linux üzerinden denedim siz windowstan denemiş olabilrisiniz

    bu arada bende malloc fonksiyonu bellekten yer ayıramadığı zaman seg fault yiyorum ayırdığı zaman normal sıfır mıfır döndürme işleri olmuyor bu doğruluğunu denemek için 700 mb büyüklüğündeki bir dosyayı belleğe aldım hata mata vermedi sizde nasıl oluyorda 0 döndürüyor hata vermiyor bende direk seg fault oluyor ordan

    malloc eğer hafıza ayıramassa sıfır/NULL değerini döndürür. Eğer ayırabilirse de ayırdığı hafıza bloğunun başlangıç adresini "void*" cinsinden döndürür. Bütün işlevi bu.

    Segmentation Fault malloc yüzünden olmuyordur. Sen malloc değerinin döndürdüğü değeri yanlış kullandığın için oluyordur. Yoksa malloc öyle kolay kolay seg fault yaratacak kadar ciddi bir arıza vermemesi lazım çünkü bütün C ve C++ dilinin biricik ve en önemli fonksiyonları malloc ve free dir.


    Yazdığın kodu bir görmek isterim açıkcası.




  • Buzz Lightyear B kullanıcısına yanıt
    hmm tamam şöyle bir kaç deneme yaptımda aynen sizin dediğiniz gibi olmuş bendede seg fault vermiyor 0 döndürüyor seg fault vermesinin nedeni 0 döndürüğü halde değişken bir şeyler kaydetmemmiş yanı değişkende işlem yapmammış ama dediğim gibi malloc(1000000000) yazınca veyada malloc(1024 x 1024 x 1024) yazınca 0 döndürmüyor yer ayırıyor yer ayırmaasa 700 mb büyüklüğündeki dosyayı belleğe alamazdım aldığımı nerenden biliyorum diye sorarsanız o anki bellek kullanımına baktığımda 700 mb civarında büyük bir artış gördüm

    bu arada bu fonksiyonları kullanarak dosyanın belirli bir yerinden baytları ileri veya geri kaydıran fonksiyon yazdım nasıl bu fonksiyon hakkındada düşüncelerinizi merak ediyorum doğurusu

     
    void frbytMove(long int byte, long int move, FILE *dosya)
    {
    fseek(dosya, 0, 2);
    long int len = ftell(dosya) - byte;

    if(len > 104857600) {return;} // 104857600 byte = 100 mb (mega byte)

    signed char *mem = (signed char*) malloc(len);
    short int ch;
    long int i = 0;

    fseek(dosya, byte, 0);

    while((ch = fgetc(dosya)) != EOF)
    {
    mem[i] = ch;
    ++i;
    }

    fseek(dosya, byte + move, 0);

    for(i = 0; i < len; ++i)
    { fputc(mem[i], dosya); }

    free(mem);
    }




  • Yapay Zeka’dan İlgili Konular
    Daha Fazla Göster
  • quote:

    Orijinalden alıntı: Harun2525

    hmm tamam şöyle bir kaç deneme yaptımda aynen sizin dediğiniz gibi olmuş bendede seg fault vermiyor 0 döndürüyor seg fault vermesinin nedeni 0 döndürüğü halde değişken bir şeyler kaydetmemmiş yanı değişkende işlem yapmammış ama dediğim gibi malloc(1000000000) yazınca veyada malloc(1024 x 1024 x 1024) yazınca 0 döndürmüyor yer ayırıyor yer ayırmaasa 700 mb büyüklüğündeki dosyayı belleğe alamazdım aldığımı nerenden biliyorum diye sorarsanız o anki bellek kullanımına baktığımda 700 mb civarında büyük bir artış gördüm

    bu arada bu fonksiyonları kullanarak dosyanın belirli bir yerinden baytları ileri veya geri kaydıran fonksiyon yazdım nasıl bu fonksiyon hakkındada düşüncelerinizi merak ediyorum doğurusu

     
    void frbytMove(long int byte, long int move, FILE *dosya)
    {
    fseek(dosya, 0, 2);
    long int len = ftell(dosya) - byte;

    if(len > 104857600) {return;} // 104857600 byte = 100 mb (mega byte)

    signed char *mem = (signed char*) malloc(len);
    short int ch;
    long int i = 0;

    fseek(dosya, byte, 0);

    while((ch = fgetc(dosya)) != EOF)
    {
    mem[i] = ch;
    ++i;
    }

    fseek(dosya, byte + move, 0);

    for(i = 0; i < len; ++i)
    { fputc(mem[i], dosya); }

    free(mem);
    }


    Evet tamam yeni öğrenen birisi için makul bir kod. Gerçi malloc sıfır döndürmüş mü döndürmemiş mi onu falan kontrol etmemişsin ama hadi geçelim o kısmı şimdilik.

    Fakat bu kodun daha hızlı çalışması için "fgetc" ve "fputc"'den ziyade komple bloğu olabilecek neredeyse en hızlı şekilde okuyacak olan "fread" ve "fwrite" fonksiyonlarının kullanılması lazım.

    Çünkü dosyadan verileri döngü içerisinde byte şeklinde okuma ve yazma yapıyorsun. Bu yaptığın şey bu iş için gereksiz ve çok hantal bir yöntem.

    Halbuki fread ve fwrite fonksiyonları bu işi olabilecek en hızlı şekilde kotaracaktır. Şöyle ki: fread ve fwrite sırf x86 komut setini kullanıyor olsa bile verileri işlemciye tek seferde 1 byte şeklinde değil de işlemcinin registeri büyüklüğü olan "int" yani 32bitlik programlarda 4'er bytelık, bloklar şeklinde sokuyordur. Yani en kötü durumda bile büyük dosya kopyalama işlemleri esnasında fread/fwrite ikilisi senin fonksiyonundan teorik olarak 4 kat daha hızlı çalışacaktır.

    x86 komut setine ek olarak, günümüz makinelerinin büyük veri bloklarını çabucak kopyalayabilmek için sahip oldukları donanım özelliklerini de hesaba katarsak, fread/fwrite ikilisi özellikle büyük dosyaları senin bu yazdığın koda nazaran 4 katdan çok daha fazla bir miktarda belki 12 kat, belki 24 kat daha hızlı bile işlemleyebilir.

    Çünkü takdir edersin ki, modern işletim sistemlerinde arka planda yer alan büyük veri bloklarını bir yerden başka bir yere taşıma işlemleri mümkün mertebe en hızlı şekilde yapılmaya çalışılınır. fread ve fwrite fonksiyonları işte sana bu olanağı açan kapılardır aslında. Her ne kadar fread ve fwrite fonksiyonları evet belki de 1970'lerden günümüze kullanılan C'nin en klasik fonksiyonları olsa da işletim sistemleri ve donanım geliştikçe işletim sistemini tasarlayan yazılımcılar bu C'nin klasik dosya okuma ve yazma arayüzü olan fread ve fwrite'ı olabilecek en hızlı çalışacak şekilde donanım olanaklarını da hesaba katarak her sürümde yeniden revize ediyorlardırlar.


    Hadi sana bir ödev:

    -- Bu işi fread ve fwrite kullanarak yapan fonksiyonu yaz.
    -- Kullandığın tampon bellek ilk seferde 1 MB olsun, ikinci seferde 2MB olsun, ...en son komple bloğu tek seferde okumaya yetecek büyüklükte olacak şekilde fonksiyonu tekrar düzenle.
    -- Tüm bu performans değerlerini yüksek çözünürlüklü/hassasiyetli "Timer"/kronometre kullanarak performans ölçümlerinde bulun.

    ve en son olarak bakalım bu iş en kısa sürede ne kadar büyüklükte bir tampon bellek kullanılarak kotarılabilecek o değeri saptamaya çalış.




  • Buzz Lightyear B kullanıcısına yanıt
    hocam haklısınızda fread ve fwriete fonksiyonu ortalama 1- 2 gb üzeri dosyalarda iyi çalışır çünki fonksiyonun 2. 3. parametreleri int tipindev ve fonksiyonlar 2. ve 3. parametrelerinin çarpımı kadar yazma okuma yapıyor biz bu çarpımı nasl dosyanın boyutunda göre yapacağız mecbur parametrelerden birisine 1 değeri veriymek zorunda klayıorum ve sadece bir parametre kullanıncada 1-2 gb üzeri dosyalarda iyi çalışıyor kaldıki yazmak veya okumak istediğiniz byte uzunluğunun boyutu asal bir sayı ise mecbur 2. veya 3. parametrelerden birine 1 değerini atamak zorunda kalıyorum bu yüzden kullanmak istemedim
  • quote:

    Orijinalden alıntı: Harun2525

    hocam haklısınızda fread ve fwriete fonksiyonu ortalama 1- 2 gb üzeri dosyalarda iyi çalışır çünki fonksiyonun 2. 3. parametreleri int tipindev ve fonksiyonlar 2. ve 3. parametrelerinin çarpımı kadar yazma okuma yapıyor biz bu çarpımı nasl dosyanın boyutunda göre yapacağız mecbur parametrelerden birisine 1 değeri veriymek zorunda klayıorum ve sadece bir parametre kullanıncada 1-2 gb üzeri dosyalarda iyi çalışıyor kaldıki yazmak veya okumak istediğiniz byte uzunluğunun boyutu asal bir sayı ise mecbur 2. veya 3. parametrelerden birine 1 değerini atamak zorunda kalıyorum bu yüzden kullanmak istemedim

    Yok onlar her boyutta dosya için neredeyse en hızlı çalışan fonksiyonlardır emin ol.

    Kullanımı konusunda o 2 parametreye fazla takılma. Şimdilik o parametreyi "1" yaparak sen tekrar düzenle fonksiyonu ve bazı performans ölçümlerinde bulun. Öyle asal sayılarla falan bir ilgisi yok onun bu arada daha çok bölüm, bölen, kalan hesabıyla ilgili bir durum o senin dediğin.

    Ama dediğim gibi sen şimdilik o parametreyi 1 yaparak yaz bakalım bi o fonksiyonu... Sonra daha da geliştirirsin...




  • Buzz Lightyear B kullanıcısına yanıt
    siz bu mesajı yazana kadar yazmıştım buyrun fonksiyon bu arada şunu okadar çok merak ediyorum ki neden bizim akıllılar 2. ve 3. parametre yerine birtane long int veya unsigned long int parametresi koymamışlar derletri ney bunların zorluk çıkarmakmı !!!

     
    void frbytMove(long int byte, long int move, FILE *dosya)
    {
    fseek(dosya, 0, 2);
    long int len = ftell(dosya) - byte;

    if(len > 104857600) {return;} // 104857600 byte = 100 mb (mega byte)

    void *mem = malloc(len);

    if(!mem) {return;}

    fseek(dosya, byte, 0);
    fread(mem, len, 1, dosya);
    fseek(dosya, byte + move, 0);
    fwrite(mem, len, 1, dosya);
    free(mem);
    }
  • 
Sayfa: 1
- x
Bildirim
mesajınız kopyalandı (ctrl+v) yapıştırmak istediğiniz yere yapıştırabilirsiniz.