1. Zədələnmiş faylların əlamətləri
Ideal dünyada fayllar həmişə səhvsiz oxunur və yazılır, onlardakı məlumatlar isə — təzə bişmiş bulka kimi: yumşaq, ətirli, səliqəli, bütöv. Amma reallıqda fayllar “qırıq”, “əyri”, “yarımçıq” və ya “başqa formatda” ola bilər. Səbəblər müxtəlifdir. Məsələn, diskə yazma zamanı nasazlıq (gücün qəfil sönməsi), şəbəkədə fayl ötürülərkən səhvlər, daşıyıcının sıradan çıxması (o köhnə “bad sector”). Və ya faylı uyğun olmayan proqramda əl ilə redaktə etmək onu korlaya bilər, eləcə də gözlənilən və faktiki məlumat formatının uyğun gəlməməsi.
Java-da belə situasiyalar adətən oxuma/yazma zamanı istisnalarla üzə çıxır, bəzən isə proqramın qəribə davranışı ilə (məsələn, məlumatlar qəfil bitir və ya “abrakadabra” yaranır).
Oxuma zamanı istisnalar
Ən aşkar əlamət — gözlənilməz istisnalardır. Bəzi nümunələr:
- EOFException — faylın gözlənilməz sonu (End Of File). Faylda hələ məlumat olacağını gözləyirdiniz, amma artıq yoxdur.
- MalformedInputException (və ya köhnə API-lərdə NIO-dan MalformedInputException) — fayl gözlənilən kodirovkaya və ya struktura uyğun deyil.
- ZipException — arxivi adi fayl kimi oxumağa cəhd etdikdə.
- StreamCorruptedException — serializə edilmiş obyektləri oxuyarkən, fayl zədələnibsə.
Məlumat formatının uyğunsuzluğu
Bəzən fayl istisnasız oxunur, amma məzmun gözlənilən formata uyğun gəlmir:
- Sətir gözləyirdiniz, amma anlaşılmaz simvollar dəsti aldınız.
- Müəyyən sayda ədəd gözləyirdiniz, amma onlar daha azdır.
- Faylın CSV formatında olmasını gözləyirdiniz, amma orada JSON var (və ya əksinə).
Həyatdan nümunə
Tutaq ki, siz mətn faylında tapşırıqlar siyahısını saxlayan tətbiq yazırsınız. Proqram gözləyir ki, hər sətir — ayrıca tapşırıqdır. Amma istifadəçi faylı Excel-də açdı, dəyişikliklər etdi, başqa formatda saxladı... və indi proqramınız faylı oxuya bilmir.
2. Zədələnmiş faylların emalı strategiyaları
Loglama və istifadəçini məlumatlandırma
Birinci qayda: panik etməmək! (və istifadəçiyə də panika etməyə imkan verməmək). Həmişə səhvi loglayın və nəsə yolunda getməsə, istifadəçiyə bildirin. Amma ona Java stack-in bütün dəhşətlərini göstərmək — vacib deyil.
try {
// faylın oxunması
} catch (EOFException e) {
System.err.println("Fayl gözlənilmədən sona çatdı. Ola bilsin, o zədələnib.");
// təfərrüatları loglayırıq
e.printStackTrace();
}
Qismən bərpa cəhdi
Bəzən heç olmasa məlumatların bir hissəsini “xilas etmək” mümkündür. Məsələn, fayl sətir-sətir oxunursa, ilk səhvə qədər bütün sətrləri emal etmək olar.
Ehtiyat nüsxələrdən istifadə (backup)
Ciddi proqramlar çox vaxt yazmadan əvvəl vacib faylların ehtiyat nüsxələrini yaradır. Əsas fayl zədələnibsə, məlumatları ehtiyat nüsxədən bərpa etməyə cəhd etmək olar.
3. Təcrübə: Gözlənilməz son (EOF) ilə faylın oxunması
Klassik vəziyyət
Tutaq ki, bizdə ardıcıl şəkildə int tipli ədədlər yazılmış binar fayl var. Proqram onların dəqiq 5 ədəd olacağını gözləyir, amma fayl zədələnib və cəmi 3 ədəd yazılıb.
import java.io.*;
public class DamagedFileExample {
public static void main(String[] args) {
String filename = "numbers.bin";
// Nümunə üçün: 5 əvəzinə 3 ədəd olan fayl yaradırıq
try (DataOutputStream out = new DataOutputStream(new FileOutputStream(filename))) {
out.writeInt(42);
out.writeInt(7);
out.writeInt(2024);
// out.writeInt(1); out.writeInt(2); // yazmırıq — qəsdən!
} catch (IOException e) {
System.err.println("Fayl yaradılarkən səhv: " + e.getMessage());
}
// İndi 5 ədədi oxumağa cəhd edək
try (DataInputStream in = new DataInputStream(new FileInputStream(filename))) {
for (int i = 0; i < 5; i++) {
int number = in.readInt();
System.out.println("Oxunan ədəd: " + number);
}
} catch (EOFException e) {
System.err.println("Fayl gözlənilmədən sona çatdı! Ola bilsin, o zədələnib.");
} catch (IOException e) {
System.err.println("Oxuma xətası: " + e.getMessage());
}
}
}
Çıxış:
Oxunan ədəd: 42
Oxunan ədəd: 7
Oxunan ədəd: 2024
Fayl gözlənilmədən sona çatdı! Ola bilsin, o zədələnib.
İlk xətaya qədər oxuma
Çox vaxt məlumatları istisna yaranana qədər dövrədə oxumaq məntiqlidir. Beləcə heç olmasa informasiyanın bir hissəsini əldə etmək olar.
try (DataInputStream in = new DataInputStream(new FileInputStream(filename))) {
while (true) {
try {
int number = in.readInt();
System.out.println("Oxunan ədəd: " + number);
} catch (EOFException e) {
System.out.println("Məlumatlar bitdi (və ya fayl zədələnib).");
break;
}
}
} catch (IOException e) {
System.err.println("Oxuma xətası: " + e.getMessage());
}
4. Mətn faylları və kodirovkalarla iş
Kodirovka problemi
Əgər fayl bir kodirovkada yazılıb, başqa kodirovkada oxunursa, dekodlaşdırma səhvləri mümkün ola bilər:
import java.nio.charset.*;
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream("tasks.txt"), "UTF-8"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (MalformedInputException e) {
System.err.println("Kodirovka xətası! Fayl zədələnib və ya UTF-8-də yazılmayıb.");
} catch (IOException e) {
System.err.println("Oxuma xətası: " + e.getMessage());
}
Vacibdir: Bəzən istisna əvəzinə “qarmaqarışıq simvollar” alacaqsınız — bu da zədələnmə və ya səhv kodirovka əlamətidir.
Necə həll etmək olar?
- İstifadəçiyə problem barədə məlumat verin.
- Faylı başqa kodirovkada açmağa cəhd edin.
- Məlumatlar kritikdirsə — ehtiyat nüsxədən bərpa təklif edin.
5. Məlumatların bərpası: strategiyalar
Qismən düzgün məlumatların oxunması
Faylın strukturu imkan verirsə, səhvə qədər oxuna bilən məlumatları “çıxarmaq” olar. Məsələn, fayl sətirlər siyahısıdırsa (bir tapşırıq — bir sətir), bütün sətrləri nasazlığa qədər emal etmək mümkündür.
try (BufferedReader reader = new BufferedReader(new FileReader("tasks.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
// sətrin işlənməsi
}
} catch (IOException e) {
System.err.println("Oxuma xətası: " + e.getMessage());
// Artıq oxunmuş məlumatları saxlamaq və ya istifadəçiyə bərpa təklif etmək olar
}
Backup-fayllardan istifadə
Əgər siz əvvəlcədən faylın nüsxəsini yaradırsınızsa (məsələn, tasks.txt.bak), məlumatları ondan bərpa etmək olar:
File original = new File("tasks.txt");
File backup = new File("tasks.txt.bak");
if (!original.exists() && backup.exists()) {
// Ehtiyat nüsxəni orijinalın yerinə kopyalayırıq
Files.copy(backup.toPath(), original.toPath(), StandardCopyOption.REPLACE_EXISTING);
System.out.println("Ehtiyat nüsxədən bərpa tamamlandı.");
}
Kontrol cəmləri və validasiya
Vacib fayllar üçün kontrol cəmi (məsələn, MD5 və ya SHA-256) saxlamaq və hər açılışda onu aktualla müqayisə etmək olar. Əgər uyğun gəlmirsə — fayl zədələnib.
// Təxmini sxem (sadəlik üçün heşləmənin reallaşdırılması buraxılıb)
String expectedHash = "..."; // əvvəl saxlanmış cəm
String actualHash = calculateFileHash("tasks.txt");
if (!expectedHash.equals(actualHash)) {
System.out.println("tasks.txt faylı zədələnib! Ehtiyat nüsxədən bərpa etməyə cəhd edin.");
}
6. Zədələnmiş faylların emalında tipik səhvlər
Səhv №1: Fayl formatı yoxlanmır. Əgər gözləyirsinizsə ki, hər sətir məsələn ədəddir, amma orada mətn çıxırsa — NumberFormatException yaranacaq. Məlumatı oxuduqca validasiya etmək daha yaxşıdır.
Səhv №2: try-with-resources istifadə olunmur. try-with-resources istifadə etməsəniz, fayl hətta səhv zamanı belə “asılı” (bağlanmamış) qala bilər ki, bu da bərpanı və ya silməni çətinləşdirir.
Səhv №3: Ehtiyat nüsxə yaratmadan zədələnmiş faylın üzərinə yazmaq. Səhv zamanı faylın dərhal üzərinə yazsanız, bərpa şansı azalır. Əvvəlcə backup saxlamaq daha yaxşıdır.
Səhv №4: Məlumatlandırmadan bərpa. İstifadəçi faylın zədələnib ehtiyat nüsxədən bərpa olunduğunu bilməlidir — əks halda niyə bəzi məlumatların itdiyini anlaya bilməz.
GO TO FULL VERSION