25 Mart 2014 Salı

C++, Java, QT Stream sınıfları

Stream Sınıfları Hiyerarşisi
Konuyu C++ Streamleri başlıklı yazıya taşıdım.

ios_base ve locale

ios_base sınıfı template parametrelerine bağımlı olmayan ve tüm stream sınıflarının kullandığı ortak özellikleri içerir.

STL ile gelen IOStream kütüphanesinde kullanılan tüm streamlerin içinde bir locale nesnesi bulunur.
Bu durumu gösteren örnek bir şekli buradan aldım.

imbue() metodu kullanılarak stream'in kullandığı locale değiştirilebilir. Ancak When to Imbue a New Locale başlıklı yazıda yazıldığı gibi eğer stream buffer içinde veri varsa locale değiştirmemek gerekir.

Daha detaylı bilgi için Locale İşlemleri başlıklı yazıya göz atabilirsiniz.

C programlarında locale atamakC programlarında setlocale(int category,const char* locale) metodu kullanılır.

Atanmış olan locale'i almak için
setlocale(LC_ALL,NULL) yapılır.
Örnek:
printf ("C locale is : %s\n", setlocale(LC_ALL, 0)) ; //C locale is : C verir
C++ programlarında locale nesnesi yaratmak
facade vererek bir locale yaratmak
Örnek  :
std::locale fct (std::locale::classic(),boost::posix_time::time_input_facet("%d.%m.%Y %H:%M:%S"));
C++ programlarında locale atamak
C++ ile locale yazısına taşıdım.

Java'da ise locale isimleri için Locale.getISOLanguages() ve Locale.getISOCountries() metodları kullanılabilir. Örnek:


Stream'in locale'ini Almak
Örnek:
cout<<"C++ locale: "<<cout.getloc().name();//C++ locale: C

stream ve yardımcı metodlar
peek
Eğer stream'in sonuna geldiyse stream.peek () == EOF döner.

C programları

C programlarında kullanılan locale aşağıdaki şekilde görünen fonksiyonları etkiler.



QT
STL'e alternatif olabilecek bir diğer kütüphaneyi de karşılaştırma yapabilmek için eklemek istedim. QT ile gelen I/O kütüphanesinin hiyerarşisini buradan aldım ve aşağıya ekledim.

QIODevice tüm kütüphanenin başlangıç noktası. STL'den farklı olarak socketler de I/O kapsamında değerlendirilmiş.

Yine STL'den farklı olarak streamlere yazarken encode/decode işlemlerinı yapabilme imkanı sağlayan bir soyutlama katmanı daha getirilmiş ve QDataStream ile QTextStream sınıfları geliştirilmiş. Bu sınıflardan QDataStream big endian veya little endian olarak herhangi bir QIODevice sınıfına yazıp okuyabilme imkanı sağlıyor. Aşağıdaki şekli buradan aldım ve kullanım durumunu gösteriyor.
Reading the same file with several different streams in Qt sorusunda da açıklandığı gibi QDataStream veya  QTextStream sınıfları kullanılsa bile QIODevice sınıfı yazılacak pozisyonu tutuyor.
QTextStream
QTextStream sınıfı ile C'deki sscanf fonsiyonu gibi verilen string'i parçalayarak okuma mümkün. Örnek burada.

QBuffer
QBuffer sınıfı QByteArray sınıfına arayüz gibi kullanılıyor. Böylece herhangi bir şeyi byte array haline çevirmek kolaylaşıyor. Örnek için buradan aldığım koda bakabilirsiniz.

 
Java
Stream ve Karakterler Arasındaki Köprü
Java'da stream ve karakterler arasındaki köprüyü sağlayan iki sınıf var. InputStreamReader ve OutputStreamWriter.

InputStreamReader

Java da geniş bir I/O kütüphanesine sahip. C++ ile aralarındaki en büyük farklardan birisi ise Java ile gelen Reader/Writer sınıfları. istringstream sınıfı bir stream (yani ham byte'lardan) string okuyabilirken aynı işi yapan Java sınıfı ise InputStreamReader. Java InputStreamReader sınıfı sayesinde ham byte'lardan encoderlar vasıtasıyla dönüşüm yapabilme imkanı bulunuyor.

BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("infilename"), "UTF-8"));
 Soket'tten okuma yapmak içinse
Socket echoSocket = new Socket("myserver", 7);
BufferedReader in = new BufferedReader(new InputStreamReader(
                        echoSocket.getInputStream()));

OutputStreamWriter
Bu işlemin tam tersini yapan sınıf ise OutputStreamWriter.


Sadece Stream Sınıfları

