void[], türsüz baytlar anlamına geliyor. Yani en çiğ haliyle hiçbir tür bilgisi taşımayan veri.
void* ve void[] ile ilgili şu bölümler var ama tam bu dönüşümlerin oralarda olmadıklarını görüyorum.
"Her türü gösterebilen void*" başlığı altında:
http://ddili.org/ders/d/gostergeler.html
void[] dilimleri ile ilgili olarak:
http://ddili.org/ders/d/bellek_yonetimi.html
Ayrıca dizilerin .ptr niteliği ile ilk elemanın adresi elde edebiliyor.
Daha önceki koddaki sorun, ubyte[]'ın TAGdata'ya dönüştürülememesi idi. Biraz araştırınca void[] dizilerinin uzunluk doğru olduğu sürece başka her türün dizilerine dönüştürülebildiklerini öğrendim. O yüzden dosyadan bu aşamada TAGdata.sizeof kadar okumak önemli:
void[] baytlar = read(dosyaYolu, TAGdata.sizeof);
TAGdata data = (cast(TAGdata[])baytlar)[0];
Yukarıdaki kod void[] dizisinden tek elemanı bulunan bir TAGdata[] dizisine dönüştürüyor. Onun sıfırıncı elemanı da başlık bilgisini veriyor. (Belki Mengü bunun daha etkin bir yolunu çevrimiçi arkadaşlarından öğrenir. :))
Sonuçta şu çalışıyor:
import std.stdio;
import std.file;
struct TAGdata
{
char tag[3];
char title[30];
char artist[30];
char album[30];
char year[4];
char comment[30];
int genre;
};
void dosyayi_olustur(string dosyaYolu)
{
auto dosya = File(dosyaYolu, "w");
ubyte[1000] baytlar = 'a';
dosya.rawWrite(baytlar);
}
void main()
{
string dosyaYolu = "deneme_dosyasi.mp3";
dosyayi_olustur(dosyaYolu);
void[] baytlar = read(dosyaYolu, TAGdata.sizeof);
TAGdata data = (cast(TAGdata[])baytlar)[0];
writeln("Okunan : ", data.tag);
}
Ama bunun önemli sorunları var. Yukarıdaki TAGdata, ID3v1'i gösteriyor. O biçimde okumak için dosyanın gerçekten de o düzeni içerdiğini önceden bilmek gerekir. O düzendeki char[] dizileri ISO-8859-1 kodları taşıyorlarmış. Yani onların içindeki ASCII dışındaki ilk karakter Ronin'in karşılaştığı hatayı oluşturacaktır.
Daha sonraki ID3 düzenleri UTF-16 çeşitlerini destekliyorlarmış. O zaman ya wchar[] kullanılmalı, ya da başka bir yolla okunmalı. Zaten yukarıda da dediğim gibi, baytları önceden biliyormuş gibi cast(TAGdata) ile dönüştürmek doğru değil.
Kaynaklar:
http://en.wikipedia.org/wiki/ID3
http://www.id3.org/id3v2.4.0-structure
Dosyanın başında hangi ID3 düzeni bulunduğu id3.org'un sayfasında görülüyor. Şunun gibi ilginç bilgiler var:
Alıntı:
> An ID3v2 tag can be detected with the following pattern:
$49 44 33 yy yy xx zz zz zz zz
Where yy is less than $FF, xx is the 'flags' byte and zz is less than
$80.
ID3v2 olduğunu anlamak için ilk üç baytın "ID3" (0x49, 0x44, 0x33) olmalarından başka, yy'ler 0xff olamıyorlar, xx bayrak baytının kurallarına uymalı (son dört biti sıfır), ve zz'lerin en üst bitleri 0.
Mengü'nün gösterdiği Java kodlarına bakmadım ama bence baytlarımızı teker teker okuyarak hangi ID3 düzeni bulunduğuna karar verip o düzeni ifade eden bir nesne döndürmeliyiz:
ID3v1 ID3v1_oku(ubyte[] baytlar);
ID3v2 ID3v2_oku(ubyte[] baytlar);
// ...
Baytlara ilk bakan kod hangi düzen olduğunu anlayıp o işlevi çağırır.
Şimdilik bu kadar. :) (Çünkü aslında bilgiVer() gibi bir işlevi bulunan bir sınıf arayüzü daha uygun olabilir. Yani yukarıdaki ID3v1, ID3v2 gibi türler o arayüzü gerçekleştiren alt sınıflar olabilirler.)
Ali
--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]