-- Genel, Go

Go ile Dosya İşlemleri #1

Go ile Dosya İşlemleri

Go programlama dilinin en güçlü olduğu alan sistem programlamadır. Sistem katmanında ise en sık kullanılan işlemlerin başında dosya-klasör oluşturma ya da bunların yönetilmesi(isim değiştir, taşı, sil vb.) gibi işlemler gelir. Uygulamalarınızda sık kullanacağınız bu tür işlemler için farklı örnekler inceleyeceğiz.

Boş Dosya Oluşturma

package main

import (
	"log"
	"os"
)

var (
	newFile *os.File
	err     error
)

func main() {
	newFile, err = os.Create("demo.txt")
	if err != nil {
		log.Fatal(err)
	}
}

Bu uygulama sayesinde, projenizin ana dizininde(main.go’nun bulunduğu klasör) demo.txt isimli bir dosya oluşturacaktır.

Dosyayı Kes (Trucate a File)

package main

import (
	"log"
	"os"
)

func main() {

	/*
		Dosyayı Kes (Truncate a File)

		Bir dosya 100 byte'a kesilmelidir.
		Eğer dosya 100 byte'tan az ise içerik kalır, geri kalan kısım boş byte ile dolacaktır.
		Eğer dosya 100 byte'ın üzerinde ise 100 byte'tan sonraki herşey kaybolur.
		Her iki durumda da kesme işlemi 100 byte üzerinden gerçekleştirilmelidir.
		Eğer kesilecek dosya boş ise sıfır değeri kullanılır.
	*/

	err := os.Truncate("demo.txt", 100)
	if err != nil {
		log.Fatal(err)
	}
}

Dosya Bilgisi Almak (Get File Info)

package main

import (
	"fmt"
	"log"
	"os"
)

var (
	fileInfo *os.FileInfo
	err      error
)

func main() {
	/*
	   Dosya Bilgisi Almak (Get File Info)
	*/
	// Dosya bilgisini döndürür.
	// Eğer dosya yoksa hata döndürür.
	fileInfo, err := os.Stat("demo.txt")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("File name: ", fileInfo.Name())
	fmt.Println("Size in bytes: ", fileInfo.Size())
	fmt.Println("Permissions: ", fileInfo.Mode())
	fmt.Println("Last Modified: ", fileInfo.ModTime())
	fmt.Println("Is Directory: ", fileInfo.IsDir())
	fmt.Println("System interface type: %T\n", fileInfo.Sys())
	fmt.Println("System info: %+v\n\n ", fileInfo.Sys())
}

Dosya Yeniden İsimlendirme (Rename and Move a File)

package main

import (
	"log"
	"os"
)

func main() {

	/*
	   Yeniden İsimlendirme ve Taşıma (Rename and Move a File)
	*/

	originalPath := "demo.txt"
	newPath := "test.txt"
	err := os.Rename(originalPath, newPath)
	if err != nil {
		log.Fatal(err)
	}

	// Taşıma işlemini de Rename() ile yapmayı dene!
}

Dosya Silme (Delete a File)

package main

import (
	"log"
	"os"
)

func main() {

	/*
	   Dosya Silme (Delete a file)
	*/

	err := os.Remove("demo.txt")
	if err != nil {
		log.Fatal(err)
	}
}

Dosya Açma ve Kapatma (Open and Close Files)

package main

import (
	"log"
	"os"
)

func main() {

	/*
	   Dosyaları Açma ve Kapama (Open and Close Files)
	*/

	// Dosyayı salt okunur olarak açtık
	file, err := os.Open("demo.txt")
	if err != nil {
		log.Fatal(err)
	}
	file.Close()

	// OpenFile çok seçenekli dosya açma yöntemidir.
	// İkinci parametre dosya açılış amacını ayarlarken, üçüncü parametre dosya izinlerini belirler.
	file, err = os.OpenFile("demo.txt", os.O_APPEND, 0666)
	if err != nil {
		log.Fatal(err)
	}
	file.Close()

	/*

		   OpenFile() ikinci parametrenin tipleri;

		   os.O_RDONLY   : Sadece okuma
		   os.O_WRONLY   : Sadece yazma
		   os.O_RDWR     : Okuma ve yazma yapılabilir
		   os.O_APPEND   : Dosyanın sonuna ekle
		   os.O_CREATE   : Dosya yoksa oluştur
		   os.O_TRUNC    : Açılırken dosyayı kes

		   Bu ayarlar birden fazla olarak da kullanılabilir

		   	-> os.O_CREATE|os.O_APPEND
			-> os.O_CREATE|os.O_TRUNC|os.O_WRONLY
	*/
}