FileInputStream
FileInputStream sınıfını kullanırken en çok dikkat edilmesi gereken konu stream ile işimiz bitince close() metodunun çağırılması. Böylece dosya için konulan kilit bırakılır. Eğer bu metodu çağırmazsak finalize() metodu garbage collector tarafından çağırılıncaya kadar dosya kilitli kalabilir. Force java to release all file locks/handles in Java sorusunda da benzer bir açıklama var.


Sadece Reader Sınıfları

BufferedReader

BufferedReader sınıfı okuma işlemi için tampon belleği kullanarak I/O işlemlerini kolaylaştırır.

readLine metodu

Bu metod ile tüm satırı okuma imkanı var

BufferedReader reader = new BufferedReader(new InputStreamReader(System.in,"UTF-8"));
while (reader.ready()) {
  String line = reader.readLine();
}

Sadece Writer Sınıfları 
PrintWriter
PrintWriter sınıfı verilen OutputStream'i bir Writer haline çeviren köprü işlevini görür. Eğer encoding ile kullanılmak istenirse örnek kod kullanılabilir.


StringWriter
StringWriter sınıfı dosya yerine hafızadaki bir tamponda girdileri biriktirir. println() metodunu sağlayan PrintWriter sınıfı ile beraber kullanılması daha kolaydır. Burada beraber kullanımı gösteriyor.

Scanner

Java zengin olduğu için bir de Scanner sınıfına sahip. Bu sınıf ile Reader/Writer arayüzlerini kullanmadan stream'den okuma yapmak mümkün. Scanner aşağıdaki kurucu metod imzasına sahip.

Örnek
Scanner sc = new Scanner(System.in,"UTF-8");
while(sc.hasNext()) {
  String next = sc.nextLine();
}
Yukarıdaki kullanımda Scanner sınıfı BufferedReader sınıfı gibi kullanılmış. Buradaki soruda ikisinin arasındaki bazı farklardan bahsediliyor. Örneğin Scanner içindeki tampon BufferedReader sınıfından daha küçük ancak esas fark, Scanner sınıfının primitif veri tipleri okumak üzere tasarlanmış olması.

Scanner sınıfının hasNextInt () metodu ise buradaki gibi kullanılabilir.

Bu kullanım şekliyle C'deki scanf'i andırıyor.

scanf'in döngü içinde kullanılabilmesini sebebi ise verilen tipten kaç tane okuyabildiğini dönmesi. Örnek:

Reflection ve Streamler

ObjectOutputStream ve ObjectInputStream sınıfları bir nesneyi stream'e binary olarak yazıp okuyabilmemizi sağlarlar. ObjectOutputStream yazma işleminden önce bir header yazdığı için kaç byte okuyacağını ve her alanın büyüklüğünü bilir. Aşağıdaki örnekte bir nesneyi TCP üzerinden bu sınıfları kullanarak gönderip alma gösterilmiş.


3 Mart 2014 Pazartesi

Dosya İşlemleri - Okuma

Dosyayının Satırlarını Okuma
C++
Tam benzemese de bir örnek burada var. Döngü kurmadan tüm dosyayı okumak kolaylaşıyor.

C#
File.ReadLines metodu kullanılarak satırlar sırayla okunabilir. ReadLines bir IEnumerable döndüğü için istenirse ilk 10 satırı okumak ta çok kolay. Örnek:
var first10Lines = File.ReadLines(path).Take(10).ToList();

