Jump to page: 1 2
Thread overview
Dosyadan bayt okumak
Jan 20, 2012
zafer
Jan 20, 2012
Mengu
Jan 20, 2012
Ronin
Jan 20, 2012
zafer
Jan 23, 2012
zafer
Jan 24, 2012
zafer
Jan 26, 2012
zafer
Jan 26, 2012
zafer
Jan 27, 2012
zafer
January 20, 2012

Merhaba,

Bir mp3 dosyasını okuyup içindeki ID3 bilgilerini almak istiyorum. Ancak bir türlü dosyayı bayt olarak okuyup yapamadım.

http://en.wikipedia.org/wiki/ID3 bu adresteki bilgilerden anladığım kadarıyla bilgiler belli bir bayt düzeninde yerleştirilmiş ama D ile bu düzeni okumayı başaramadım hatta daha güzeli bu yapıyı birebir bir yapı (struct) içine aktarabilsem çok daha güzel olur.

Bu konuda yardım istiyorum??

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

January 20, 2012

selamlar zafer

http://javamusictag.sourceforge.net/download.htm adresinde java icin bir kutuphane var. bu kutuphaneyi incelemeni tavsiye ederim.

ek olarak, dosyadan nasil byte okuruz diye #d kanalinda sordugumda soyle cevap verildi:

auto bytes = cast(byte[])std.file.read("test.d");

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

January 20, 2012

Şöyle birşey yaptım fakat ihtiyacı karşılamıyor.

import std.stdio;
import std.file;
import std.stream;
void main()
{
	char[21]  filename  = "BenzemezKimseSana.mp3";
 if (exists(filename)!=0) {
   ulong size = getSize(filename);

   writefln("%r", cast(char[])read(filename,-128));
 } else {
   writefln("File not found. Please try again later :-)");
   /* File does not exist! */
 }
}

Çıktısı da şu şekilde
Alıntı:

>

I D 3 ♥ ☺ # T I T 2 ¶
B e n z e m e z K i m s e S a n a
T R C K ♣ 1 / 1 2 T L E N
2 1 8 0 2 7 T A L B ‼
E n S o n O k u d u k l a r i m
T P E 1 ☼ M u z e y y e n
S e n a r C O M M
std.utf.UTFException@std\utf.d(644): Invalid UTF-8 sequence (at index 1)

47A6E8
47A55F
40462D
4051B7
404DB6
404C2F
4024AB
40213C
4020AE
4075B8
4075FC
4071F3
4DB26D

           e   n   g       M   U   Y   A   P   T   C   O   N               ☻
           1   T   Y   E   R               ♣               2   0   0   0

7
C:\Users\workspace\d1\bin>

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

January 20, 2012

std.file.read'in seçime bağlı ikinci parametresi de kaç bayt okunacağını belirliyormuş.

İki seçenek daha var: std.stdio.File.rawRead ve belki readf'i "%r" ile kullanmak. Sonuncuyu hiç denemedim ama writef'yin "%r" (raw) diye bir belirteç desteklediğini öğrendim. Belki readf'te de vardır. "%-r" küçük soncul (little endian) olarak, "%+r", büyük soncul (big endian), "%r" de platformun yerel sonculluğunu kullanıyormuş.

Ali

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

January 20, 2012

Önce önemsiz bir ayrıntı: :)

Alıntı (Ronin):

