Forum: Diğer Konular RSS
C++ binary dosya yaratma yazma ve okuma
Sayfa:  1  2  sonraki 
cos00kun #1
Üye Kas 2014 tarihinden beri · 104 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: C++ binary dosya yaratma yazma ve okuma
C++ binary dosya yaratma,yaratılan dosyaya yazma ve bu dosyadan okuma hakkında türkçe kaynak yada bilgi rica ediyorum.. c++ ile ilgili İngilizce kaynaklar benim ingilizce seviyeme göre bir yere kadar yeterli oluyor belki ancak daha derin konularda maalesef yetersiz kalıyor.. Türkçe bulduğum video ve kaynaklarda ise bu binary konusu ya çok karışık anlatılmış yada çok az değinilmiş oluyor..

Konunun cevabının uzun ve büyük olacağı gerekçesiyle daha kısa cevaplar oluşturacak sorular sorayım;

neden binary dosyalarda;
..........
fstream dosya;
 dosya<<"Al sana yazi.." 
 .........
yukardaki sıralı dosyalarda olduğu gibi kolayca veri yazma yada okumalar yapılmıyorda

............
ifstream dosyam("FALCON4.ct", ios::binary);
    dosyam.read(reinterpret_cast <char*>(tampon), max * sizeof(int));
...........
gibi karışık fonksiyonlar kullanılıyor ..

aslında
dosyam.read(reinterpret_cast <char*>(tampon), max * sizeof(int));
  satırını az çok C++ de bilgisi olan birinin anlayabileceği ölçüde yani basit bir anlatımla birisi anlatabilirse herşey aydınlanacak.. Şimdiden herkese teşekkür eder hayırlı günler dilerim..
Not: C++ bilgim sınıflar fonksiyonlar oluşturup amatörce basit program yazabilecek ölçüdedir..
E=mc^2
cos00kun #2
Üye Kas 2014 tarihinden beri · 104 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Bu arada Ali hocam sizin http://acehreli.org/turkcecpp/tur_donusumu_islecleri.html yazınızda reinterpret_cast dan bahsedilmiş ancak orada tür değişimleri konusunda en güvensizi olduğundan bahsedip "C++ türleri içinde en güvenilmez olanıdır. ... " demişsiniz.. Binary Dosyalara yazma ve okumalarda Neden güvenli birşeyler kullanılmıyor da güvensiz birşeyler kullanılıyor acaba bunuda merak ettim açıkçası
E=mc^2
acehreli (Moderatör) #3
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #1
cos00kun:
yukardaki sıralı dosyalarda olduğu gibi kolayca veri yazma yada okumalar yapılmıyorda

Anlaşmaya bağlı bir konu... Asıl anlamının çıktıya bilgi göndermeyle en ufak bir ilgisi olmayan << işlecinin bu amaç için yüklenmiş olması, "bu değişkeni dizgiye dönüştür" anlamını taşır. O yüzden, örneğin dizi gibi bir değişkenin elemanlarının köşeli parantezler içinde yazılmasına kimse karşı çıkmaz. Programcı nasıl uygun görmüşse öyle kodlamıştır...

Binary'de ise böyle dönüşümlerle işimiz yok. :) (Örneğin, binary olmadığında '\n' karakteri de platforma uygun olarak dönüştürelibilir.)

dosyam.read(reinterpret_cast <char*>(tampon), max * sizeof(int));

Anlaşılan, tampon'un türü int*. max da 42 ise, dosyadan 42 adet int okunacak. (32 bitlik ortamda 42*4.) Tahminen, read'in ilk parametresinin türü de char*. O yüzden, derleyici o parametre yerine int* gönderilmesine izin vermiyor. Buradaki reinterpret_cast derleyiciye "sevgili derleyici, tampon'un int* olduğunu ve genelde char*'a uyumlu olmadığını biliyorum; ama sen bana güven ve tampon'u bir char* gibi kullanmama izin ver" demek anlamına geliyor.

reinterpret_cast'in güvensiz olmasının nedeni, derleyicinin bu konudan elini çekmesi ve programcıya güvenmesidir. Eğer dosyadaki baytlar aslında int değilseler, program yanlış veriyi int olarak kullanacak demektir. Güvensiz olan bu: derleyicinin olayı programcıya bırakmış olması...

read gibi işlevlerin char* kullanmalarının nedeni, alt düzey işlevler olmaları. Binary dosya düzeyinde bayt'tan başka bir şey bilmiyoruz. Öte yandan, XML, JSON ve başka düzenlerde olsa, verinin tam türünü de dosyada tutmuş olabiliriz ve tam türüne uygun olarak okuyabiliriz.