Java
Java ile satırları okumak için Scanner veya BufferedReader kullanılabilir.
Scanner örneği
Scanner scanner = new Scanner(new File(filename));
while (scanner.hasNextLine()) {
      String line = scanner.nextLine();
      //Process line
}
BufferedReader ve FileReader örneği
Aşağıdaki örnekte FileReader kullanılıyor ancak FileReader dosyayı okumak için encoder kullanmamıza izin vermiyor. Dolayısıyla kullanılması tavsiye edilmiyor.
BufferedReader br = new BufferedReader(new FileReader("textfile.txt"));
while (br.ready()) {
    String sCurrentLine = br.readLine(); 
    //Process line

}
BufferedReader ve InputStreamReader örneği
Aşağıdaki örnekte InputStream ile UTF8 encoding kullanan dosya okunabiliyor.
FileInputStream in = new FileInputStream("textfile.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(in,"UTF8"));
while (br.ready()) {

    String sCurrentLine = br.readLine();
    //Process line
}
Eğer istenirse her satır okunduktan sonra toCharArray() metodu ile array olarak ta işlenebilir.

Apache Commons
FileUtils.lineIterator ile başarılıyor.Örnek:

QT
QTextStream sınıfı kullanılabilir. Örneği buradan aldım.

Plot-to-Track Tracker

Aşağıdaki  cümleyi buradan aldım:
Savunma alanında sensor veri füzyonu hedeflerin konum ve kimliklerine ait en iyi kestirimi elde edebilmek, eksiksiz ve zamanında durum değerlendirmesi ve tehdit analizi yapabilmek amacı ile kısıtlı çözünürlük ve kaplama alanına sahip, farklı hata seviyelerinde çalışan sensörlerden ve bilgi kaynaklarından gelen verilerin eşleştirilmesi(correlation), birbiri ile ilişkilendirilmesi (association) ve birleştirilmesi (combining) olarak tanımlanmaktadır.

Eşleştirme (correlation) nitelik olarak aynı tip bilgilere sahip nesnelerin gruplandırılması olarak tanımlanabilir. Örneğin iki farklı radar tarafından rapor edilen iki izin aynı (gerçek) temasa ait olup olmaması “eşleştirme” işlemidir.

Birleştirme (association) ise farklı tip bilgilere sahip nesnelerin gruplandırılması olarak tanımlanabilir. Örneğin bir edt izi ile bir radar izinin aynı temasa ait olup olmadıklarının testi ise “ilişkilendirme” işlemidir.

Birleştirme (combining) ise eşleştirme / ilişkilendirme işlemleri sonucu aynı gerçek dünya nesnesine ait
olduğu belirlenerek gruplandırılan bilgilerin birleştirilme işlemidir.

İzlerin sınıflandırılması

Bir plot-to-track tracker anladığım kadarıyla izleri şu şekilde sınıflandırmalı.

  1. ConfirmedTrack : Yeterince plot hit etmiş ve iz olduğu kesin olarak bilinen nesne. Yeterince kelimesi ile belli bir sayı kast ediliyor. Örneğin buradaki yazıda 3 kere hit alan bir nesnenin iz olarak teşhis edildiği belirtilmiş.
  2. TentativeTrack   : Arka arkaya birden fazla plot almış ve gerçek iz olma olasılığı yüksek olan aday nesne. Yukarıdaki örnekten yola çıkarsak 2 kere hit almış nesne kast edilir.
  3. PotentialTrack    : Bir plot hiti almış almış nesne

Plot bilgisinin toplanması

Plot-to-track tracker bir çok sensörden bilgi toplayacağı için concurrent bir yapıda çalışmalı. Bunun için iki tane yapıdan biri seçilmeli.
  • İlk seçenek her plot bilgisi geldiğinde bunu tracker'a hemen sokmak ve iz yapısını güncellemek. 
  • İkinci seçenek ise gelen plot bilgilerini biriktirerek periyodik olarak tracker'a sokmak. 
Geleneksel olarak Plot-to-track trackerlar radar antenleri gibi periyodik olarak çalışacak şekilde tasarlanmışlardır. Bu yüzden birinci metodun kullanıldığını bu çeşit trackerlarda hiç görmedim.

Covariance Matris
Sensörden gelen bilgi belli bir oranda hatalıdır. Eğer sensörün hata oranı bilinirse gönderdiği ölçümler covariance matris ile dönüştürülerek ölçüm hatası düzeltilmeye çalışılır.

Hava Manevraları
Burada temel hava savaşı manevraları var. İyi bir tracker bu manevraların hepsini takip edebilmeli.

Algoritma

Algoritma aslında basit ve şu adımlardan oluşuyor :

Öncelikle tüm sensörlerden plotlar orijinlerine göre bir indeksleme yapabilen bir veri yapısı içinde depolanırlar.

Eğer tracker'ın platformu hareketli bir platform ise (örneğin uçak, gemi vs.) önce elimizde bulunan izler için bir pozisyon düzeltmesi yapmak gerekebilir (ownship correction).

Daha sonra yeni gelen plotlar önce ConfirmedTrack izleri ile ilişkilendirilmeye çalışılır. İlişki kurma işleminden  sonra ConfirmedTrack izleri güncellenir.

İlişki kurulamayan plotlar bu sefer TentativeTrack izleri ile ilişkilendirilmeye çalışılır. İlişki kurma işleminden  sonra TentativeTrack izleri incelenir ve eğer gerekiyorsa bazıları ConfirmedTrack olarak sistemde terfi ettirilir.

İlişki kurulamayan plotlar bu sefer PotentialTrack denenir. Eğer bir PotentialTrack belli bir süre boyunca hiç hit almazsa bu iz silinir. Belli bir süre boyunca hit almış plotlar ise TentativeTrack olarak sistemde terfi ettirilir.

Yeni gelen ve hiç bir PotentialTrack ile ilişkilendirilemeyen plotlar ise eğer Non Automatic Initiation (NAI) sahası içine düşmüyorlarsa yeni bir PotentialTrack olarak sisteme eklenir.