TXMLDocument kullanımı hk.
Forum kuralları
Forum kurallarını okuyup, uyunuz!
Forum kurallarını okuyup, uyunuz!
TXMLDocument kullanımı hk.
Merhaba arkadaşlar,
Rad XE5 ile TCP Client/Server projemin bir aşamasında içinden çıkamadığım bir sorun için yardımcı olursanız sevinirim.
Projem uzaktan sistem yönetim özelliklerine sahip. Projemde ayrıca uzaktan çoklu masa üstü modülünü geliştirmekteyim. Client sorunsuz olarak severe masa üstü görüntüsünü göndermekte ve yönetebilmekteyim. Ayrıca belirli aralıklarda tüm Clientlerden Rapor almaktayım RAM kullanım oranı, CPU kullanım oranı, aktif uygulamaların listesi vs. Tabi bu raporu TStringList olarak almaktayım. Ancak Masa Üstünü görüntülediğim ve yönettiğim Client rapor gönderdiğinde çakışma olmaktadır.
Yani TMemoryStrem beklerken Rapor gönderildiğinde (TStringList) Görüntü donuyor, haliyle bağlantı sorunlarıda oluyor.
Bende, TXMLDocument kullanayım istedim, tüm bilgileri tek pakette göndereyim Rapor ve Data. Fakat bu Componenti yeterince tanımıyorum.
Yapmak istediğim TXMLDocument'in bir bağına data (TBitmap içeriği vb.) yüklemek istiyorum. Bu yapılabilir mi yapılabilirse nasıl veya yukarıda izah ettiğim çalışmaya başka bir önerisi olan var mı?
Saygılar Yaşar.
Rad XE5 ile TCP Client/Server projemin bir aşamasında içinden çıkamadığım bir sorun için yardımcı olursanız sevinirim.
Projem uzaktan sistem yönetim özelliklerine sahip. Projemde ayrıca uzaktan çoklu masa üstü modülünü geliştirmekteyim. Client sorunsuz olarak severe masa üstü görüntüsünü göndermekte ve yönetebilmekteyim. Ayrıca belirli aralıklarda tüm Clientlerden Rapor almaktayım RAM kullanım oranı, CPU kullanım oranı, aktif uygulamaların listesi vs. Tabi bu raporu TStringList olarak almaktayım. Ancak Masa Üstünü görüntülediğim ve yönettiğim Client rapor gönderdiğinde çakışma olmaktadır.
Yani TMemoryStrem beklerken Rapor gönderildiğinde (TStringList) Görüntü donuyor, haliyle bağlantı sorunlarıda oluyor.
Bende, TXMLDocument kullanayım istedim, tüm bilgileri tek pakette göndereyim Rapor ve Data. Fakat bu Componenti yeterince tanımıyorum.
Yapmak istediğim TXMLDocument'in bir bağına data (TBitmap içeriği vb.) yüklemek istiyorum. Bu yapılabilir mi yapılabilirse nasıl veya yukarıda izah ettiğim çalışmaya başka bir önerisi olan var mı?
Saygılar Yaşar.
Re: TXMLDocument kullanımı hk.
TXMLDocument ile nasıl yapabilirsiniz bilmiyorum ama tüm bilgileri TMemoryStream ile gönderebilirsiniz.
İlk aklıma gelen yöntem, TMemoryStream'in ilk birkaç byte'ını (mesela 4 byte) masaüstü görüntü uzunluğu için kullanın. Ardından masaüstü görüntüsü gelecek. Bundan sonraki kısma da Rapor'u eklersiniz.
Yani sizin TMemoryStream içeriği: Header + Masaüstü Götüntüsü + Rapor şeklinde olsun
Mesajı aldığınızda ilk olarak baştaki 4 byte'a bakıp masaüstü görüntüsünü alın, geriye kalan data'lar da Rapor kısmıdır.
Kısacası kendinize özgü bir mesajlaşma protokolü geliştirin. Header kısmını biraz daha geniş tutarsanı ileride farklı amaçlarda mesaj kullanmak gerektiğinde işiniz kolaylaşır. Mesela Header içinde bir Mesaj ID olabilir...
İlk aklıma gelen yöntem, TMemoryStream'in ilk birkaç byte'ını (mesela 4 byte) masaüstü görüntü uzunluğu için kullanın. Ardından masaüstü görüntüsü gelecek. Bundan sonraki kısma da Rapor'u eklersiniz.
Yani sizin TMemoryStream içeriği: Header + Masaüstü Götüntüsü + Rapor şeklinde olsun
Mesajı aldığınızda ilk olarak baştaki 4 byte'a bakıp masaüstü görüntüsünü alın, geriye kalan data'lar da Rapor kısmıdır.
Kısacası kendinize özgü bir mesajlaşma protokolü geliştirin. Header kısmını biraz daha geniş tutarsanı ileride farklı amaçlarda mesaj kullanmak gerektiğinde işiniz kolaylaşır. Mesela Header içinde bir Mesaj ID olabilir...
There's no place like 127.0.0.1
Re: TXMLDocument kullanımı hk.
Evet benim de aklıma geldi ve uygulamasını yaptım ancak her 10 ms de bir masa üstü görüsü gönderiyor bu zaten fazlasıyla işlemci gücü tüketiyor bir de MemoryStream'a raporu ekle sonra serverde parshe et hem görüntü hızı düşüyor hem fazla cpu tüketiyor hem de hatayaaçık, bunu xml ile yapmak bana daha avantaj sağlayacağana inanıyorum. Yani anlayacağın çok yöntem denedim.
Temel sıkıntım; Masa üstü bağlantida
1. Cpu çok kullanılıyor %30
2. Ağ çok meşgul oluyor 30 MB.
3. Hem TMemoryStream hem de TStrings kullanmam lazım
4. Ayrıca masa üstü img transferi için ayrı bir porttan bağlantı da denedim oldu fakat başka sıkıntılar oldu.
5. vs. vs.
TXMLDocument hk. Yardimcı olursanız sevinirim.
Temel sıkıntım; Masa üstü bağlantida
1. Cpu çok kullanılıyor %30
2. Ağ çok meşgul oluyor 30 MB.
3. Hem TMemoryStream hem de TStrings kullanmam lazım
4. Ayrıca masa üstü img transferi için ayrı bir porttan bağlantı da denedim oldu fakat başka sıkıntılar oldu.
5. vs. vs.
TXMLDocument hk. Yardimcı olursanız sevinirim.
Re: TXMLDocument kullanımı hk.
Aslında 10 ms'lik bir aralıkta ekran görüntüsünü alıp, bir yerden bir yere iletiyorsanız bahse konu 1 ve 2nci maddelerdeki sıkıntıları elbette yaşarsınız. İster XML ile ister stream ile ister json formatında gönderin datayı değişen pek bir şey olmaz kanaatimce.
Sizin yerinizde olsa idim öncelikle bu zaman aralığını biraz daha makul bir seviyeye çekerdim. Ardından ekran capture eden kodunuzu bir thread olarak kodlardım ve herşeyden önemlisi nasıl yapılır bir fikrim yok ama, ekranda sadece değişen alanları göndermenin bir yolunu bulurdum. Ayrıca; 32 bit yada 24 bit değil 8 bitlik monochrome bir bitmap transferi epey bir hızlanmanıza vesile olurdu. Ayrıca TDecompressionStream ile mevcut bitmap'ı sıkıştırabilirsiniz de. Aslında pek çok alternatif var yapabileceğiniz, ama isteğiniz az CPU tüketimi ve optimum network trafiği ise bazı şeylerden feragat etmeniz gerekecektir.
Sizin yerinizde olsa idim öncelikle bu zaman aralığını biraz daha makul bir seviyeye çekerdim. Ardından ekran capture eden kodunuzu bir thread olarak kodlardım ve herşeyden önemlisi nasıl yapılır bir fikrim yok ama, ekranda sadece değişen alanları göndermenin bir yolunu bulurdum. Ayrıca; 32 bit yada 24 bit değil 8 bitlik monochrome bir bitmap transferi epey bir hızlanmanıza vesile olurdu. Ayrıca TDecompressionStream ile mevcut bitmap'ı sıkıştırabilirsiniz de. Aslında pek çok alternatif var yapabileceğiniz, ama isteğiniz az CPU tüketimi ve optimum network trafiği ise bazı şeylerden feragat etmeniz gerekecektir.
Re: TXMLDocument kullanımı hk.
Tuğrul Bey'in "zaman aralığında makul bir seviye" yaklaşıma ek olarak şunu önerebilirim. Akıcı bir ekran görüntüsü için 24 frame/sn yeterlidir. Dolayısıyla 1000ms/24 = ~40ms de bir ekran görüntüsünü almanız problemsiz bir akıcılık sağlayacaktır. 40ms üzerinde yapılan tüm örneklemelerde, görüntüde hafif kopukluklar yaşanır.
Veri sıkıştırma tekniklerine ek olarak veri-zaman uzayından veri-frekans uzayına geçişi de tavsiye edebilirim. Örnek olarak 1024*768 elemana sahip pixel kümesini FFT (Fast Fourier Transform) ile çok çok daha az elemana sahip bir frekans kümesine dönüştürebilirsiniz. Ayrıca iletilecek veri boyunu da ciddi oranda küçülteceksiniz. Mesela bir pixel i 4-byte ile temsil ediyorken, bir frekansı 2-byte [yalnızca örnek veriyorum; 1-byte ya da 3-byte da olabilir] ile temsil edebileceksiniz.
Veri sıkıştırma tekniklerine ek olarak veri-zaman uzayından veri-frekans uzayına geçişi de tavsiye edebilirim. Örnek olarak 1024*768 elemana sahip pixel kümesini FFT (Fast Fourier Transform) ile çok çok daha az elemana sahip bir frekans kümesine dönüştürebilirsiniz. Ayrıca iletilecek veri boyunu da ciddi oranda küçülteceksiniz. Mesela bir pixel i 4-byte ile temsil ediyorken, bir frekansı 2-byte [yalnızca örnek veriyorum; 1-byte ya da 3-byte da olabilir] ile temsil edebileceksiniz.
Re: TXMLDocument kullanımı hk.
Tuğrul beyin ve The_aLiEn in tespitlerine katılıyorum.
Ancak bu masaüstü çalışma üzerinde çok çalıştım önerilerinizin bir çoğunu denedim.
10 ms aralıklar ile ekran görüntüsünü alsam bile ikinci işlem aralığı zaten 40 ms yi buluyor. Ekranın yakalanması ilmeç'in img eklenmesi MemoryStream'a yüklenmesi gönderilmesi vs. Bu durumda gönderilmese bile CPU zaten %30'u buluyor. Bunu Thread içinde yapıyorum hatta MultiThread Class yazdım.
Sıkıştırma yöntemlerin bir çoğunu da denedim jpg, zlib vs. ne kadar sıkıştırma işlemi yaparsam işlemciyi o kadar yoruyorum en son img sıkıştırmamaya kara verdim ve TIdCompressionIntercept de karar kıldım hem sorunsuz hem istediğim seviyede sıkıştırma seçeneğini kullanabiliyorum (1..9). Ayrıca Serverde Bitmap işlemleri daha başarılı.
Tuğrul beyin dediği gibi değişen yerlerin gönderilmesi daha yerinde olur.
Algoritmayı şöyle düşündüm: ilk önce Ekran yakalama işlemi yapılır ve servere gönderilir ve temp değişkeninde de tutulur ikinci yakalama yapılır ve yeni img 2 Kbyte aralıklar ile karşılaştırılır eğer farklıysa servere 2 kbyte data ve o dilimin indexi gönderilir sever gereğini yapar. Karşılaştırma EOF'a kadar yapılır ve yeni img temp değişkeninde yeniden tutulup ilşlem yenilenir.
Bu durumda ağ her defasında image'ın tamamıyla değil 2 Kbyte'ın gönderilmesi ile meşgul olur. Tabi bu Thread içinde yapılması gerekir hatta yakalama ve karşılaştırma -gönderme ayrı ayrı Thread ile yapılması yerinde olur.
İşte bu durumdan dolayı doğru bileşen TXMLDocument olacağını düşünüyorum şöyleki Rapor+(Data info)+Data. Ancak Node'a Data yüklenebilir mi ve nasıl?
Bir çözüm Bulamazsam Rapor ve Data info için TStringList kullanacağım MemoryStreama yükleyeceğim Data nın başladığı yere bir işret koyup Datayı da MemoryStrema ekleyip göndereceğim.Bu işlemin daha yorucu olduğu görülüyor.
Ve başka öneri veya yönlendirmelerinizi bekliyorum
Ancak bu masaüstü çalışma üzerinde çok çalıştım önerilerinizin bir çoğunu denedim.
10 ms aralıklar ile ekran görüntüsünü alsam bile ikinci işlem aralığı zaten 40 ms yi buluyor. Ekranın yakalanması ilmeç'in img eklenmesi MemoryStream'a yüklenmesi gönderilmesi vs. Bu durumda gönderilmese bile CPU zaten %30'u buluyor. Bunu Thread içinde yapıyorum hatta MultiThread Class yazdım.
Sıkıştırma yöntemlerin bir çoğunu da denedim jpg, zlib vs. ne kadar sıkıştırma işlemi yaparsam işlemciyi o kadar yoruyorum en son img sıkıştırmamaya kara verdim ve TIdCompressionIntercept de karar kıldım hem sorunsuz hem istediğim seviyede sıkıştırma seçeneğini kullanabiliyorum (1..9). Ayrıca Serverde Bitmap işlemleri daha başarılı.
Tuğrul beyin dediği gibi değişen yerlerin gönderilmesi daha yerinde olur.
Algoritmayı şöyle düşündüm: ilk önce Ekran yakalama işlemi yapılır ve servere gönderilir ve temp değişkeninde de tutulur ikinci yakalama yapılır ve yeni img 2 Kbyte aralıklar ile karşılaştırılır eğer farklıysa servere 2 kbyte data ve o dilimin indexi gönderilir sever gereğini yapar. Karşılaştırma EOF'a kadar yapılır ve yeni img temp değişkeninde yeniden tutulup ilşlem yenilenir.
Bu durumda ağ her defasında image'ın tamamıyla değil 2 Kbyte'ın gönderilmesi ile meşgul olur. Tabi bu Thread içinde yapılması gerekir hatta yakalama ve karşılaştırma -gönderme ayrı ayrı Thread ile yapılması yerinde olur.
İşte bu durumdan dolayı doğru bileşen TXMLDocument olacağını düşünüyorum şöyleki Rapor+(Data info)+Data. Ancak Node'a Data yüklenebilir mi ve nasıl?
Bir çözüm Bulamazsam Rapor ve Data info için TStringList kullanacağım MemoryStreama yükleyeceğim Data nın başladığı yere bir işret koyup Datayı da MemoryStrema ekleyip göndereceğim.
Kod: Tümünü seç
void __fastcall TBaglanti::SendCommand(const String command, String param, String value, vs.....)
{
StrLst->Clear();
StrLst->Values[MACHID] = svrid; // Server Machine ID
StrLst->Values[COMMAND] = command; // Command
StrLst->Values[PARAM] = param; // Parameter
StrLst->Values[VALUE] = value; // value
//Rapor ve diğer işlemler
//..
//Data info...
//Data başlangıç işaretlenmesi
//StrLst'in MemoryStream a yüklenmesi
// En son MemoeryStream'a Datanın yüklenmsi
// Stream'ın gönderilmesi
}
//---------------------------------------------------------------------------
Ve başka öneri veya yönlendirmelerinizi bekliyorum
Re: TXMLDocument kullanımı hk.
Ben Delphi XE kullanıyorum. EncdDecd.pas içerisinde EncodeBase64 adında bir fonksiyon var. Bu fonksiyon yardımı ile TMemoryStream'i stringe çevirebiliyorsunuz. Dolayısıyla bu sayede tüm verilerinizi TStringList'e atabilirsiniz.
gibi birşey...
Ama siz illa TXMLDocument ile yapmak istiyorsanız XML'e Node eklerken ntCData kullanmalısınız.
Kod: Tümünü seç
StrLst->Values[IMAGE] = EncodeBase64(MemoryStream.Memory, MemoryStream.Size);
Ama siz illa TXMLDocument ile yapmak istiyorsanız XML'e Node eklerken ntCData kullanmalısınız.
Kod: Tümünü seç
YeniNode := XMLDoc.CreateNode('Resim', ntCData);
YeniNode.Text := EncodeBase64(MemoryStream.Memory, MemoryStream.Size);
There's no place like 127.0.0.1
Re: TXMLDocument kullanımı hk.
Sanıyorum CPU kullanım yüzdesinden şikayet ettiğiniz kısım server tarafındaki kısım. Yani, ekran görüntüsünü capture ettiğiniz yer. Server uygulamanız; bir Server işletim sistemi üzerinde mi çalışıyor bilmiyorum ama eğer öyle ise zamanlama yine sıkıntılı görünüyor. İşletim sistemi üzerinde quanta zamanı olarak tabir edilen zaman dilimi server işletim sistemlerinde çok daha uzun bir zamandır. Genellikle server işletim sistemlerinde, GUI threadlerine değil background thread'lere öncelik verilir ve onlar daha sık zamanlanır. Client işletim sistemlerinde ise bunun tam tersidir.
Ama her ne olursa olsun, 10 ms. gerçekten kısa bir zamandır ve bir thread'in bu kadar kısa bir quanta zamanında schedule edilmesi reel olarak pek mümkün değildir. RISC vb. gerçek zamanlı işletim sistemlerinde ancak bu kadar katî bir zamanlamaya sahip olabilirsiniz.
Eğer ekran görüntüsü alan kodunuz bir thread içinde çalışıyor ise, bu thread'in zamanlamasını biraz daha uzun tutmak isteyebilirsiniz. Ayrıca; bu thread'iniz sürekli çalışan bir thread ise, başka thread'leri de zamanlayabilmesi için işletim sistemine bir fırsat sunmak adına, Sleep(0) çağrımını bir yerde geçmeniz yerinde olacaktır.
Belki de thread priority'nizi real time'a çekmek de isteyebilirsiniz. Tüm bunlara rağmen, capture edeceğiniz ekran görüntüsünün kalitesi üzerinde bir feragat yapmayacaksanız, yine de network üzerinden göndermek isteyeceğiniz veri boyutu ciddi olacaktır.
Bir önceki mesajımda dediğim gibi; sizin yerinizde olsam veriyi sıkıştırarak gönderir ve sadece değişen kısımları anlamaya çalışırdım. Ancak burada size chain of responsibility tasarım kalıbını kullanmanızı öneririm. Bu kalıp sayesinde, öncelikle ekran görüntüsünü çeker, sonra sıkıştırır, sonra yapmak istiyorsanız fark hesaplar ardından da client tarafa bu bilgiyi istediğiniz herhangi bir formatta gönderebilirsiniz. Bu sayede; sizin gönderme işleminiz henüz tamamlanmadan mevcut thread'inizin; bir başka görüntüyü iletmesi ve çakışma olabilme ihtimalinden de kurtulmuş olurdunuz.
Ama her ne olursa olsun, 10 ms. gerçekten kısa bir zamandır ve bir thread'in bu kadar kısa bir quanta zamanında schedule edilmesi reel olarak pek mümkün değildir. RISC vb. gerçek zamanlı işletim sistemlerinde ancak bu kadar katî bir zamanlamaya sahip olabilirsiniz.
Eğer ekran görüntüsü alan kodunuz bir thread içinde çalışıyor ise, bu thread'in zamanlamasını biraz daha uzun tutmak isteyebilirsiniz. Ayrıca; bu thread'iniz sürekli çalışan bir thread ise, başka thread'leri de zamanlayabilmesi için işletim sistemine bir fırsat sunmak adına, Sleep(0) çağrımını bir yerde geçmeniz yerinde olacaktır.
Belki de thread priority'nizi real time'a çekmek de isteyebilirsiniz. Tüm bunlara rağmen, capture edeceğiniz ekran görüntüsünün kalitesi üzerinde bir feragat yapmayacaksanız, yine de network üzerinden göndermek isteyeceğiniz veri boyutu ciddi olacaktır.
Bir önceki mesajımda dediğim gibi; sizin yerinizde olsam veriyi sıkıştırarak gönderir ve sadece değişen kısımları anlamaya çalışırdım. Ancak burada size chain of responsibility tasarım kalıbını kullanmanızı öneririm. Bu kalıp sayesinde, öncelikle ekran görüntüsünü çeker, sonra sıkıştırır, sonra yapmak istiyorsanız fark hesaplar ardından da client tarafa bu bilgiyi istediğiniz herhangi bir formatta gönderebilirsiniz. Bu sayede; sizin gönderme işleminiz henüz tamamlanmadan mevcut thread'inizin; bir başka görüntüyü iletmesi ve çakışma olabilme ihtimalinden de kurtulmuş olurdunuz.
Re: TXMLDocument kullanımı hk.
Teşekkürler dostum bu yöntem işime yaramaz, TBitmap MemoryStream'a yükle streamdan EncodeBase64 bileşenine yükle ondan TStringList e ya da TXMLDocument e yükleyip göndermek fazladan işlem yükü getirir.SimaWB yazdı:Ben Delphi XE kullanıyorum. EncdDecd.pas içerisinde EncodeBase64 adında bir fonksiyon var. Bu fonksiyon yardımı ile TMemoryStream'i stringe çevirebiliyorsunuz. Dolayısıyla bu sayede tüm verilerinizi TStringList'e atabilirsiniz.gibi birşey...Kod: Tümünü seç
StrLst->Values[IMAGE] = EncodeBase64(MemoryStream.Memory, MemoryStream.Size);
Ama siz illa TXMLDocument ile yapmak istiyorsanız XML'e Node eklerken ntCData kullanmalısınız.Kod: Tümünü seç
YeniNode := XMLDoc.CreateNode('Resim', ntCData); YeniNode.Text := EncodeBase64(MemoryStream.Memory, MemoryStream.Size);
Benim istediğim TBitmap nesnesinde olan img'ı bir node'a yülebilme imkanı bulmak yoksa bunda kasmak gereksiz.
Tuğrul bey işlemci yükününün sorun olduğu taraf Client(terminal) ScreenCapture yapıp paketleyip server'e gönderiyor. Bunu Thread fonksiyonumda dögü ile tekrarlı olarak yapıp server'e gönderiyorum her döngü sonunda Sleep(10); ile 10ms ve bekletiyorum. Ama önce server'e TStrings ile servere komut paketi gönderiyorum, bunlar ilmeçin tipi kordinatları ve screen göndereceğimi bildiriyorum serverde komutları uygulayıp TMemoryStream bekliyor streamdaki datayi forma çiziyor. O yüzden hem komut ve ilaveten rapor hem datayı birlikte gonderebileceğim yöntem aramaktayım.
chain of responsibility yöntemini nerden inceleybilirim. Link varsa sevinirim Delphi örneği de olabilir okuyabilirim.
Re: TXMLDocument kullanımı hk.
İkinci kod örneği tam da bunun içindi zaten.SHURZAN yazdı: Benim istediğim TBitmap nesnesinde olan img'ı bir node'a yülebilme imkanı bulmak yoksa bunda kasmak gereksiz.
Kod: Tümünü seç
YeniNode := XMLDoc.CreateNode('Resim', ntCData);
YeniNode.Text := EncodeBase64(MemoryStream.Memory, MemoryStream.Size);
XML içerisine bir resmi koymak istiyorsanız önce onu Encode etmeli, okurken de Decode etmelisiniz. XML dosyası text tabanlı olduğu için bunu başka türlü yapamazsınız.
Ayrıca; daha önce de yazdığım gibi, XML'e resim eklemek için Node eklerken tipi CDATA olmak zorundadır. Node'u CDATA olarak tanımladığımızda XML okunurken CDATA içerisindeki veri text olarak yorumlanmasın demiş oluruz.
Bence sizin probleminizin çözümü TXMLDocument değil ama kullanmak isterseniz yukarıda bahsettiğim şekilde yapmak zorundasınız.
There's no place like 127.0.0.1
Re: TXMLDocument kullanımı hk.
Chain of Responsibility için aşağıdaki linkler faydalı olabilir:
http://delphipatterns.blog.com/2011/03/ ... nsibility/
http://www.dofactory.com/Patterns/PatternChain.aspx
http://www.buraksenyurt.com/post/Tasarc ... ility.aspx
http://delphipatterns.blog.com/2011/03/ ... nsibility/
http://www.dofactory.com/Patterns/PatternChain.aspx
http://www.buraksenyurt.com/post/Tasarc ... ility.aspx
Re: TXMLDocument kullanımı hk.
Sağ ol Tuğrulcuğum verdiğin linkleri inceledim. Bu bizim C++ da Bağlı liste mantığına benzer bir çalışma sanırım.
Sanırım daha araştırma yapmalıyım.
Yine de önerilerinizi bekliyorum
Sanırım daha araştırma yapmalıyım.
Yine de önerilerinizi bekliyorum
- sabanakman
- Kıdemli Üye
- Mesajlar: 3081
- Kayıt: 17 Nis 2006 08:11
- Konum: Ah bi Antalya olaydı keşke (Ankara)
Re: TXMLDocument kullanımı hk.
İyi günler. Bu yöntem için iki değişik yol önerebilirim. TStrings bilgiyi de SaveToStream ile tıpkı resim bilgisinde olduğu gibi binary kayıt etmek mümkün ve artık iş birden fazla binary bilgiyi tek bir Stream veya XML içerisine yerleştirmeye kalmaktadır. Örnekler delphi kodu üzerinden olacak ama en azından C++ Builder tarafına örnek yol gösterici olabilir.
1-) XML düğümü için String bilgi elde etme ve bu String'i geri dönüştürme :
Bir zamanlar SQL Server veritabanı Img tipli alanı için SQL script'i oluşturan ve bu script değeri tekrar Binary yapan iki fonksiyon örneğim vardı. Burada bulunan BinaryToSQL fonksiyonu ile hem TStrings'in SaveToStream ile kayıt edilen Binary bilgisini, hem de Stream türünde tutulabilen başka türden (resim v.s. gibi) bilgilerin String karşılıklarını elde etmek mümkündür ve bu String bilgi daha sonra SQLToBinary fonksiyonuyla tekrar Stream ortama çevrildikten sonra ilgili bilgi türüne göre bu Stream'den geri yüklenebilir. Bu XML düğümlerine yazılacak bilgi olarak kullanılabilir bir yöntemdir.
2-) Özelleştirimiş TStream yapısı :
Bir de direkt tek Stream içine birden fazla veriyi türlerine göre yazabilme imkanı da bulunmaktadır. Bu ise VCL kütüphanesine özel sınıflar olan TWriter ve TReader ile mümkün olabilir. Bu sınıflar TStream üzerine bizim belirlediğimiz yapıda verileri yazmaya ve okumaya yarar. Burada dikkat edilmesi gereken en önemli husus, TWriter sınıfı, create edilirken parametrede verilen miktar kadar Buffer oluşturur ve işimiz bittiğinde burada bir miktar bilgi, Stream'e yazılmamış halde kalabilir. Buffer içinde kalan son bilginin de Stream'e yazılabilmesi için muhakkak .Free ile yok etmek gerekmektedir (maksat private metot olan WriteBuffer metodunu çağırmaktır
). Aşağıda bulunan örnek, Memo1 ve Image1 içinde bulunan bilgilerin her ikisini de (boyutunu dikkate alarak ) Mem isimli TMemoryStream içine (TWriter) ile yazıldıktan sonra (TReader) sınıfı ile bu iki ayrı Binary veriyi boyutunu dikkate alarak tekrar okuyup Memo2 ve Image2 içerisine yüklemektedir.
Daha sonra zamanla artabilecek parametre yapısına sahip uygulamalar için basit bir tavsiyem olacak. Böyle uygulamalarda tek bir Stream parametre kullanılabilir ve o zaman TWriter ve TReader sınıfları ile çalışılmalı. Bu sınıflar incelendiği takdirde, diğer tipler için de uygun metotları bulunmaktadır (Float, Single, Double, Date, v.s.). Bu yüzden sonradan eklenecek parametreler, Stream'e ilave edilme imkanı olabilir ve böylece uygulamanın parametre yapısına hiç dokunmadan sonradan arttırılabilir parametre yapısına uygun hale gelebilir. Sunucusu güncel olan eski istemciler eklenen yeni parametrelerden habersiz olsa bile herhangi bir hata olmadan çalışma imkanına kavuşacaktır (son tavsiyeyi basit bir makalede örnekleştirmek gerekiyor sanırım
). İyi çalışmalar.
1-) XML düğümü için String bilgi elde etme ve bu String'i geri dönüştürme :
Bir zamanlar SQL Server veritabanı Img tipli alanı için SQL script'i oluşturan ve bu script değeri tekrar Binary yapan iki fonksiyon örneğim vardı. Burada bulunan BinaryToSQL fonksiyonu ile hem TStrings'in SaveToStream ile kayıt edilen Binary bilgisini, hem de Stream türünde tutulabilen başka türden (resim v.s. gibi) bilgilerin String karşılıklarını elde etmek mümkündür ve bu String bilgi daha sonra SQLToBinary fonksiyonuyla tekrar Stream ortama çevrildikten sonra ilgili bilgi türüne göre bu Stream'den geri yüklenebilir. Bu XML düğümlerine yazılacak bilgi olarak kullanılabilir bir yöntemdir.
2-) Özelleştirimiş TStream yapısı :
Bir de direkt tek Stream içine birden fazla veriyi türlerine göre yazabilme imkanı da bulunmaktadır. Bu ise VCL kütüphanesine özel sınıflar olan TWriter ve TReader ile mümkün olabilir. Bu sınıflar TStream üzerine bizim belirlediğimiz yapıda verileri yazmaya ve okumaya yarar. Burada dikkat edilmesi gereken en önemli husus, TWriter sınıfı, create edilirken parametrede verilen miktar kadar Buffer oluşturur ve işimiz bittiğinde burada bir miktar bilgi, Stream'e yazılmamış halde kalabilir. Buffer içinde kalan son bilginin de Stream'e yazılabilmesi için muhakkak .Free ile yok etmek gerekmektedir (maksat private metot olan WriteBuffer metodunu çağırmaktır

Kod: Tümünü seç
type
TForm1 = class(TForm)
Memo1: TMemo;
ListBox1: TListBox;
Image1: TImage;
Image2: TImage;
btnOku: TBitBtn;
btnYaz: TBitBtn;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btnOkuClick(Sender: TObject);
procedure btnYazClick(Sender: TObject);
private
{ Private declarations }
Mem:TMemoryStream;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var Oku:TReader; Yaz:TWriter; Tmp:TMemoryStream; i:Int64;
procedure TForm1.btnOkuClick(Sender: TObject);
begin
Mem.Clear;
Tmp:=TMemoryStream.Create;
Yaz:=TWriter.Create(Mem,1024);
Yaz.WriteListBegin;
//Tmp.Clear;
Memo1.Lines.SaveToStream(Tmp); //1. memory
Yaz.WriteInteger(Tmp.Size);
Yaz.Write(Tmp.Memory^,Tmp.Size);
Tmp.Clear; //2. memory
Image1.Picture.Bitmap.SaveToStream(Tmp);
Yaz.WriteInteger(Tmp.Size);
Yaz.Write(Tmp.Memory^,Tmp.Size);
Yaz.WriteListEnd;
Yaz.Free;//free önemli, 1024 lük buffer da kalan son bilgiler de stream e bu anda yazılır
Tmp.Free;
end;
procedure TForm1.btnYazClick(Sender: TObject);
begin
Tmp:=TMemoryStream.Create;
//Tmp.Clear;
Mem.Position:=0;//okunacak bilgiler
Oku:=TReader.Create(Mem,1024);
Oku.ReadListBegin;
i:=Oku.ReadInt64;
Tmp.Size:=i;
Oku.Read(Tmp.Memory^,i);//1. sırada memo bilgisi
Tmp.Position:=0;
ListBox1.Items.LoadFromStream(Tmp);
i:=Oku.ReadInt64;
Tmp.Size:=i;
Oku.Read(Tmp.Memory^,i);//2. sırada resim bilgisi
Tmp.Position:=0;
Image2.Picture.Bitmap.LoadFromStream(Tmp);
Oku.ReadListEnd;
Oku.Free;
Tmp.Free;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Mem:=TMemoryStream.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Mem.Free;
end;
end.

Şaban Şahin AKMAN
_________________
Derin olan kuyu değil kısa olan iptir. - .
_________________
Derin olan kuyu değil kısa olan iptir. - .
Re: TXMLDocument kullanımı hk.
Teşekkürler Şaban bey;
Cevap biraz geç oldu kusura bakma.
Öneriniz çalışmam için yerinde ve uygulanabilir.
TWriter Mem adlı MemoryStream'a Link alıp yazıyor böylece benim MemorySream'ı işaretleyip veriyi yazmak ve okumak için uğramam gerekmiyor. İstediğim kadar veri yükleyip gönderebileceğim, başka bir yükleyiciye gerek kalmadı XMLDocument vs. MemoryStreamı veriyle doldurduktan sonra gönderip Serverd'e TReader ile okuyabileceğim. Çok işime yaradı Teşekkürler.
Ancak şu konuda da gene bir yardıma ihtiyacım var.
Sen TBitmap'ı ikinci bir MemoryStream(Tmp)Yükleyip MemoryStream'ın Memory'sinden Write ediyorsun.
Sormak istediğim TBitmap içeriği Doğrudan Write edilemez mi yani şunu denedim TBitmap içeriğinden başka bir şeyler yazıyor bitmap içeriği değil. olmuyor.
TBitmap içeriğinde doğrudan erişmenin yolu nedir ki bende içeriğini TWriter yardımı ile MemoryStream'a yazabileyim?
Saygılar
Cevap biraz geç oldu kusura bakma.
Öneriniz çalışmam için yerinde ve uygulanabilir.
TWriter Mem adlı MemoryStream'a Link alıp yazıyor böylece benim MemorySream'ı işaretleyip veriyi yazmak ve okumak için uğramam gerekmiyor. İstediğim kadar veri yükleyip gönderebileceğim, başka bir yükleyiciye gerek kalmadı XMLDocument vs. MemoryStreamı veriyle doldurduktan sonra gönderip Serverd'e TReader ile okuyabileceğim. Çok işime yaradı Teşekkürler.
Ancak şu konuda da gene bir yardıma ihtiyacım var.
Sen TBitmap'ı ikinci bir MemoryStream(Tmp)
Kod: Tümünü seç
Image1.Picture.Bitmap.SaveToStream(Tmp);
Yaz.WriteInteger(Tmp.Size);
Yaz.Write(Tmp.Memory^,Tmp.Size);
Sormak istediğim TBitmap içeriği Doğrudan Write edilemez mi yani şunu denedim TBitmap içeriğinden başka bir şeyler yazıyor bitmap içeriği değil.
Kod: Tümünü seç
Yaz.WriteInteger(Image1.Picture.Bitmap);
TBitmap içeriğinde doğrudan erişmenin yolu nedir ki bende içeriğini TWriter yardımı ile MemoryStream'a yazabileyim?
Saygılar
Re: TXMLDocument kullanımı hk.
Buna da ben cevap vereyim; TBitmap; resim özelliklerinin ve canvas gibi yüzeye ulaşmanın yolladırının barındırıldığı bir yapı/sınıftır. Veri transfer işlemlerinde bu propertylerden arındırılmış binary bir dizi haline yani stream'e dönüştürmek şarttır.SHURZAN yazdı:Ancak şu konuda da gene bir yardıma ihtiyacım var.
Sen TBitmap'ı ikinci bir MemoryStream(Tmp)Yükleyip MemoryStream'ın Memory'sinden Write ediyorsun.Kod: Tümünü seç
Image1.Picture.Bitmap.SaveToStream(Tmp); Yaz.WriteInteger(Tmp.Size); Yaz.Write(Tmp.Memory^,Tmp.Size);
Sormak istediğim TBitmap içeriği Doğrudan Write edilemez mi yani şunu denedim TBitmap içeriğinden başka bir şeyler yazıyor bitmap içeriği değil.olmuyor.Kod: Tümünü seç
Yaz.WriteInteger(Image1.Picture.Bitmap);
TBitmap içeriğinde doğrudan erişmenin yolu nedir ki bende içeriğini TWriter yardımı ile MemoryStream'a yazabileyim?
Saygılar
- Sanki önce bir streame dönüşümü ardından da başka bir streame aktarım yapılması gibi bir görüntü yakalamışsınız. TWriter sandığınız şekilde bir stream değildir.
[b]bkz. Embarcadereo[/b] yazdı: Description
TWriter is a specialized filer object that writes data to its associated stream.
TWriter is used internally by the component streaming system to write information associated with a component, such as published properties of components or custom property data, to a stream. TWriter handles the mechanics of writing the data associated with a component to a stream. It is the writer object, rather than the stream, that is responsible for handling the complexities of streaming components. These include methods for:
Writing different kinds of items to the associated stream.
Writing property deltas used for streaming inherited forms and properties with default values.
Writing nested groups of items or collections to the stream.
Other methods and properties of TWriter are used for interacting with stream and component objects.
Do not directly create writer objects. Writers are automatically created in stream object methods or in global routines that initiate the streaming process. These include:
The global routine ObjectTextToBinary procedure, which directly creates a writer.
The global WriteComponentResFile function, which creates a file stream that creates a writer.
The WriteDescendent method of TStream, which creates a writer object.
Once the streaming process is underway, programs do not need to directly manipulate writer objects. The interaction between the writer, component, and stream objects happens automatically in methods of these objects that make calls to each other.