MmFile, "memory-mapped file" anlamına geliyor. Türkçe'ye "bellekle eşleştirilmiş dosya" diye çevirebiliriz. Ne kadar büyük olursa olsun, bütün dosya sanki bellekte bir adreste oturuyormuş gibi sunuluyor. İşin güzel tarafı, aslında dosyanın yalnızca erişilen bölümleri gerektikçe otomatik olarak okunuyor.
Bu, aslında D'nin değil, işletim sisteminin sanal bellek (virtual memory) olanağından yararlanarak sunduğu bir olanak. Küçük dosyalarda yarardan çok zarar getirebilirmiş çünkü sanal belleğin kullandığı en küçük bellek birimi 4K. O yüzden, örneğin dosya 5K bile olsa toplamda 2 adet 4K kullanılması gerekiyor.
Bu olanak ancak binary dosyalarla kullanılabilir. Örneğin, bir metin dosyasını bu şekilde kullanmak uygun değil. Ek olarak, dosya içeriği olarak sunulan diziye eleman eklemeye kalkışmamak gerek çünkü D bütün içeriği bambaşka bir yere kopyalar ama işletim sisteminin bundan haberi olmaz.
Aşağıdaki program mevcut değilse bir dosya oluşturuyor, içeriğinin bir bölümünü dizi olarak kullanıyor. Güzel olan, dosyayı kendimiz açmıyoruz ve elemanları doğrudan kullanıyoruz. Programın gösterdiği gibi, dosyayı kayıt bile etmiyoruz. Biz belleği gerektiğinde dizi ile oynayarak değiştiriyoruz; asıl dosyanın değiştirilmesi işletim sistemine kalıyor.
import std.exception : enforce;
import std.range : iota, array;
import std.algorithm : map;
import std.string : format;
import std.conv : to;
import std.stdio : writefln, File, writeln;
import std.file : exists;
import std.mmfile : MmFile;
struct S {
double d;
int i;
short s;
byte b;
}
// Yanlışlıkla fazla büyük dosya üretmemek için yapay bir sınır
enum sınır = 1_000_000; // bayt olarak
void main() {
const dosyaİsmi = "S_nesnelerim";
if (exists(dosyaİsmi)) {
writefln("%s dosyası mevcut olduğundan tekrar oluşturmuyorum.", dosyaİsmi);
} else {
const adet = 10;
dosyaOluştur(dosyaİsmi, adet);
}
elemanlarıKullan(dosyaİsmi);
}
void dosyaOluştur(string dosyaİsmi, ulong adet) {
enforce(adet * S.sizeof <= sınır,
format("Fazla büyük dosya oluşturmak istemiyorum." ~
" Gerekiyorsa 'sınır' değişkeninin değerini değiştirin."));
auto dosya = File(dosyaİsmi, "w");
// Kaç adet eleman olduğunu yaz
dosya.rawWrite([adet]);
// Elemanları üret
const dizi = adet.iota.map!(i => S(i + 0.5, i.to!int, i.to!short, i.to!byte)).array;
// Dosyaya yaz
dosya.rawWrite(dizi);
writefln("%s dosyasını oluşturdum:", dosyaİsmi);
writefln("%(%s\n%)", dizi);
}
void elemanlarıKullan(string dosyaİsmi) {
// mm, dosyanın içeriğine erişim sağlayan bir nesnedir
// 0: uzunluğunu dosyadan kendin hesapla anlamına geliyor
// null: dosyayı bellekte istediğin yere yerleştir anlamına geliyor
auto mm = new MmFile(dosyaİsmi, MmFile.Mode.readWrite, 0, null);
// Bu dosya düzeninde en başta ulong türünde adet bilgisi bulunduğunu
// biliyoruz. O yüzden mm'in iki farklı dizi olarak dilimliyoruz:
const adet = (cast(ulong[])(mm[0..ulong.sizeof]))[0];
auto dizi = cast(S[])mm[ulong.sizeof..mm.length];
// Elemanlara nasıl erişildiğini göstermiş olmak için ortadaki elemanla
// oynuyoruz
dizi[$/2].i *= 2;
writefln("Ortadaki elemanı değiştirdim:");
writefln("%(%s\n%)", dizi);
}
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]