>
>   if (exists(filename)!=0) {
> ```


exists() kendisi bir mantıksal ifade (bool) olduğundan, false ve true'nun 0 ve 1'e otomatik olarak dönüşme özelliğini kullanmak yerine yine mantıksal ifadede kalınabilir:


if (!exists(filename)) {




Alıntı:
>
>
writefln("%r", cast(char[])read(filename,-128));
>

...
std.utf.UTFException@std\utf.d(644): Invalid UTF-8 sequence (at index 1)

Onun çalışmasını bekleyemeyiz, çünkü hatırlarsan char[], UTF-8 olarak kodlanmış dizgidir. İçinde yasal UTF-8 kodları bulunmayan dosyaya o biçimde davranamayız.

Zaten o yüzden read()'in dönüş değeri ubyte[]. O ubyte kendimiz ne anlama geldiklerine göre dönüştürebiliriz.

Örneğin mp3 dosyasının baş tarafını ifade eden bir yapı olsa:

   auto başlık = cast(Mp3Başlığı)baytlar;

Ama o durumda da soncullukla ilgili sorunlar olacaktır. O yüzden en hızlı yöntem olmasına karşın her ortamda doğru olmayabilir.

Ali

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

January 21, 2012

Mengü, teşekkürler javadan çok anlamasamda adresteki kütüphaneyi inceledim. Daha öncede bu alanda çok bilinen taglib (http://developer.kde.org/~wheeler/taglib.html) kütüphanesine bakmıştım. Hatta şu adresde D ile kullanım için proje geliştirilmiş. https://github.com/AndrejMitrovic/DTagLib Bunlar hazır kütüphane kullanmak isteyenler için güzel özellikleride var ama ben dosyayı kendim direk okumak istiyorum D ile belki sizlerde yardım ederseiniz küçük bir kütüphane hazırlayıp insanlığa hediye de edebiliriz tabi :)

Ronin, kodlar için teşekkürler, umarım bu desteğin devam eder. Hep beraber D kodu yazmak keyifli olur diye düşünüyorum.

Ali, mesajının sonunda bahsettiğin yapı şöyle bir şey olabilir mi;

struct TAGdata
{
	char tag[3];
   char title[30];
  	char artist[30];
   char album[30];
	char year[4];
   char comment[30];
	int genre;
};

Aslında benimde yapmak istediğim dosyadan okudum bilgiyi bu yapı içine doldurmak, bunun için şöyle bir kod yazmaya çalıştım ama çalışmadı tabi;

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 main()
{
	string dosyaYolu = "Fading.mp3";

	TAGdata data = cast(TAGdata) read(dosyaYolu, 128);;

	writeln("Okunan : ", data.tag);
}

Bu kod derleme esnasında aşağıdaki hatayı veriyor;

Alıntı:

>

Error: Error: cannot cast from void[] to TAGdata

Bu void[] nedir onuda anlamadım zaten, bu bilgiyi TAGdata yapısına çevirmeyide başaramadım. Arkadaşlar yardımmm!!

'Not: Bu arada işlerim yoğunluğundan bir süre buraya uğrayamadım. Buradaki küçük ama sıcak ve samimi ortamı çok özlemişim, bunuda belirtmek isterim :)'

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

January 21, 2012

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. ]

January 23, 2012

Malesef olmadı :(

Yazdığın kodları denemek için önce bir mp3 dosyasının diğer tüm bilgilerini silip sadece ID3v1 bilgilerini tanımladım. Bu işlemi winamp ile yaptım. Ardından eklediğin kodları kullanarak Id3v1 bilgisini okumaya çalıştım. Bu arada bu bilgiler tamamen ASCII karakterleri içeriyor. Buna rağmen düzgün bir çıktı elde edemedim.

Ayrıca mp3tag isimli program ile dosyayı kontrol ettiğimde ID3v1 bilgisini düzgün bir şekilde görebiliyorum.

Bir diğer konu daha önce bu konu ile ilgili bir C++ kodu yazmışım ve o kod dorunsuz çalışıyor. D ile neden bu kadar zorlandık anlamıyorum. Yardımları bekliyorum.İlgili C++ kodunuda aşağıya ekliyorum.

#include <iostream>
#include <fstream>

#define ETIKET_BOYUT 128

using namespace std;

struct ETIKETLER
{
	char baslik[31];		// title
	char sanatci[31];		// artist
	char album[31];			// album
	char yil[5];			// year
	char mesaj[31];			// comment
	char bos;				// zero
};

int main()
{
   ETIKETLER etiketPaketi;
   ifstream mp3Dosya("D:\\test.mp3", ios::binary);
   char etiketKontrol[4] = {0};

   memset(&etiketPaketi, 0, sizeof(etiketPaketi));

   char *tampon = new char[ETIKET_BOYUT + 1];

   mp3Dosya.seekg(-ETIKET_BOYUT, ios::end);
   mp3Dosya.read(tampon, ETIKET_BOYUT);

   strncpy(etiketKontrol, tampon, 3);

   if (strcmp(etiketKontrol, "TAG") == 0)
   {
       strncpy(etiketPaketi.baslik, tampon + 3, 30);
       strncpy(etiketPaketi.sanatci, tampon + 33, 30);
       strncpy(etiketPaketi.album, tampon + 63, 30);
       strncpy(etiketPaketi.yil, tampon + 93, 4);
       strncpy(etiketPaketi.mesaj, tampon + 97, 28);

       // Etiket bilgilerini ekrana yaz.
       //EtiketBilgisiYaz(etiketPaketi);
   }

   return 0;
}

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

January 24, 2012

Ben ID3v1 düzeninin dosyanın sonunda olduğunu anlamamışım. Baktığım site ID3v2.4.0'ı gösteriyordu. Zafer'in C++ programından öğrendim ve şu sayfadaki "ID3v1/ID3v1.1 test suite" ile denedim:

http://www.id3.org/Developer_Information

Yalnızca başlığı yazdırıyor ama oldu:

import std.stdio;
import std.string;
import std.exception;
import std.conv;

struct ID3v1Pakedi
{
   char[3]  TAG;           // "TAG" belirteci
   char[30] başlık;        // title
   char[30] sanatçı;       // artist
   char[30] albüm;         // album
   char[4]  yıl;           // year
   char[30] mesaj;         // comment
   char[1]  tarz;          // genre

   string toString() const
   {
       return to!string(başlık);
   }

   static ID3v1Pakedi oku(File dosya)
   {
       scope(exit) dosya.seek(dosya.tell(), SEEK_SET);
       dosya.seek(-ID3v1Pakedi.sizeof, SEEK_END);

       ID3v1Pakedi[1] paketler;
       dosya.rawRead(paketler);

       ID3v1Pakedi paket = paketler[0];

       enforce(paket.TAG == "TAG",
               format("'%s', bir ID3v1 dosyası değil!", dosya.name()));

       return paket;
   }
}

int main(string[] args)
{
   if (args.length < 2) {
       stderr.writefln("Kullanım: %s dosya1.mp3 [dosya2.mp3 [...]]", args[0]);
       return 1;
   }

   foreach (dosyaİsmi; args[1..$]) {
       auto etiketPakedi = ID3v1Pakedi.oku(File(args[1], "r"));
       writeln(etiketPakedi);
   }

   return 0;
}

Notlar:

  • oku(), akıllı bir işlev olarak kendisine verilen dosyanın başlangıçtaki yerini scope(exit) ile garantiliyor. dosya.seek() yaparak okuma yerini bozmadan hemen önce "buradan nasıl çıkarsak çıkalım şu temizlik işlemini yap" demiş oluyor. D'nin en güçlü olanaklarından birisi! C++'ta olsa bir RAII sınıfı yazmak zorunda kalırdık veya daha da belalısı olarak try-catch yazmak zorunda kalırdık.

  • oku()'yu çağıranların bu dosyanın kesinlikle bir ID3v1 dosyası olduğunu bilmeleri gerekiyor. Yoksa oku() enforce() ile bir hata atıyor. Daha temizi, ID3v1Pakedi.oku()'yu başka bir işlevin çağırması olur. Bu işlev önce hangi düzende olduğunu anlar ve ondan sonra doğru oku() işlevini çağırır.

Ali

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

January 24, 2012

Alıntı (acehreli):

>

oku(), akıllı bir işlev olarak kendisine verilen dosyanın başlangıçtaki yerini scope(exit) ile garantiliyor.

Öyle olsun istiyor ama programcı hatası var! :( scope(exit)'in ifadeleri bu kapsamdan çıkılırken işletileceği için seek.tell()'i çıkarken çağırmak geç olur. Onun başlangıçtaki değerini saklamamız gerekir:

       immutable dosyaYeri = dosya.tell();    // <-- değişkende sakla
       scope(exit) dosya.seek(dosyaYeri, SEEK_SET);
       dosya.seek(-ID3v1Pakedi.sizeof, SEEK_END);

Ali

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

« First   ‹ Prev
1 2