Java'da Struct benzeri yapı kullanımı

Başlatan yamak, 02 Eylül 2015, 10:02:57

yamak

Merhaba arkadaşlar,
Java'da gelen serial data'yı C'deki gibi bir struct'a cast edip parse etmenin bi yolu var mı?Bildiğim kadarıyla java'da structure yok.Bu tip durumlarda java'da nasıl bir yol izleniyor?

ercan_t

merhaba,

javada struct yok sanırsam herşey class

class ogrenci
{
    public String ad;
    public String soyad; 
    public int    no;
};
gibi

ama dataları seri bir buffera koyup irdeleyebilirsin
string ad;
string soyad;
int no;

ByteBuffer data = ByteBuffer.allocate(10);
....
data .order(ByteOrder.LITTLE_ENDIAN);
data .put(0, ad);
data .put(4, no);
byte[] rawBytes = data .array();
...
senddata...

yamak

Hocam structure'daki gibi isim isim erişmek istiyoru.
Örneğin;
ad=serialdata.ad;
soyad=serialdata.soyad;
no=serialdata.no;

gibi.
Buna benzer bişey yapamaz mıyım javada?

mufitsozen

Alıntı yapılan: yamak - 02 Eylül 2015, 11:12:58
Hocam structure'daki gibi isim isim erişmek istiyoru.
Örneğin;
ad=serialdata.ad;
soyad=serialdata.soyad;
no=serialdata.no;

gibi.
Buna benzer bişey yapamaz mıyım javada?

hem javada hemde c++, python vbde bu sekilde yazabilirsin.  Ama Cde kullandigim bir 'struct'a javada erismek istiyorum dersen, o baska bir konu ve preon kullanmak gibi cozumler var (yada JNI yada....)
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

yamak

Hocam amacım bi array'i ya da bi memory alanını struct benzeri bir yapıya cast edip o alandaki verilere isim isim erişmek bunu nasıl yapabilirim.

AsHeS

Alıntı yapılan: yamak - 03 Eylül 2015, 08:28:46
Hocam amacım bi array'i ya da bi memory alanını struct benzeri bir yapıya cast edip o alandaki verilere isim isim erişmek bunu nasıl yapabilirim.
Java'da hard memory işlemleri mevcut değil(gideyim x adresine erişeyim tarzında) bu bahsettiğiniz çok mümkün değil ancak tanımladığınız class taki set, get methodları ile çözüme yaklaşılabilir ancak.

mufitsozen

Alıntı yapılan: yamak - 03 Eylül 2015, 08:28:46
Hocam amacım bi array'i ya da bi memory alanını struct benzeri bir yapıya cast edip o alandaki verilere isim isim erişmek bunu nasıl yapabilirim.

sayin @yamak, preon, https://github.com/raydac/java-binary-block-parser, yada JNI inceleyin demistim. Ucude sizin sorununuza care olur.

Daha fazlasi icin sizin caba gostermeniz gerekiyor.
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

yamak

Tamam hocam bi inceleyeyim.Teşekkür ederim.

elektronart

soruda bir tuhaflık var,
serial data dediğin şey bir struct olamaz zaten. Kendisi bir byte array olmalı.
Eğer ad için sabit alan, soyad için sabit alan ayırdım diyorsan o zaman serialdata gibi bir struct a cast edebilirsin. Muhtemelen serialdata struct şöyle bir yapıda;
byte ad[12]
byte soyad[16]
byte no[11]
Ama bu verimsiz bir yöntem olur. Eğer ad 3 harfli ise kalan 9 luk bölüm boş kalacak.
Örneğin pakette 0x01 adın, 0x02 soyadın, 0x03 de nonun öneki olsa, 0x01 ve 0x02 arasında kalan bytelar ad, 0x02 ve 0x03 arasındakiler de soyad olur. Bu şekilde ayıran bir kodla ad ve soyadı paketten ayırabilirsin. Ayırdığın bu ad ve soyadı da istediğin dilde istediğin değişkene atayabilirsin.
Açık Elektronik

yamak

#9
Soruda tuhaflık yok.C de şu yaptığımı java da nasıl yapabilirim diye soruyorum:
#include <stdio.h>
#include <string.h>
unsigned char serialData[]={'1','9','2','.','1','6','8','.','2','.','1',0,0,0,0,0,'v','o','d','a','f','o','n','e',0,0,'4','0','0','1',0};
#pragma pack(push,1)
typedef struct
{
    unsigned char ip[16];
    unsigned char apnName[10];
    unsigned char portNo[5];
}ConfigFrame;
#pragma pack(pop)
int main(void)
{
    ConfigFrame* configFrame;
    configFrame=(ConfigFrame*)serialData;
    printf("IP No:%s\n",configFrame->ip);
    printf("APN Name:%s\n",configFrame->apnName);
    printf("Port Number:%s\n",configFrame->portNo);

}

