Thread overview
Tüm Dosyaları MD5'lemek! (hızlı çözüm)
Oct 09, 2012
Salih Dinçer
Oct 09, 2012
Salih Dinçer
Oct 09, 2012
Salih Dinçer
Oct 09, 2012
Salih Dinçer
Oct 09, 2012
Salih Dinçer
October 09, 2012

Merhaba,

Dün akşam şurada (http://forum.ceviz.net/d-dili/121391-tum-dosyalari-md5lemek-hizli-cozum.html) paylaştığım işe yarar uygulamayı, burada da paylaşmamak olmaz diye düşündüm. Bunu yapmadan önce biraz daha geliştirip (artık dirEntries() sayesinde alt dizinleri özyinelemi olarak tarıyor!) ve önemli bir kaç hatasını giderdim...

/*
*   genMD5files.d (v1.2)
*/
import std.stdio, std.conv, std.file, std.md5;

struct container {
   char[1024] buffer;

   string toString() {
       int[] primes = [ 3, 5, 11, 17, 29, 41, 59, 71, 101,
                        107, 137, 149, 179, 191, 197, 227,
                        239, 269, 281, 311, 347, 419, 431,
                        461, 521, 569, 599, 617, 641, 659,
                        809, 821, 827, 857, 881, 1019 ];
       char[][] md5;

       foreach(x; primes) {
           if(x < buffer.length) {
               md5 ~= [ buffer[x..x+1], buffer[x+2..x+3] ];
           }
       }
       return getDigestString(to!string(md5));
   }
}

void main(string[] args) {
   string path = args.length > 1 ? args[1] : ".";
   SpanMode mode = args.length > 2 ? args[2] == "-R" ?
                                   SpanMode.breadth :
                                   SpanMode.depth :
                                   SpanMode.shallow;

   foreach(string name; dirEntries(path, mode)){
       container t;
       if( ! isDir(name) ) {
           auto data = File(name, "r");
           data.rawRead(t.buffer);
           t.writeln(" (", name, ")");
       }
   }
}

Kullanmak için genMD5files . -R veya sadece bulunduğunuz yerdeki başka bir dizin için genMD5files obj ve ./obj/ dizini altındakiler için ise -R de ekleyebilirsiniz. Aslında **-Mö **de deseniz farketmiyor çünkü recursive olan diğer mode'a geçiyor. Şimdilik bu kadar geliştirme yeter...:)

Başarılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 09, 2012

Güzel ve akıllıca...:)

Öncelikle bu akıllıca sorulardan şu şekilde yırtayım:

Kodun şu hale gelmesine 'dirEntries()' işlevi sebep oldu, suçlu o!

Şaka bir yana gerçekten de eski sürümlerde (<1) olmayan bu sorunlar, sırf özyinelemeli özellikleri için zorunda kaldığım hususlar oldu. Örneğin 'with()''i kaldırıp struct'a çevirmem ve buffer'a static özelliğini koymam hep 'dirEntries()' işlevinin nanemollalığı...)

Çünkü hep parçalama hatası alıyordum. Ali hocam bilir, 'with()''i kullanmayı çok severim. Onu kaldıracak derecede zart zurt etmesi bana bu kadar köklü değişikliğe gitmeme sebep oldu. Hoş özyinelemeli olması dışında şu özellikleri gerçekten tercih edilesi bırakıyor:

  • Önceki işlev 'listDir()' emekliye ayrılması
  • Dosyanın tam yolunu döndürmesi
  • İşletim sistemine göre slash ve ters slash ayrımını hissetmesi
  • Çalıştırırken parametre serbestliği (obj, ./obj, obj/ ve ./obj/ hep aynı)

Yine de var olan sorunları farklı şekillerde halledebileceğimizi düşünüyorum...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 09, 2012

Az önce yukarıdaki kodu değiştirdim. Çünkü tek çözüm olarak taşıyıcının kurulduğu satırı döngü içine almak geldi. Ancak ne hikmetse buna gerek yok. Eğer bir şeyleri karıştırmadıysam (gerçi basit bir denemeydi) 1 KB'dan küçük dosyalarda MD5 kodu her iki çözümde de aynı:
Alıntı:

>

F0144C70A8CA250061EB456D9DFFEFD8 (.\opengl.d)
F0144C70A8CA250061EB456D9DFFEFD8<- emin olmak için sadece MD5'i kopyaladım...

