COPYFILE yetmediğinde: satır satır dosya işlemleri
Bir önceki yazıda COPYFILE ile dosyaları olduğu gibi taşımaktan bahsetmiştim. Ama bazen dosyanın içeriğiyle ilgilenmeniz gerekir — bir CSV'yi satır satır okuyup her satırdan bir kayıt üretmek, ya da bir log dosyasına sürekli yeni satırlar eklemek gibi. Bunun için TROIA'nın dosya G/Ç komut ailesi var: OPEN FILE, PUT, GET, GETBLOCK, CLOSE FILE.
Dosya açma ve kapama
OPEN FILE {dosyayolu} [FORNEW|FORREAD|FORAPPEND] [FILEID {fileid}];
CLOSE FILE [FILEID {fileid}];
Üç mod farklı davranır:
- FORNEW: Yeni dosya oluşturur, mevcut istemci dosyasını kopyalamaz.
- FORREAD: İstemci dosyasını önce sunucuya kopyalar, sonra okuma için açar.
- FORAPPEND: Varsayılan mod; istemci dosyasını sunucuya kopyalar.
Her iki komut da başarısızlıkta SYS_STATUS'u 1 yapar ve SYS_STATUSERROR'a hata detayını yazar — bu yüzden OPEN FILE'dan hemen sonra SYS_STATUS kontrolü yapılmadan PUT/GET çağırmak, "dosya açılamadı ama program kodu bunu fark etmeden devam etti" tarzı sinsi hataların klasik kaynağıdır.
İstemci tarafındaki bir yola işaret ederken yol * öneki alır: '*C:\TMP\dosya.txt'.
Yazma: PUT
PUT {degerlistesi} [CODEPAGE {kodlama}] [NOENDOFLINE] [FILEID {fileid}];
PUT varsayılan olarak her çağrıdan sonra satır sonu (\n\r) ekler; bunu istemiyorsanız NOENDOFLINE kullanılır. Kodlama belirtilmezse varsayılan ISO8859_9 (Türkçe Latin-5) kullanılır — bu detay, bir dosyayı UTF-8 bekleyen harici bir sisteme gönderirken "Türkçe karakterler bozuk geliyor" şikayetinin neredeyse her zaman gerçek sebebidir; CODEPAGE parametresini açıkça belirtmek bu sınıf hataları baştan önler.
Okuma: GET ve GETBLOCK
GET {degiskenlistesi} [CODEPAGE {kodlama}] [FILEID {fileid}];
GETBLOCK {degisken}, {ayirici} [CODEPAGE {kodlama}] [FILEID {fileid}];
GET tek satır okur, dosya sonunda boş string döner — yani döngü koşulu genelde "boş string dönene kadar oku" şeklinde kurulur. GETBLOCK ise belirtilen ayırıcıya kadar okur; boş ayırıcı verilirse dosyanın tamamını tek seferde okur (küçük dosyalar için pratik, büyük dosyalarda bellek tüketimine dikkat).
Gerçek bir örnek: CSV'yi satır satır okuyup tabloya aktarmak
/* Basit bir CSV dosyasını satır satır okuyup tabloya aktarır. */
LOCAL:
STRING SATIR;
TABLE KAYITLAR(KOD CHAR(20), ADI CHAR(100));
OPEN FILE '*C:\TMP\urunler.csv' FORREAD FILEID 1;
IF SYS_STATUS = 1 THEN
MESSAGE 'Dosya açılamadı: ' + SYS_STATUSERROR TYPE ERROR;
RETURN;
ENDIF;
GET SATIR FILEID 1;
WHILE SATIR <> '';
PARSE SATIR ';' KAYITLAR.KOD, KAYITLAR.ADI;
ADDROW TO KAYITLAR;
GET SATIR FILEID 1;
ENDWHILE;
CLOSE FILE FILEID 1;
Sık yapılan hatalar
FILEIDkullanmadan aynı anda birden fazla dosya açmaya çalışmak —FILEIDverilmezse sistem varsayılan bir dosya tanımlayıcı kullanır, bu da eşzamanlı erişimi engeller. Birden fazla dosyayla aynı anda çalışıyorsanız her birine ayrıFILEIDvermek zorunludur.- Döngü sonunda
CLOSE FILEçağırmayı unutmak — özellikle bir hata/RETURNile döngüden erken çıkıldığında dosya açık kalabilir; sonraki çağrılarda "dosya kilitli" hatasıyla karşılaşmamak içinCLOSE FILE'ı bir hata durumunda da mutlaka çalışacak şekilde kurgulamak gerekir. GET'in dosya sonunda boş string döndürdüğünü unutup sonsuz döngüye girmek — eğer okunan satır gerçekten boşsa (dosyada boş satır varsa) döngü yanlışlıkla erken sonlanabilir; kritik veri dosyalarındaSYS_STATUS'u da kontrol ederek dosya sonunu daha güvenilir tespit etmek daha sağlam bir yaklaşımdır.- Kodlama belirtmeden Türkçe karakter içeren dosyalarla çalışmak — yukarıda değindiğim gibi,
CODEPAGEparametresi atlanırsa dış sistemle veri alışverişinde karakter bozulmaları en sık karşılaşılan destek talebi haline gelir.
Sıradaki adım
DIGESTFILE ile dosya bütünlüğü kontrolü (checksum/hash) ve ZIPFILE/UNZIPFILE ile bu satır satır okuma-yazma yaklaşımını birlikte kullanan bir örneğe ileride başka bir yazıda değinebilirim; şimdilik dosya G/Ç ailesinin temel taşlarını kapsamış olduk.
Yorumlar (0)
Yorum Yaz