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


Hiç yorum yok:

Yorum Gönder