Skip to main content

Java’da Dosya Kopyalama İşlemleri

Java’da dosya okuma , yazma , kopyalama işlemleri için bir çok farklı sınıf kullanılır. Ve bu sınıflar performansları açısından farklılık göstermektedir. Özellikle Java’nın ilk zamanlarında oluşturulan sınıflar ile ,  Java  7 ‘de kullanılan sınıflar arasında performans açısından gözle görülebilir farklılıklar bulunmaktadır.

Java’da dosya kopyalaması yaparken kullanılabilecek farklı yaklaşımlar bulunmaktadır.

  1. Byte Byte okuyup yazma
  2. Bir bütün olarak okuyup yazma
  3. Tampanlama kullanarak okuyup yazma.

Bu 3 yaklaşımdan en  performanssız olanı şüphesiz ki Byte byte okuyup yazmaktır. Sebebi her okunan byte sonrasında sistemin birde yazma işlemi yapması gerekmektedir.  Bunun için önce hardiske erişip okuma işlemi yapması , daha sonra okuduğu veriyi yine hardiske erişerek yazması gerekmektedir. Hardisklerin  oldukça yavaş aygıtlar olduğu düşünülürse harcanacak zamanı az çok tahmin edebiliriz. Bu nedenle bu yöntem önerilmeyen bir yöntemdir.  Çok küçük boyutta dosya okuma işlemleri yapılacaksa , ve performans çok önemli değilse kullanılabilir.

İkinci yakşım ise dosyayı bir bütün olarak okumak , ve tek  seferde yazmaktır. Bu  yaklaşım aslında düşünüldüğünde en mantıklı gelen yaklalım olabilir. Bir düşünelim dosyayı okuyacağız, ve tek bir sefer hardiske ulaşarak o dosyayı yazacağız. Kulağa ne kadar hoş geliyor  öyle değil mi ?    Ama aynı zamanda çokta tehlikeli. Çok büyük boyutlu bir dosya ile çalıştığımızı hesap edelim , ve bu dosya boyutu bilgisayardaki Ram miktrınıda aşıyor bulunsun ? Bu durumda  okuma işlemi yaparken  RAM tamamen dolacak ve bilgisayar kaynaksızlıktan kağnı gibi  işlem yapar hale gelecektir.  Bu nedenle bu yaklaşımda pek tercih edilmemektedir.

En iyi  kopyalama yaklaşımını en sona sakladım 🙂 Bu yontemde bir tampon boyutu belirlenir  ve bu tampon boyutu büyüklüğünde bir byte dizisi oluşturulur.  Byte dizisi oluşturmamızın sebebi dosyadan byte olarak okuma işlemi yapacak olmamızdandır. Java’da byte olarak okuma ve yazma işlemi yapmamızı sağlayan sınıflar  InputStream, ve OutputStream sınıflarıdır. Biz bu iki sınıftan türeyen FileInputStream ve FileOutputStream sınıfını kullanacağız.  Oluşuracağız sınıfta bir kaynak dosya, ve bir hedef dosya ismi vereceğiz.  Program çalışmaya başladığında  kaynak dosyanın var olup olmadığını kontrol edecek, eğer bir hata olması durumunda İstisna (Exception) fırlatacaktır.

Oluşturulan tampon  boyutu keyfidir, Statik olarak tanımlamak yerine  sisteme özel bir tasarım yapılabilir. Bir takım komutlar ile sistem belleğinin boyutu alınabilir ve belli bir yüzdelik dilim  bu tampon için ayırabilir. Ben 2000 byte’lik bir alan ayırmayı uygun gördük.  Peki ne  bu 2000 byte ne anlama gelecek.