İyice emin olmak için MD5'den önceki değerleri ekrana yansıttım. Son düzenleme de çözüm değilmiş! Oysa her döngü yenilendiğinde container nesnesi tekrar kurulmaz mı?

Alıntı:

>

["G", "\n", "\n", "\n", "\r", "H", "\x00", x"A5"c, x"B1"c, "o", '"\x00", x"CE"c, x"FC"c, "
x05", "\x00", x"C2"c, "f", x"E9"c, x"C6"c, "\r", x"DD"c, "P", x"AA"c, "j", "0", x"CC"c, "#
", x"F7"c, "\f", "y", """, x"B9"c, x"97"c, x"F7"c, "(", x"97"c, "v", "4", x"DF"c, "1", x"
F0"c, x"9D"c, x"95"c, "", "\x1B", x"D6"c, "\a", x"E6"c, x"8B"c, x"C0"c, x"D9"c, "z", x"F2
"c, "2", "|", x"B4"c, x"D5"c, "\x1C", x"F7"c, x"8D"c, "\x02", "\b", "\x02", "\b", x"80"c,
"\x01", "\x00", "\x02", "\x01", "\x04", x"D1"c, x"BB"c'] (veriler\primes.img)
["h", " ", " ", "f", "e", "h", ".", "x", "d", "l", "\n", "e", "o", "j", '"\x00", x"C2"c, "f
", x"E9"c, x"C6"c, "\r", x"DD"c, "P", x"AA"c, "j", "0", x"CC"c, "#", x"F7"c, "\f", "y", "
"", x"B9"c, x"97"c, x"F7"c, "(", x"97"c, "v", "4", x"DF"c, "1", x"F0"c, x"9D"c, x"95"c, "

", "\x1B", x"D6"c, "\a", x"E6"c, x"8B"c, x"C0"c, x"D9"c, "z", x"F2"c, "2", "|", x"B4"c, x"
D5"c, "\x1C", x"F7"c, x"8D"c, "\x02", "\b", "\x02", "\b", x"80"c, "\x01", "\x00", "\x02",
"\x01", "\x04", x"D1"c, x"BB"c'] (veriler\clear.bat)

Maviler aynı yani önceki döngüden buffer[]'dan kalanlar...:(

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 09, 2012

Tamam şimdi oldu...:)

Ne hikmetse (belki Linux'a geçince yine hata verecek!) sorun şöyle düzeldi:

  • static'i kaldırdım (nasıl olduysa!) ve
  • container'ı döngü içinde bıraktım...

Anlamadığım şey ise static olan bir üye yeniden oluşturulduğunda (malum küme sonlanınca GC'ye emanet etmiyor mu?) neden önceki bilgilerini muhafaza edebiliyor? Sankli global variable gibi bir olay söz konusu!

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 09, 2012

Teşekkürler hocam, bu vesileyle yeni bir şey daha öğrendik. Tabii ki static'in anlamını çok iyi biliyordum ama destruct olduğunda bunun paylaşılan bir nesne olmayacağını düşünüyordum. Belki destroy() yapmak da bir değişikliğe yol açmayacak...:)

Bu arada Nokta() yapısını ve örneğini incelerken bir şey dikkatimi çekti; şu satır:

auto üstteki = NoktaOluştur(7, 0);

Sanki 'NoktaOluştur()' bir işlev değil de biz burada aynı isimde bir yapıyı kuruyormuş gibi görünmüş. Hoş döndürdüğü değer de bir yapı nesnesi ya...:D

Elbette tüm kodu inceleyince birinin yapı birinin işlev olduğu anlaşılıyor. Belki 'new' operatörünü kullanmak iyi bir alışkanlık olacak. Sanırım D'de bir çok kurma ve eşitleme olanakları C'ye uyumluluğu arttırmak için. Güzel parantezler ( {, } ) ile yapılan işlemleri de geçen hafta dersinizde öğrendim. Eski C'cilerin D'ye geçmek için çok sebebi var gibi geliyor bana...:)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 09, 2012

Güzel ve kısa. :)

container.buffer'ın static olmasını riskli görüyorum. İki container nesnesi aynı anda kullanılsa buffer'ı paylaştıkları belli olmuyor:

   dosya0.rawRead(t0.buffer);
   dosya1.rawRead(t1.buffer);    // t0.buffer'ın üstüne yazdı

Bir de, container'ı kullananların onun bir üyesinin içine okumaları sarmayı deliyor. :) Herkes kendisine ait bir yere okusa ve ondan sonra "şunu md5'le" dese daha kullanışlı olur.

Hatta, işlemin toString içinde yapılıyor olması olaya gizem katmış. ;) Tabii toString'i yavaşlatıyor da.

