# Dosya Tabanlı Depolama

- **İngilizce aslı:** https://wiki.facepunch.com/gmod/File_Based_Storage
- **Çeviri tarihi:** 2025-09-08

## Giriş

Veri Depolama (Data Storage), verilerin harita değişiklikleri ve sunucu yeniden başlatmaları boyunca kalıcı olmasını istediğimizde kullandığımız yöntemdir.

> **NOT:** Veri konusunda istemciye asla güvenmeyin. Verileri yalnızca sunucudan depolayın, kaydedin, değiştirin ve yükleyin. İstemciye veri vermeniz gerekirse, sunucuda bir yedeğini tuttuğunuzdan emin olun!

Garry's Mod'da veri depolamanın birden çok yolu vardır. Bu eğitimde, Dosya Tabanlı Depolama'yı (File Based Storage) ele alacağız.

## Veri işleme kuralları

Herhangi bir veriyi işlerken uymamız gereken bazı kurallar vardır:

- **Asla** istemci tarafından işlenmiş verilere güvenmeyin. Tüm verileri sunucuda yedekli tutun, çünkü verilerin orijinal olduğundan emin olmanın tek yolu budur. Diyelim ki istemcilerin paralarını takip etmelerine izin vermeye başladık; sonuna birkaç sıfır eklemelerini ne engelleyebilir ki?
- **Daima** istemcinin manipüle edemeyeceği bir kimlik bilgisi kullanın. Bir istemcinin çıkış yaptığında canını kaydetmek isteseydik ve kimlik olarak Steam adlarını kullansaydık, bir sonraki girişlerinden önce bunu değiştirmelerini ne engelleyebilir? Hiçbir şey. Bu yüzden [Player:SteamID](https://gmod.tr/wiki/Player:SteamID) gibi, istemci tarafından asla değiştirilemeyecek kimlik bilgileri kullanmalıyız.

Fark etmediyseniz, burada kapsayıcı bir tema var: **İstemciye asla güvenme**.

Ne yazık ki, Garry's Mod sunucuları öngörülebilir değildir - uyarı vermeden kolayca çökebilir veya aşırı yüklenebilirler. Bu nedenle, veriyi kaybetmemek için mümkün olduğunca çabuk işlemelisiniz. Oyuncunun oynarken kazandığı jeton sayısını kaydetmek için oyundan ayrılmasını beklemeyin, çünkü sunucu o zamandan önce ölümcül bir çökme yaşayabilir. Ayrıca, verileri [GM:ShutDown](https://gmod.tr/wiki/GM:ShutDown) hook'u sırasında kaydetmemelisiniz, çünkü bazı oyuncular geçersiz hale geleceği ve değerli jeton sayılarının kaybolacağı için veri kaydetmeye başlamak için çok geç olabilir. Ancak, bunu okuyor olabilirsiniz ve verilerinizin en son anda kaydedilmesi gerektiğini veya her değiştirildiğinde kaydedilecek kadar önemli olmadığını düşünebilirsiniz - bu durumda, [GM:ShutDown](https://gmod.tr/wiki/GM:ShutDown) hook'unu riski size ait olmak üzere kullanabilirsiniz!

## Hakkında

Metin dosyaları, veri depolamanın basit bir yoludur. Dosya Tabanlı Depolama, yalnızca [file](https://gmod.tr/wiki/file) kütüphanesine dayandığı ve oldukça basit olduğu için herhangi bir harici modül gerektirmez. Bu nedenlerden dolayı, yeni başlayanlar için önerilen yöntemdir.

## Tabloları depolama - util.TableToJSON

Bu, belki de [Color](https://gmod.tr/wiki/Color) veya [Vector](https://gmod.tr/wiki/Vector) gibi veri türlerini dönüştürürken yaşanan hayal kırıklığını önleyecek, yeni başlayanlar için en kolay yöntemdir, bu yüzden önce bu yöntemle başlayacağız.

### Tabloları metin dizisine (string) dönüştürme

Bir metin dosyası temel olarak bir karakter dizisidir. Bu, tüm verilerimizi bir karakter dizisine dönüştürmemiz gerektiği anlamına gelir...

[util.TableToJSON](https://gmod.tr/wiki/util.TableToJSON), bir Lua tablosunu JSON formatına dönüştürecek bir fonksiyondur. JSON, (Lua tabloları gibi) belirli verileri metin olarak temsil etmek için popüler bir formattır; bu metin bir dosyaya kaydedilebilir ve daha sonra aynı veriye geri dönüştürülebilir.

[util.TableToJSON](https://gmod.tr/wiki/util.TableToJSON)'ı nasıl kullanabileceğimize dair bir örnek:

```lua
-- Here we have a generic table, containing different types of data that we wish to save into a file:
local storeOwnerData = {
	pos = Vector(1000,20,3),
	rot = Angle(0,90,0),
	col = Color(255,0,0,20),
	text = "Dave - Store Owner"
}

-- Let's see what util.TableToJSON is going to give us to work with:
print(util.TableToJSON(storeOwnerData))
```

Çıktı:

```lua
{"text":"Dave - Store Owner","rot":"{0 90 0}","pos":"[1000 20 3]","col":{"r":255.0,"b":0.0,"a":20.0,"g":0.0}}
```

Color, Angle ve Vector yapılarının nasıl ayırt edilebilir metin yapılarına dönüştürüldüğüne dikkat edin. Bu benzersiz formatlar, tersine çevirme fonksiyonu olan [util.JSONToTable](https://gmod.tr/wiki/util.JSONToTable)'ın formatları orijinal veri yapılarına geri dönüştürmesine olanak tanır.

Dosyayı okurken gerçekleşmesi gereken tersine çevirme sürecini görebilmemiz için biraz daha kod yazalım.

```lua
-- JSONData now stores the Lua table "storeOwnerData" in JSON format.
local JSONData = util.TableToJSON(storeOwnerData)

local converted = util.JSONToTable(JSONData)
PrintTable(converted)
```

Çıktı:

```lua
col:
                a       =       20
                b       =       0
                g       =       0
                r       =       255
pos     =       1000.000000 20.000000 3.000000
rot     =       0.000 90.000 0.000
text    =       Dave - Store Owner
```

Gördüğünüz gibi, JSON metni tekrar bir tablo formatına dönüştürüldü. Ayrıca, `converted.pos` ile [isvector](https://gmod.tr/wiki/Global.isvector) ve `converted.rot` ile [isangle](https://gmod.tr/wiki/Global.isangle) kullanarak veri türlerinin orijinal formatlarına döndüğünü kontrol edebiliriz, bu da bize onların tekrar bir [Vector](https://gmod.tr/wiki/Vector) ve [Angle](https://gmod.tr/wiki/Angle)'a dönüştürüldüğünü söyler. Ne yazık ki, `converted.col`'u [IsColor](https://gmod.tr/wiki/Global.IsColor)'a geçirmek, onun doğru bir şekilde [Color](https://gmod.tr/wiki/Color) yapısına dönüştürülmediğini gösterir. Neyse ki, daha sonra onu normale döndürmek için kod yazabiliriz.

### JSON verisini kaydetme

Artık bir tabloyu depolanabilir bir formata nasıl dönüştüreceğimizi ve depolanan formatı normal bir Lua tablosuna nasıl geri çevireceğimizi öğrendiğimize göre, şimdi dosyaları nasıl okuyup/yazacağımızı ve JSON verisini nasıl kaydedeceğimizi öğrenebiliriz.

İster inanın ister inanmayın, veriyi bir dosyaya kaydetmek yalnızca tek bir fonksiyon gerektirir: [file.Write](https://gmod.tr/wiki/file.Write). Dokümantasyona baktığımızda yalnızca iki şeye ihtiyacı olduğunu öğreniyoruz:

- Bir dosya adı
- Kaydedilecek veri Öyleyse devam edelim ve storeOwnerData tablosunu `storedata.json` adlı bir dosyaya kaydetmeyi tamamlamak için biraz kod yazalım:

```lua
local storeOwnerData = {
	pos = Vector(1000,20,3),
	rot = Angle(0,90,0),
	col = Color(255,0,0,20),
	text = "Dave - Store Owner"
}

-- Let's put it in a function so that when we next change the table, we can just call this function again
function SaveStoreData()
	local converted = util.TableToJSON(storeOwnerData)
	file.Write("storedata.json", converted)
end

SaveStoreData()
```

İşte bu kadar, dosya kaydedildi!

Dosyayı kendi gözlerinizle görmek isterseniz, `garrysmod/data` klasörüne gidebilirsiniz; dosyanın adı "storedata.json" olacaktır.

> **NOT:** [Eylül 2019](https://gmod.facepunch.com/blog/september-2019-update)'dan beri dosyalar JSON (.json) formatında kaydedilebilmektedir.

### Dosyalardan JSON verisini okuma ve tekrar tabloya dönüştürme

JSON verisini okumak da, anahtar fonksiyonun tek bir argüman alan [file.Read](https://gmod.tr/wiki/file.Read) olmasıyla aynı derecede kolaydır... Dosya Adı. Burada ayrıca renk verisi içeren tabloyu da bir Color yapısına dönüştüreceğiz:

```lua
local storeOwnerData = {}

function ReadStoreData()
	-- Make sure you use the same filename as the one in file.Write!
	local JSONData = file.Read("storedata.json")

	-- JSONData is currently a JSON string - let's convert that into a table:
	storeOwnerData = util.JSONToTable(JSONData)

	-- Remember how the col value does not get converted into a Color structure? Let's fix that:

	local oldCol = storeOwnerData.col

	storeOwnerData.col = Color(oldCol.r, oldCol.g, oldCol.b, oldCol.a)
end
```

`storeOwnerData` değişkeni artık tüm verileri içeriyor ve `col` değeri artık bir [Color](https://gmod.tr/wiki/Color)!

## Tablolar dışındaki veri türlerini yazma

Yukarıdaki yöntem tabloları depolamak için mükemmeldir, peki ya sadece bir sayı veya metin (string) depolamak istersek?

Bu senaryoda özellikle farklı olan bir şey yok, sadece artık util fonksiyonlarına ihtiyacımız yok:

### Metni (string) kaydetme

```lua
local myString = "This is a string that I want to save!"

function SaveString()
	-- We are saving the contents of myString into a file called "stringdata.txt"
	file.Write("stringdata.txt", myString)
end

SaveString()
```

### Metni (string) yükleme

```lua
local myString = ""

function LoadString()
	myString = file.Read("stringdata.txt")
end

LoadString()
```

Hiç de o kadar zor değil, değil mi?

## Dosya tabanlı depolamaya alternatifler

Diyelim ki bir oyuncunun para miktarını takip etmemiz gerekiyor. O zaman, oyuncu her ayrıldığında veya para miktarı güncellendiğinde dosyaya kaydetmemiz gerekir ve bu nedenle, 1.000 satırlık (hatta daha fazla!) bir dosyanın okunması, değiştirilmesi ve ardından tamamen yeni verilerle üzerine yazılması gerekecektir. Bu yavaştır ve bir dosyada verisi depolanan oyuncu sayısı arttıkça çok daha yavaş hale gelecektir.

Bu nedenle, bir alternatife ihtiyacımız var.

Belki de Garry's Mod'da büyük miktarda veri depolamanın en verimli yöntemi [SQL](https://gmod.tr/wiki/sql)'dir. Ne yazık ki, SQL'i öğrenmek dosya tabanlı depolama kadar kolay değildir, ancak öğrenmeye karar verirseniz kesinlikle buna değer.

> **NOT:** PData artık dahili olarak [Player:SteamID64](https://gmod.tr/wiki/Player:SteamID64) kullanıyor, bu da çakışan veri olmaması gerektiği ve 19 Temmuz 2024 itibarıyla kullanımının güvenli olduğu anlamına geliyor.

- [GMod Wiki ana sayfası](https://gmod.tr/wiki)

---

[Tüm sunucular](https://gmod.tr/) · [GmodTR Launcher](https://gmod.tr/launcher) · [Rehber](https://gmod.tr/rehber) · [GMod Wiki](https://gmod.tr/wiki) · [GmodTR nedir?](https://gmod.tr/hakkinda) · [Sunucu ekle](https://gmod.tr/sunucu-ekle) · [Discord](https://discord.gg/gmodtr)

Kaynak: https://gmod.tr/wiki/File_Based_Storage