Dosyanın Varlığını Kontrol Etme (Check if File Exists)

package main

import (
	"log"
	"os"
)

var (
	fileInfo *os.FileInfo
	err      error
)

func main() {

	/*
	   Dosyanın var olup olmadığını kontrol etmek (Check if File Exists)
	*/

	// Dosya bilgisini döndürür.
	// Eğer dosya yoksa hata döndürür.
	fileInfo, err := os.Stat("demo.txt")
	if err != nil {
		if os.IsNotExist(err) {
			log.Fatal("File does not exist")
		}
	}
	log.Println("File does exist. File information : ")
	log.Println(fileInfo)
}

Dosya Okuma ve Yazma İzinlerini Kontrol Etme (Check Read and Write Permissions)

package main

import (
	"log"
	"os"
)

func main() {

	/*
	   Okuma ve Yazma İzinlerini Kontrol Etmek ( Check Read and Write Permissions)
	*/

	// Yazma izinleri testi
	// Dosyanyı açmaya çalışmadan önce varlığını kontrol edebilirsiniz;
	// Bunun için; os.IsNotExist
	file, err := os.OpenFile("demo.txt", os.O_WRONLY, 0666)
	if err != nil {
		if os.IsPermission(err) {
			log.Println("Hata : Yazma izni reddedildi")
		}
	}
	file.Close()

	// Okuma izinleri testi
	file, err = os.OpenFile("demo.txt", os.O_RDONLY, 0666)
	if err != nil {
		if os.IsPermission(err) {
			log.Println("Hata : Okuma izni reddedildi")
		}
	}
	file.Close()
}

İzinleri, Sahipliği ve Zaman Damgalarını(Timestamps) Değiştirmek (Change Permissions, Ownership, and Timestamps)

package main

import (
	"log"
	"os"
	"time"
)

func main() {

	/*
	   İzinleri, Sahipliği ve Zaman Damgalarını(Timestamps) Değiştirmek Change Permissions, Ownership, and Timestamps
	*/

	// İzinleri değiştirme (Linux tarzı)
	err := os.Chmod("demo.txt", 0777)
	if err != nil {
		log.Println(err)

	}

	// Sahipliği değiştirme
	err = os.Chown("demo.txt", os.Getuid(), os.Getgid())
	if err != nil {
		log.Println(err)
	}

	// Zaman Damgalarını(Timestamps) Değiştirme
	twoDaysFromNow := time.Now().Add(48 * time.Hour)
	lastAccessTime := twoDaysFromNow
	lastModifyTime := twoDaysFromNow
	err = os.Chtimes("demo.txt", lastAccessTime, lastModifyTime)
	if err != nil {
		log.Println(err)
	}
}

Hard Links and Symlinks

package main

import (
	"fmt"
	"log"
	"os"
)

func main() {

	/*
	   Hard Links and Symlinks
	*/

	// Bir "Hard Link" oluştur
	// Aynı içeriğe işaret eden iki dosya adı olacaktır.
	// Birinin içeriğini değiştirmek diğerini değiştirecek
	// Birini silmek / yeniden adlandırmak diğerini etkilemez
	err := os.Link("demo.txt", "demo_also.txt")
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("sym oluşturma")

	// Symlink oluştur
	err = os.Symlink("demo.txt", "demo_also.txt")
	if err != nil {
		log.Fatal(err)
	}

	// Lstat dosya bilgisini döndürür.
	// Ama aslında o bir symlink ise symlink hakkında bilgi döndürür.
	// Bağlantıyı takip etmeyecek ve gerçek dosya hakkında bilgi vermeyecektir.
	// Symlink'ler Windows'da çalışmaz.
	fileInfo, err := os.Lstat("demo_sym.txt")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Bağlantı Bilgisi: %+v", fileInfo)

	// Sadece bir symlink'in sahipliğini değiştir.
	// Ama işaret ettiği dosyanın sahipliğini değiştirmez.
	err = os.Lchown("demo_sym.txt", os.Getuid(), os.Getgid())
	if err != nil {
		log.Fatal(err)
	}
}

Dosya Kopyalama (Copy a file)

package main

import (
	"io"
	"log"
	"os"
)

func main() {

	/*
	   Dosya Kopyalama (Copy a file)
	*/

	originalFile, err := os.Open("demo.txt")
	if err != nil {
		log.Fatal(err)
	}
	defer originalFile.Close()

	// Yeni bir dosya oluştur
	newFile, err := os.Create("demo_copy.txt")
	if err != nil {
		log.Fatal(err)
	}
	defer newFile.Close()

	// Byte'ları kaynaktan hedefe Kopyalama
	bytesWritten, err := io.Copy(newFile, originalFile)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Copied %d bytes.", bytesWritten)

	// Dosya içeriğini işle(commit)
	// Belleği diske boşalt(flush)
	err = newFile.Sync()
	if err != nil {
		log.Fatal(err)
	}
}