Ali
cos00kun #4
Üye Kas 2014 tarihinden beri · 104 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Işık hızı gibi cevabınız için ayrıca teşekkürler Ali Bey :)
yine müsait olduğunuz zaman şu sorularada cevap verebilirmsiiniz ?

soru1 ) diyelimki bir binary dosyam var ve bunlara zamanında kayıtlar şu şekilde yapılmış;
   int, char[5], 4* int, string, inti, int 
    bu sırayla diyelimki 120 tane kayıt var. Şimdi ben bu binary dosyadan ekrana aynı şekilde yani sıralaması değişmeden    int, char[5], 4* int, string, inti, int olacak şekilde ekrana yazdırmak istediğimde nasıl yapmam gerekiyor ??

soru2 ) D dilinde binary dosya okumalarında farklı bir kullanımmı var yoksa mantık aşağı yukarı aynımı dır ?
E=mc^2
erdem (Moderatör) #5
Üye Tem 2009 tarihinden beri · 978 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
cos00kun:
soru2 ) D dilinde binary dosya okumalarında farklı bir kullanımmı var yoksa mantık aşağı yukarı aynımı dır ?

Örneğin dosyaya bayt yazma:
 
import std.exception;
import std.stdio;
 
void main(string[] args)
{
    try
    {
        byte[] veriler = [0x68, 0x65, 0x6c, 0x6c, 0x6f];
 
        auto kütük = File("test.txt", "w");
 
        kütük.rawWrite(veriler);
    }
    catch (ErrnoException hata)
    {
        // Hataları işle
    }
}

Bayt okuma da şu şekide oluyor.

import std.exception;
import std.stdio;
 
void main(string[] args)
{
    try
    {
        byte[] bellek;
        bellek.length = 1024;
 
        auto kütük = File("test.txt", "r");
 
        auto veriler = file.rawRead(bellek);
    }
    catch (ErrnoException hata)
    {
        // Hata işle
    }
}
cos00kun #6
Üye Kas 2014 tarihinden beri · 104 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Amiyane tabiriyle canına yandığımın C++ dili, gözünü sevdiğimin D Dili :)

soru1 ) nin cevabını da alırsam tamamdır sanırım bu konu..
herkese tekrar teşekkürler..
E=mc^2
acehreli (Moderatör) #7
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Birinci sorunun hemen hemen her zaman için tek yanıtı var:

  • Veriyi temsil eden bir kullanıcı türü olsun

  • Dosyadaki bilgiyi okuyan ve bu türden nesnelere dönüştüren bir işlev olsun (Tabii, bir de yazdıran işlev olduğunu varsayıyoruz)

  • O işlevi 120 kere çağıralım ve oluşan elemanları teker teker ekrana yazdıralım (veya bir diziye ekleyelim, veya başka biçimde kullanalım, vs.)

Ek olarak, günümüzde dosyalara artık binary olarak yazmıyoruz çünkü bunun yarar sağladığı durumlarla karşılaşmıyoruz: Dosya işlemleri çok yavaş olduğundan binary okumayla düz metin okuma arasındaki zaman farkı önemli olmuyor ve bilgisayarlar çok hızlı olduklarından okunan verinin düz metinden yapı nesnesine dönüştürülmesi işlemi fazla zaman almıyor. Öyle olmasa bile, bu konudaki yavaşlıklar çoğu uygulamada önemli olmuyor. Ama tabii binary'den gerçekten yararlanan programlar da var.

Binary'nin gerçekten gerektiğini varsaydığımızda bir kaç tane önemli nokta var:

  • Dosyayı yazdığın ve okuduğun ortamlarda veriler aynı büyüklükte mi? Örneğin, int 2, 4, 8, veya başka sayıda bayt mı?

  • Yazan tarafla okuyan taraf doldurma (padding) baytları konusunda aynı fikirdeler mi? Örneğin, gösterdiğin yapıda char[5] geçiyor. Veri hızlı işlensin diye hizalama (alignment) uygulanmışsa sonraki dört int'ten önce ne kadar doldurma baytı kullanılmış?

  • İki taraf bayt sıraları (endianness) konusunda aynı fikirdeler mi? Örneğin, dosyadaki int'i gösteren 0x01, 0x02, 0x03, ve 0x04 baytları hangi değeri ifade ediyor? Yaygın olan 16,909,060 ve 67,305,985 değerlerinden hangisi? Yoksa bambaşka bir bayt sıralamasından mı bahsediyoruz?

  • Dinamik veri türleri nasıl yazılmışlar? Örneğin, veride string geçiyor. C++ ve D gibi dillerden bildiğimiz gibi, bu türler elemanlarını bir göstergenin gösterdiği yerde tutarlar. (Veya hatta small string optimization uygulamış olabilirler ve kısa dizgilerde gösterge yoktur.) O göstergenin gösterdiği ve olasılıkla bilinmeyen sayıda olan elemanlar bellekten okunup dosyanın neresine yazılmışlar? (Bu soruyu cevapladığımızda artık benim anladığım binary olmaktan çıkıyor ve jpg filan gibi aslında binary olan ama belirli bir düzene uyan dosya haline geliyor.)