Bir soru: rawRead, kısa bir dosya geldiğinde 1024'ten az bayt okuyordur. O zaman buffer'ın son tarafında hâlâ önceki dosyanın baytları duruyordur, değil mi? Bir hata mı?

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 09, 2012

dirEntries'in daha önce gösterdiği bir dosya uzun olsun (1024 veya daha büyük). Onun baytları buffer'da kalacaklar.

Daha sonra okunan bir dosya daha kısa olsun. toString'in içinde foreach primes'ı gezerken önceki dosyanın baytlarını da kullanır.

Eğer bu hatayı denediğin halde görmediysen belki de iki dosya da kısa oldukları için olmuştur.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 09, 2012

Alıntı (Salih Dinçer):

>

Sankli global variable gibi bir olay söz konusu!

Aynen öyle. static üyeden bir adet bulunur. O üye o türün bütün nesneleri tarafından paylaşılır.

O üye program başında bir kere ilklenir. Her nesne oluşturulduğunda tekrardan ilklenmesi başka nesnelerin işini bozacaktır. Öyle olsaydı şurada "static üyeler" başlığındaki örnek çalışamazdı:

http://ddili.org/ders/d/yapilar.html

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 09, 2012

Alıntı (Salih Dinçer):

>

Sanki 'NoktaOluştur()' bir işlev değil de biz burada aynı isimde bir yapıyı kuruyormuş gibi görünmüş

Kodlama standardı ne olursa olsun böyle karışıklıklar oluyor. :( Belki noktaOluştur() daha doğru olurmuş ama o zaman da türün adı 'nokta' gibi görünüyor. O zaman yeniNokta() daha iyi bir isim olabilirmiş. (?)

Benzer bir durum D'nin toString işlevinde de var. Dönüştürülen tür 'String' mi 'string' mi? Kodlama standardı birleşik sözcükleri büyük harfle yazdırınca toString oluyor. :(

O kadar önemli değil tabii. :)

Alıntı:

>

Belki new operatörünü kullanmak iyi bir alışkanlık olacak.

O örnekte olamıyor çünkü kullanıcılar 'new Nokta' deseler numara değişkenini de kendileri yönetmek zorunda kalırlar. Olmaz.

Ayrıca new ile oluşturulan nesne çöp toplayıcıya bırakılacağından sonlanması hemen olmaz.

Aslında burada daha iyisi 'static opCall'dur. Yukarıdaki bölümde bilerek göstermemiştim. Sonunda şurada "Varsayılan kurucu yerine static opCall" başlığında ortaya çıkıyor:

http://ddili.org/ders/d/ozel_islevler.html

İşin güzeli, ben tam da bu örneği Arayüzler bölümünde "static üye işlevler" başlığı altında 'static opCall' kullanacak biçimde değiştirdim bile! :) (Ama daha siteye koymadım.) O zaman kodda şaşıracak bir şey kalmıyor:

import std.stdio;

struct Nokta
{
   // Her nesnenin kendi tanıtıcı numarası
   size_t numara;

   int satır;
   int sütun;

   // Bundan sonra oluşturulacak olan nesnenin numarası
   static size_t sonrakiNumara;

   this (int satır, int sütun)
   {
       this.satır = satır;
       this.sütun = sütun;
       this.numara = yeniNumaraBelirle();
   }

   static size_t yeniNumaraBelirle()
   {
       immutable yeniNumara = sonrakiNumara;
       ++sonrakiNumara;
       return yeniNumara;
   }
}

void main()
{
   auto üstteki = Nokta(7, 0);
   auto ortadaki = Nokta(8, 0);
   auto alttaki =  Nokta(9, 0);

   writeln(üstteki.numara);
   writeln(ortadaki.numara);
   writeln(alttaki.numara);
}

Ama static opCall'un tanımlanmış olması ortalığı biraz karıştırıyor. Bu soru şurada da daha bugün geçti:

http://forum.dlang.org/thread/mryghcsskaxqhzmrvlof@forum.dlang.org

Benim oradaki yanıtım benzer başka konulara bağlantı da içeriyor.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]