Ayrıca tüm iletişim sabit uzunlukta.Atıyorum yukardaki örneğe göre konuşursak her zaman 31 byte'lık bir data geliyo.Gelen data nın hepsini zaten alıyorum.Neden verimsizlik olsun.

elektronart

Kızmana gerek yok, yardımcı olmaya çalışıyorum, tabi istiyorsan.
Sorunun içinde cevabın var zaten. İp den sonra 5 tane, apnden sonra 2 tane porttan sonra da 1 tane 0 var. İp adresi ve apne bağlı olarak bunların sayısı artabilir de. Paketi header ile düzenlediğinde bu fazlalıklara gerek kalmaz.
Bu headerları ayıtladıktan sonra configframei olduğu gibi cast etmeyip parça parça eşitleyebirsin zaten kullanırken öyle kullanıyorsun.
Cfgfrm->ip = serbufparser(0x01, 0x02) olsa, iki header arasını sana verse
Cfgfrm->apn=serbufparser(0x02, 0x03) mesela.
Açık Elektronik

yamak

#11
Hocam kızdığım falan yok. O şekilde parse edebileceğimi biliyorum zaten. Ama bu frame çok küçük bi frame. Bu 100 lerce bytelık 10 larca elemanlı bi frame olduğunda senin bahsettiğin yöntem efektif olmuyo.Örneğin frame yapısını değiştirip araya bir iki eleman eklendiğinde o zaman bütün ofsetlerin tek tek değişmesi gerekiyo. Ya da seninki gibi delimeter koyarsak her bir elaman için ayrı delimeter koymak ve algoritmayı ona göre değiştirmek gerekiyo hem koyulan delimeter lar frame içinde de olabilir.Örneğin 0x02 ya da 0x03 frame içinde de olabilir, o zaman da parser saçmalayabilir.Ama benim bahsettiğim yöntemde sadece struct ı değiştirmek yeterli. Ayrıca

Cfgfrm->ip = serbufparser(0x01, 0x02)
Cfgfrm->apn=serbufparser(0x02, 0x03)

satırlarında ne demek istediğini anlamadım?Zaten senin yöntemle parse ettiğimde elemanları tekrar struct a doldurmamın ne anlamı var?

elektronart

Yaklaşım meselesi. Bana da sorarsan 31 karakterde 8 karakter boşa harcamak verimsiz, 100lü bir bufferda kimbilir kaç olur. Bu yöntem aklınıza yatmadı anlaşılan, zorlamaya gerek yok. Bu yöntem tıkandığınız noktada kurtarıcı olabilecek bir yöntem o yüzden önermiştim. Delimiterlar paket içinde geçiyorsa ve yeterli gelmiyorsa uzunluk eklenir. TLV yapısıyla hiç sorunsuz gider. Ama dediğim gibi aklınıza yatmadıysa illa bu yöntem diye zorlamaya gerek yok. Aklınıza yatan ygun bir yöntem bulursunuz.

Cfgfrm->ip = serbufparser(0x01, 0x02) ile 01 ve 02 delimiterlarının arasındaki bölümü getiren bir fonksiyon uydurdum. 
Cfgfrm->ip = serbufparser(0x01) veya
Cfgfrm->ip = serbufparser_ip() de olabilir. Dediğim gibi uydurdum.
Açık Elektronik

yamak

#13
Hocam bu tarz sistemlerde genelikle sabit uzunlukta data gönderilir.Senin dediğin yöntemde hem fazladan delimeter lar eklenir hem de parse etmek için daha fazla işlem gücü gerekir, hem de sistem daha fazla karmaşıklaşır.Örneğin proje geliştirilirken gönderilecek frame'de proje bitimine kadar bir çok değişiklik olabilir.Bu tarz değişikliklerde parser ı yeniden düzenlemek zahmetli olur ve zaman kaybı yaratır.Özellikle client ve host tarafı farklı kişiler tarafından geliştiriliyorsa.Ayrıca bahsettiğim yöntem bana özgü değil çok fazla kullanılan bi yöntemdir.Ama sen o yönteme alıştıysan yapacak bişey yok.

Klein

struct yerine class tanımlamayı denedin mi?  Class ve struct yapıları benzeşir.  Java bilmediğim için nasıl cast edersin hiç fikrim yok.