Diyelim ki biz 6000 Byte boyutunda bir dosya kopyalamaya çalışalım  aşağıdaki sınıfta while dongusu içinde okuma islemi yapılmaya başlanacak  ve  bun tampon dolduğunda  FileOutputStream’ın Write metodu calişacaktır. 6000 Byte’lık bir kopyalama söz konusu olduğundan hardiske  sadece 3 defa yazma işlemi yapılacak ve  performansta artış sağlanmış olacaktır. Eğer ilk yaklaşım kullanılsa idi bu islem için 6000 bin defa okuma , 6000  defa yazma işlemi yapılacak ve performans kaybı söz konusu olacaktır.

Şimdi kodları paylaşalım.


import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class dosyaKopyala {
	private static final int TAMPONBOYUTU = 2000;
	// Verilerimizi byte byte yazmak  performans kaybı olacaktır. Bu nedenle  byteların
	// bir arada bulundugu bir ön bellekleme yöntemi ile verileri  okumak  ve yazmak
	// cok daha performanslı olur.
	private static  byte onBellek[] = new byte [TAMPONBOYUTU];
	// 2000 boyutlu bir byte dizisi olusturuyoruz. Byte dizisi olusturmamızın sebebi byte byte okuma
	// yapacak olmamamız.  Input Stream , OutputStream sınıfları byte byte okuma yapar.

	public static void dosyaYedekle(String kaynak, String hedef) throws IOException
	{

	 try{

		 InputStream  okuyucu = null;
		 OutputStream yazici = null;
		 // Dosya  islemlerinde kullanılabilecek bir cok sınıf vardır. fakat dosya kopyalaması
		 // yaparken özellikle de byte byte okurken Onbellek yeteneği olan sınıfları kullanırız. Bu tip
		 // sınıflar "Stream" olarak son ek alırlar. ve InputStream , OutputStream sınıflarından türerler.
		 okuyucu =  new FileInputStream(kaynak);
		 yazici =  new FileOutputStream(hedef);
		 // kaynak ve hedef dosya gosterildi.
		  while(true)
		   {
			 // sonsuz bir dongu  kurulması saglanarak dosya kopyalamaya baslayacağız.
			  // ve dosya sonua geldiğinde döngüyü kırıp çıkacağız

			  int okunan = okuyucu.read(onBellek);
			   // okuma islemini byte byte yapmak yerine ön bellek sistemi kullaniyoruz
			  // okuyu.read() yaptıgımızda bu yordam her okudugu veriyi direk yazmak gerine 2000 li
			  // bloklar halinde yazma islemi yapılacak.
			  if(okunan==-1){
				break;
				// dikkt edilirse okuyucu.read() bir integer dondurur ve bu integer deger aslında bizim
				// okudumuz dosyanın byte olarak karsılıklarıdır.
				// eğer okudumuz değer -1 ise , dosyanın sonu gelmiş demektir.döngüyü kırmamız gerekir
			    }

			   yazici.write(onBellek);
			   // 20000 li blok  dosyaya yazıldı.
		 }

	   okuyucu.close(); // okuyucu kapat
	   yazici.close();  // yazıyı kapat.

	 }catch (IOException e){

		throw new IOException();
	 }

	}

	// Bu yordamdan kaynak dosya adı , ve hedef dosya adı elle girilir
	// Dikkat kaynak  dosya ile program aynı dizinde olmalıdır.

	public static void main(String[] args) {

		try{

		  dosyaYedekle("jandarma.Jpeg", "jandarmaKopya.Jpeg");
		} catch(IOException e){

			System.out.println("Dosya kopyalanırken hata olustu."+ e.getLocalizedMessage());

		}
		System.out.println("Dosya Kopyalam başarılı..");

	}

}

Kaynak Kodları indirmek için aşağıdaki tıklayın.. Sağlıcakla

https://www.dropbox.com/s/44u2yk3hs652yop/Dosya%C4%B0slemleri.rar

Share and Enjoy

  • Facebook
  • Twitter
  • Delicious
  • LinkedIn
  • StumbleUpon
  • Add to favorites
  • Email
  • RSS