Seek Positions in File

package main

import (
	"fmt"
	"log"
	"os"
)

func main() {

	/*
	   Seek Positions in File
	*/

	file, _ := os.Open("demo.txt")
	defer file.Close()

	// Offset kaç byte taşımalıdır?
	// Offset negatif(-) ya da pozitif(+) olabilir
	var offset int64 = 5

	// Offset için referans noktası nerededir?
	// 0 = Dosyanın başlangıcı
	// 1 = Şu anki pozisyon
	// 2 = Dosyanın sonu
	var whence int = 0
	newPosition, err := file.Seek(offset, whence)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Just moved to 5: ", newPosition)

	// Şu anki pozisyondan 2 byte geri git
	newPosition, err = file.Seek(-2, 1)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Just moved back two: ", newPosition)

	// 0 byte taşındıktan sonra Seek'den dönüş değerini elde ederek geçerli konumu bul.
	currentPosition, err := file.Seek(0, 1)
	fmt.Println("Current position: ", currentPosition)

	// Dosyanın başlangıcına git
	newPosition, err = file.Seek(0, 0)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Position after seeking 0,0: ", newPosition)
}

Byte’ları Bir Dosyaya Yazma (Write Bytes to a File)

package main

import (
	"log"
	"os"
)

func main() {

	/*
	   Byte'ları Bir Dosyaya Yazın (Write Bytes to a File)
	*/

	// Demo.txt dosyasını sadece yazılabilir bir dosya olarak aç
	file, err := os.OpenFile(
		"demo.txt",
		os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
		0666)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	byteSlice := []byte("Bytes!\n")
	bytesWritten, err := file.Write(byteSlice)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Wrote %d bytes.\n", bytesWritten)
}

Hızlıca Dosya Yazma (Quick Write to File)

package main

import (
	"io/ioutil"
	"log"
)

func main() {

	/*
	   Hızlıca Dosya Yazma (Quick Write to File)
	*/

	err := ioutil.WriteFile("demo.txt", []byte("Hi!\n"), 0666)
	if err != nil {
		log.Fatal(err)
	}
}

Buffer İşlemleri

package main

import (
	"bufio"
	"log"
	"os"
)

func main() {
	// Yazmak için dosyayı aç
	file, err := os.OpenFile("test.txt", os.O_WRONLY, 0666)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	// Dosyadan bir "buffered writer" oluştur
	bufferedWriter := bufio.NewWriter(file)

	// Arabelleğe byte yaz
	bytesWritten, err := bufferedWriter.Write(
		[]byte{65, 66, 67},
	)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Bytes written: %d\n", bytesWritten)

	// String'i belleğe(buffer) yaz
	// Ayrıca bunlarda mevcut: WriteRune() ve WriteByte()
	bytesWritten, err = bufferedWriter.WriteString(
		"Buffered string\n",
	)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Bytes written: %d\n", bytesWritten)

	// Buffer beklenirken ne kadar depolandığını kontrol etme
	unflushedBufferSize := bufferedWriter.Buffered()
	log.Printf("Bytes buffered: %d\n", unflushedBufferSize)

	// Kullanılabilir arabellek miktarını görme
	bytesAvailable := bufferedWriter.Available()
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Available buffer: %d\n", bytesAvailable)

	// Belleği diske yaz
	bufferedWriter.Flush()

	// Henüz Flush() ile dosyaya yazılmamış arabellekte yapılan değişiklikleri geri alın.
	bufferedWriter.Reset(bufferedWriter)

	// Kullanılabilir arabellek miktarını görme
	bytesAvailable = bufferedWriter.Available()
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Available buffer: %d\n", bytesAvailable)

	// Tamponu yeniden boyutlandırır.
	// Bu kullanınmda aynı buffer'ı yeniden boyutlandırıp kullanıyoruz.
	bufferedWriter = bufio.NewWriterSize(
		bufferedWriter,
		8000,
	)

	// Yeniden boyutlandırma sonrasında tekrar kullanılabilir arabellek miktarını kontrol etme
	bytesAvailable = bufferedWriter.Available()
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Available buffer: %d\n", bytesAvailable)
}

Github: https://github.com/cihanozhan/golang-file-samples

İyi çalışmalar.
Cihan Özhan

Yorumla

Yorum