Sonuncusuna gerek olmadığını kabul ettiğimizde diğer sorulardan kurtulmanın en kolayı, programı aynı derleyiciyle derleyip aynı (veya aynı çeşit) bilgisayarda çalıştırmaktır.

Ali
cos00kun #8
Üye Kas 2014 tarihinden beri · 104 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Desteklerinizle konuyu sanırım anladım.. sözkonusu C++ olunca aslında karmaşıklığını basite indirgemek lazım o zaman birçok konu kavranabiliyor.. özetlersek burda en önemli konu aslında verinin bellekteki başlangıcı yada veriyi nerden okuyacaksak onun adresinin char pointer türüne  (derleyici kısmen kandırmaca durumu :) ) dönüştürülmesi oluşturuyor.. gerisi zaten biraz yoğunlaşıp iyi çalışınca anlaşılabiliniyor.. Son yazdığınız cevaptan anladığım kadarıyla da veri dosyada byte halinde saklanıldığından, dosyadaki değişik veri türlerinde saklanma biçimlerini ve uzunluklarını okuturkende doğru ve aynı şekilde bilip okutmamızı gerekli..

Ali hocam ve Erdem kardeşim emekleriniz ve değerli bilgileriniz için çok teşekkürler.. kalın sağlıcakla
E=mc^2
cos00kun #9
Üye Kas 2014 tarihinden beri · 104 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
D dilindende uzak kalmayan ve zaman zaman ufak programcıklar da yazan biri olarak yukarıdaki konuda bahsedilen dosyadan okumayı D dilinde yazmaya kalkarsak nasıl bir veri türü karşılığında bulacağız.. ?

konunun iyi anlaşılması için dosyadan ne okunması gerektiğini anlatan bir excel tablosu ile okunacak dosyanın kendisini wetransfere atıyorum.. üşenmeden ilgilenen vakit ayıran varsa bir bakabilirse iyi olur.. Bende bir yandan D diline biraz yüklenmeye başlayacağım eğer bu bahsettiğim konuyu D dilinde çözebilirsem ve sorun yaşamassam D ye sandığımdan daha çabuk geçiş yapacağımı umuyorum.

https://wetransfer.com/downloads/f6ad7e2efd4edd1529bb2e938…

dosyalar yarım MB bile değil :)

Edit1: ve hatta boş bir zamanı olan varsa verilen dosyadan D dili ile bu binary dosyayı okutan basit bir program yazsa tadından yenmez :)  Not: dosyadaki ilk 2 byte yani numEntities olarak excel tablosunda belirtilen Signed 16-bit integer  2byte kadar kayıt okunacak.

bana bu istek için kızanlar olursa söyleyeyim bende bunu yazacağım ancak D dilinde bu konulara gelene kadar sanırım 1 ay zamana ihtiyacım var :) amacım sadece D diliyle C++ dilinde bu işlemlerin kıyasını yapabilmek sonra ona göre hangi dilde ilerlemem gerekliliğine karar vereceğim.. 

saygılar sevgiler
E=mc^2
Bu mesaj cos00kun tarafından değiştirildi; zaman: 2017-10-18, 08:39.
acehreli (Moderatör) #10
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
wetransfer'e üye olmak istemediğimden Excel dosyasını göremedim ama sanırım daha önce baktığımız .ct dosyası sayfası yeterli olmalı. Tembellik ettim ve VuEntity yapısını tamamlamadım ama gerisi senin için kolay olmalı: 4 bayt için int veya uint, 2 bayt için short veya ushort, 1 bayt için byte veya ubyte, vs.
import std.stdio;
import std.string;
import std.exception;
 
// Bkz: https://pmc.editing.wiki/doku.php?id=falcon4:file_formats:ct_file
 
align(1)
struct VuEntity {
align(1):
    ushort id;
    ushort collisionType;
    float collisionRadius;
    byte[8] classInfo;
    // vs....
    // Bütün türleri yazmak istemediğimden bu türün büyüklüğünü
    // belgede belirtilen 60'a tamamlıyorum
    byte[44] doldurma;
}
 
// Denetleyelim
static assert (VuEntity.sizeof == 60);
 
align(1)
struct Falcon4Entity {
align(1):
    VuEntity vuClassData;
    short[7] visType;
    short vehicleDataIndex;
    byte dataType;
    uint dataPtr;
}
 
// Denetleyelim
static assert ((Falcon4Entity[2]).sizeof == 81 * 2);
 
Falcon4Entity[] oku(string dosyaİsmi) {
    auto dosya = File(dosyaİsmi, "rb");
 
    short adet;
    auto okunanAdet = dosya.rawRead((&adet)[0..1]);
    enforce(okunanAdet.length == 1, "HATA: Adet değerini okuyamadım");
 
    writefln("%s adet nesne okuyorum", adet);
 
    auto entries = new Falcon4Entity[](adet);
    auto okunanEntries = dosya.rawRead(entries);
    enforce(okunanEntries.length == adet,
            format("HATA: %s yerine yalnızca %s nesne okudum", adet, okunanEntries.length));
    return entries;
}
 
int main(string[] args) {
    if (args.length != 2) {
        stderr.writefln("Kullanım: %s <dosya ismi>", args[0]);
        return 1;
    }
 
    Falcon4Entity[] entries = oku(args[1]);
 
    writefln("Elimde %s adet nesne var: %s", entries.length, entries);
 
    return 0;
}
Ancak, daha önce de konuştuğumuz endianness konusu hâlâ geçerli. Bu tür bir okuma ancak okuyan bilgisayar dosyayla uyuştuğunda doğrudur.

Ali
cos00kun #11
Üye Kas 2014 tarihinden beri · 104 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Hay Allah razı olsun sizden .. Çok teşekkürler.. yukardaki kodlamada bazı kavramlara uzak olsamda çok büyük kısmı anlayabileceğim türden... yarından sonra biraz D ye ağırlık vereceğim C++ öğrenmem sebebiyle daha hızlı bir ilerleme olacaktır... bakalım..

endianness konusunda endişe etmeyin zira yapacağım programın birçok versiyonu 1990 lı yıllarda yazılmıştı ve ordaki verilere yapacağım taşmalardan hangi veri tipinin yukarda belrttiğiniz veri türü eşleşmeleriyle örtüştüğünü bulabilirim sanırım..

Bundan sonra Artık D konuşacağız ancak kafanızı çok ağırtırım haberiniz olsun.. hakkınızı şimdiden helal edin :)
E=mc^2
acehreli (Moderatör) #12
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
cos00kun:
kodlamada bazı kavramlara uzak olsamda

align(1)'ler, üyelerin (ve struct nesnelerinin) 1 bayta hizalanacaklarını belirliyor. Bu arada, kodu hiç denemedim; içinde her tür hata olabilir. :)

D konuşacağız ancak kafanızı çok ağırtırım haberiniz olsun

Burada amaç zaten D konuşmak. :)

Ali
cos00kun #13
Üye Kas 2014 tarihinden beri · 104 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Ali hocam şöyle bir hata mesajı aldım

[Resim: https://i.hizliresim.com/g92RQZ.png]
E=mc^2
erdem (Moderatör) #14
Üye Tem 2009 tarihinden beri · 978 mesaj · Konum: Eskişehir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Tabi şuna benzer şekilde çalıştırman gerekiyor   ;-)

$ ./dosyalama FALCON4.ct
cos00kun #15
Üye Kas 2014 tarihinden beri · 104 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
erdem:
Tabi şuna benzer şekilde çalıştırman gerekiyor   ;-)

$ ./dosyalama FALCON4.ct

Neden FALCON4.ct ekle çalıştırmamız grektiğini anlamadım ancak bunu program içinden çağıramazmıyızki ? Ben herhangi bir IDE ile programı yazdığımda sorun vermezmi bu durum..

Bu arada gtkd dökümanlarınızıda okumaya başlıyorum ancak D dili ve eklentilerini yani IDE leri, kütüphaneleri vesaire kurması  okadar çok problemliki windowsta..  ayarlaması bir dert kurması bir dert hepsini :( ancak gördüğüm kadarıyla D dilinin kolay ve basit kodalanabilirliğini bu kütüphanedede görebiliyorum... her ne kadar henüz D ile gtkd yi tam örtüştürememiş olsamda bu pazar IDE ve kütüphane kurma olayını tam olarak çözmeyi umud etmekteyim..
E=mc^2
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Sayfa:  1  2  sonraki 
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-18, 17:22:42 (UTC -08:00)