CodeGym /Kurslar /C# SELF /Fayllarla işləyərkən tipik istisnalar

Fayllarla işləyərkən tipik istisnalar

C# SELF
Səviyyə , Dərs
Mövcuddur

1. Giriş: niyə fayllar "möcüzə göstərməyi" sevirlər?

Bəzən sənədi açırsan — və birdən sistem bildirir: "Fayl tapılmadı". Və ya nəsə saxlamağa çalışanda mesaj gəlir: "Giriş qadağandır". Bu elə həmin hallardır ki, fayllarla nəsə qəribə baş verir. Əgər kodlaşdırma ilə "krakozyabr" formasında rastlaşırsınızsa, burada problemlər fayl sisteminin özündən qaynaqlanır.

Fayl sistemini böyük bir kitabxana kimi təsəvvür etmək olar, tətbiq isə kitabxanaçı kimidir. Və o faylı soruşduqda müxtəlif cavablar ala bilərsiniz:

  • Kitab (yəni fayl) yoxdur — sadəcə mövcud deyil.
  • Kitabın olmalı olduğu bölmə də yoxdur — lazım olan direktoriy a mövcud deyil.
  • Kitab "qapadılıb" və ya başqasına verilib — fayl başqa proses tərəfindən istifadə olunur və ya giriş üçün hüquq yoxdur.
  • Raf doludur — yeni fayl yaratmaq üçün diskte kifayət qədər yer yoxdur.
  • Və ya məsələn, kitabı DVD qaytarma şöbəsinə qoymağa çalışırsınız — yəni dəstəklənməyən əməliyyat həyata keçirilir.

C# dilində bütün bu situasiyalar istisnalar vasitəsilə ifadə olunur. İnkişaf etdiricinin vəzifəsi — proqramın "yıxılmasını" müşahidə etmək deyil, mümkün problemləri qabaqcadan proqnozlaşdırmaq və onları səliqəli emal etməkdir. Heç kimin istifadəçiyə anlaşılmaz səhv mesajı göstərilməsini istəməz.

Biz artıq try-catch konstruksiyası ilə tanışıq. Bu bizim xilasedici halqadır, istisnanı "tutmağa" və proqramın qəfil dayanmasının qarşısını almağa imkan verir.

// Bu bizim tanış nümunəmizdir, Leksiya 57-dən xatırlatma
try
{
    // Burada səhv verə biləcək kod yazırıq
    // Məsələn, faylı oxumağa cəhd
}
catch (Exception ex) // Hər hansı istisnanı tuturuq
{
    // Səhvi burada emal edirik
    Console.WriteLine($"Ay, səhv baş verdi: {ex.Message}");
}

Bugün fayllarla işləyərkən yaranan spesifik istisnalara daha dərindən baxacağıq. Bu bizə daha etibarlı kod yazmağa kömək edəcək — kod fayl sistemi ilə "söhbət" edə bilsin, hətta o "xasiyyətsiz" olanda belə.

İstisnalar — bu səhv deyil, kömək siqnalıdır!

Vacibdir ki, başa düşəsiniz: istisna həmişə sizin kodda səhv demək deyil. Çox vaxt bu, sizin kodun qarşılıqlı əlaqədə olduğu xarici mühitdə nəsə səhv getdiyinin siqnalıdır. Fayl sistemi — belə xarici mühitin aydın nümunəsidir. Faylı oxumaq üçün tam düzgündür yazılmış kodunuz ola bilər, amma əgər istifadəçi proqram onu oxumazdan əvvəl faylı sildisə, siz istisna alacaqsınız. Bu normaldır! İnkişaf etdirici kimi vəzifəniz — proqramı belə situasiyalara cavab verməyi öyrətməkdir.

Gəlin fayllarla işləyərkən ən çox rast gəlinən "kömək siqnallarına" baxaq.

2. FileNotFoundException: fayl heç olmayıb

Bu, fayllarla işləyərkən ən çox rast gəlinən istisnalardan biridir. O, göstərilmiş yolda mövcud olmayan fayla açma, oxuma və ya digər əməliyyat etmək cəhdində yaranır.

Həyat nümunəsi: dostunuzdan sizə "C# 14 üçün başlanğıclar" adlı kitab gətirməsini xahiş edirsiniz, o isə cavab verir: "Belə kitabım yoxdur". Eyni şəkildə proqramınız əməliyyat sistemindən soruşa bilər: "Mənə settings.txt faylını ver", sistem isə cavab verə bilər: "Bağışlayın, belə fayl yoxdur".

Gəlin abracadabra.txt faylını oxuyan kod nümunəsi yazmağa çalışaq. Fayl yoxdursa, istifadəçiyə bunu bildirməliyik, təkcə proqramı "yıxmaq" olmaz.

try
{
    using var reader = new StreamReader("abracadabra.txt");
    Console.WriteLine(reader.ReadToEnd());
}
catch (FileNotFoundException ex)
{
    Console.WriteLine("Fayl tapılmadı: " + ex.FileName);
}

Gündəlik həyatda bu dayanacaqda avtobusun olmaması və marşrutkanın da gəlməməsi kimidir. Kədərli.

Qeyd: Tez-tez bu istisna səhv yol ilə birlikdə gəlir (məsələn, başqa direktoriyadan işlədiyinizi unudursunuz).

3. DirectoryNotFoundException: qovluqlar hardasa yoxa çıxıblar

Bu istisna FileNotFoundException-ə çox oxşardır, amma faylın özündən yox, onun yerləşdiyi direktoriyadan (qovluq) danışır. Məsələn, yol göstərmisiniz: "C:\MyDocuments\MyProject\Data\report.txt", amma Data qovluğu mövcud deyilsə, DirectoryNotFoundException alacaqsınız.

Tətbiqimizdə əgər parametrləri data altqovluğunda, məsələn, "./data/app_settings.txt" saxlamaq istəsəydik və bu qovluq yox idisə, faylı yazmağa və ya oxumağa çalışanda bu problem çıxardı.

DirectoryNotFoundException-ı ayrıca tutmaq olar, FileNotFoundException kimi, və ya o daha ümumi IOException-ın bir hissəsi ola bilər — bu haqda sonra danışacağıq.

try
{
    using var writer = new StreamWriter(@"C:\very\strange\path\file.txt");
    writer.WriteLine("Hello world");
}
catch (DirectoryNotFoundException ex)
{
    Console.WriteLine("Qovluq tapılmadı!");
}

Tez-tez rast gəlinən səhv: Qovluq istənilən vaxt silinə bilər (məsələn, kiminsə temp fayllarını təmizləməsi), və ya yazı üçün yol səhv göstərilmiş ola bilər.

4. UnauthorizedAccessException: giriş qadağandır!

Təsəvvür edin ki, kitabı rafa qoymaq istəyirsiniz, amma orada lövhədə yazılıb: "Yalnız əməkdaşlar üçün". Bu məhz UnauthorizedAccessException deməkdir! Bu, proqramınızın fayla və ya qovluğa giriş üçün lazım olan hüquqa malik olmadıqda yaranır. Səbəblərdən bəziləri:

  • İstifadəçi hüquqları yetərsizdir: Faylı yalnız administrator yaza bilən qovluğa yazmağa çalışırsınız (məsələn, C:\Windows).
  • Fayl "yalnız oxu" olaraq işarələnib: Dəyişdirməyə çalışdığınız fayl "yalnız oxu" atributuna malikdir.
  • Fayl sistem və ya gizli sistem faylıdır: Və ona xüsusi məhdudiyyətlər tətbiq olunub.

Bu korporativ mühitlərdə və ya istifadəçilər proqramları qorunan direktoriyalara quraşdırdıqda çox rast gəlinən problemdir.

Gəlin sistem qovluğuna fayl yazmağa çalışaq — adi istifadəçiyə icazə olmayan yerə. (Diqqət: belə kodu admin hüquqları olmadan çalışdırmaq təhlükəsizdir, amma sistem direktoriyalarını qarışdırmamağa diqqət edin).

try
{
    using var writer = new StreamWriter("/system/settings.conf");
    writer.WriteLine("Bütün güc tələbələrə!");
}
catch (UnauthorizedAccessException ex)
{
    Console.WriteLine("Fayla və ya qovluğa giriş yoxdur!");
}

Əgər bu kodu administrator hüququ olmadan işə salsanız, çox güman ki, "Bu qovluğa giriş qadağandır" mesajını görəcəksiniz. Əgər administrator kimi işə salsanız, fayl yaradılacaq. Bu nümunə göstərir ki, UnauthorizedAccessException-ı emal etmək vacibdir ki, istifadəçi niyə əməliyyatın yerinə yetirilmədiyini başa düşsün.

5. IOException: fayl sisteminin universal "ay-ay"

IOException — input/output əməliyyatları ilə bağlı ən ümumi istisnadır. O, giriş-çıxış cihazı və ya fayl sistemi ilə bağlı, daha spesifik istisnalara (məsələn, FileNotFoundException və ya UnauthorizedAccessException) aid olmayan problemlər yarananda atılır.

Tipik ssenarilər, IOException ala biləcəyiniz hallardır:

  • Fayl başqa proqram tərəfindən istifadə olunur: Məsələn, silməyə çalışdığınız fayl Notepad və ya başqa proqramda açıqdır.
  • Disk doludur: Faylı yazmaq üçün kifayət qədər yer yoxdur.
  • Fayl və ya fayl sistemi zədələnib: Nadirdir, amma baş verə bilər.
  • Şəbəkə problemləri: Fayl şəbəkə diskindədirsə və əlaqə kəsilərsə.
  • Fayl və ya qovluq adı çox uzundur. (Bu bəzən PathTooLongException-a aid edilir, amma bəzən IOException-a düşə bilər).

IOException — bir çox problemlər üçün "universal açardır". Tez-tez bu istisnanı tutduqda onun Message xassəsinə baxmaq məsləhətdir, orada daha dəqiq nə baş verdiyi göstərilir.

try
{
    using var file = new FileStream("busyfile.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.None);
    // bir yerdə faylı açıq saxlayırıq
    // eyni vaxtda başqa yerdə:
    using var writer = new StreamWriter("busyfile.txt");
    writer.WriteLine("Yazmaq cəhdi...");
}
catch (IOException ex)
{
    Console.WriteLine("Giriş-çıxış səhvi: " + ex.Message);
}

Vacib məqam: IOException — bir çox "fayl" istisnalarının baza sinifidir.

6. Digər, amma əhəmiyyətli "narahatlıqlar"

PathTooLongException

Bu daha az tez-tez olsa da rast gəlinən problemdir: yolunuz (və ya fayl/qovluq adı) əməliyyat sistemi üçün çox uzundur. Məsələn, fayl adında "Vətən müharibəsi və sülhün qısa xülasəsi" kimi uzun təsvirlər qoysanız, Windows buna rəğbət göstərməyə bilər.

Windows-da tarixi məhdudiyyət — tam yol üçün 260 simvol. Yeni OS və .NET versiyaları "uzun yolları" aktiv etməyə imkan verir, amma bu hər zaman defolt üzrə işə düşmür.

try
{
    string veryLongPath = new string('a', 300); // 300 simvol!
    using var writer = new StreamWriter(veryLongPath + ".txt");
    writer.WriteLine("Bu çox uzun fayl adıdır!");
}
catch (PathTooLongException ex)
{
    Console.WriteLine("Fayl adı və ya yol çox uzundur!");
}

NotSupportedException

Bu nadir, amma "surrealist" haldır: StreamReader və ya FileStream kimi konstruktora yolverilməz simvol və ya qadağan olunmuş yol (məsələn, C:::\wow???\file.txt) verirsinizsə yaranır.

7. Faydalı nüanslar

Hansı istisna nə üçündür

İstisna Səbəb Nümunə situasiya
FileNotFoundException
Fayl tapılmadı Mövcud olmayan faylı açmaq
DirectoryNotFoundException
Qovluq tapılmadı Silmış qovluqdakı faylı açmaq
UnauthorizedAccessException
Fayla/qovluğa giriş yoxdu (hüquqlar) Mühafizə olunan qovluğa yazmaq
IOException
Ümumi giriş-çıxış səhvi Fayl başqa prosesdə açıqdır
PathTooLongException
Yol çox uzundur Çox uzun fayl/qovluq adı
NotSupportedException
Yolun formatı düzgün deyil Qadağan olunmuş simvollu yol

Tez-tez rast gəlinən səhvlər və xüsusi hallar

Nümunə: Fayl başqa prosesdə məşğuldur

Təsəvvür edin ki, həqiqi hacker kimi Notepad-də mətn faylını açmısınız və bağlamağı unutmusunuz. Eyni anda proqramınız həmin fayla yazmağa çalışır. Belə vaxt IOException (və ya "sharing violation") gəlir.

Nümunə: Giriş yoxdur

Məlumatları C:\Windows-a administrator hüququ olmadan saxlamağa çalışın — UnauthorizedAccessException alacaqsınız. Eyni hal faylı yalnız oxumaq üçün açıb ona yazmağa çalışanda da baş verə bilər.

Nümunə: Yanlış yol

Windows-da fayl adlarında <>:"/\|?* simvolları istifadə etmək olmaz. Belə fayl yaratmağa çalışsanız — NotSupportedException (və ya ArgumentException) ala bilərsiniz.

Nümunə: Diskdə yer yoxdur

Bu da bəzən IOException ilə əks olunur — məsələn, disk doludursa (bəzi istifadəçilərə Downloads qovluğunu vaxt-vaxt xatırlatmaq lazımdır).

Səhvə düşməmək üçün ən yaxşı təcrübələr

  • Faylın mövcudluğunu File.ExistsDirectory.Exists ilə yoxlayın əvvəl faylı açmağa cəhd etməzdən. Amma diqqətli olun: fayl yoxlama ilə açma arasında yoxa çıxa və ya yaranmış ola bilər (klassik race condition).
  • Heç vaxt istisnaları tamamilə "udmayın" (sadəcə catch { } etməyin), əgər siz ciddi logger yazmırsınızsa. Həmişə ən azı loq daxil edin və ya istifadəçiyə nə baş verdiyini göstərin.
  • Mümkün qədər konkret istisnaları tutmağa çalışın (FileNotFoundException, DirectoryNotFoundException), yalnız ümumi Exception-ı tutmaqla kifayətlənməyin.
  • Cross-platform tətbiqlərdə nəzərə alın: hüquqlar, yol formatları, fayl adlarının uzunluğu — Windows, Linux, macOS-da fərqlidir.
  • Mətn faylları ilə işləyirsinizsə, hər zaman lazım olan kodlaşdırmanı açıq şəkildə göstərin — əks halda sürprizlər qaçılmazdır.
  • Massiv fayl əməliyyatları üçün "bulk" emal istifadə edin və hər addımda mümkün uğursuzluqları nəzərə alın.

Tipik istisnalar üzrə xülasə cədvəli

İstisna Nə zaman yaranır? Necə qarşısını almaq/idarə etmək?
FileNotFoundException
Göstərilən yolda fayl yoxdur File.Exists ilə yoxlayın və ya faylı yaradın
DirectoryNotFoundException
Yolda mövcud olmayan qovluq var Yolu yoxlayın, Directory.CreateDirectory ilə qovluqları yaradın
UnauthorizedAccessException
Fayla/qovluğa giriş yoxdu, fayl yalnız oxu, fayl başqa prosesdədir Doğru istifadəçi ilə işə salın, ACL-ləri yoxlayın, faylları düzgün bağlayın
IOException
Ümumi I/O səhvi, fayl məşğul, diskdə yer yoxdur try-catch istifadə edin, faylları açıq saxlamamağa çalışın
PathTooLongException
Yol və ya fayl adı çox uzundur Yolu qısaldın, nisbətən yollar istifadə edin
NotSupportedException
Yolun formatı düzgün deyil Yol sətrini qadağan simvollara görə yoxlayın

Blok-sxem "Fayl səhvi olanda nə etmək lazımdır?"

flowchart TD
    A[Fayl əməliyyatı] --> B{İstisna atıldı?}
    B -- Yox --> C[Əməliyyat uğurla tamamlandı]
    B -- Bəli --> D{Hansı növ istisnadır?}
    D -- FileNotFound --> E[Istifadəçidən doğru faylı soruşun və ya yaradın]
    D -- DirectoryNotFound --> F[Olmayan qovluğu yaradın]
    D -- UnauthorizedAccess --> G[İstifadəni lazımınca hüquqlarla yenidən işə salmağı xahiş edin]
    D -- IOException --> H[Faylı kim istifadə edir yoxlayın, diski yoxlayın]
    D -- PathTooLong --> I[Yolu qısaldın]
    D -- NotSupported --> J[Yol formatını yoxlayın]
    D -- Other --> K[Mesaj göstərin və logları yoxlayın]

8. Tipik istisnalar real tətbiqdə necə görünür?

Tədris layihəmizi inkişaf etdirərkən düşünək ki, istifadəçi qeydlərini faylda saxlayan və sonra onları oxuyan mini proqramımız var.

string notesPath = "notes.txt";

Console.Write("Qeyd daxil edin: ");
string note = Console.ReadLine();

try
{
    // Qeydi saxlayırıq
    using var writer = new StreamWriter(notesPath, true, Encoding.UTF8);
    writer.WriteLine(note);

    // Bütün qeydləri oxuyuruq
    Console.WriteLine("Sizin qeydləriniz:");
    using var reader = new StreamReader(notesPath, Encoding.UTF8);
    Console.WriteLine(reader.ReadToEnd());
}
catch (FileNotFoundException)
{
    Console.WriteLine("Qeyd faylı tapılmadı. Onu əl ilə yaradın və yenidən yoxlayın.");
}
catch (DirectoryNotFoundException)
{
    Console.WriteLine("Qeyd faylına gedən yol səhvdir. Qovluğun mövcudluğunu yoxlayın.");
}
catch (UnauthorizedAccessException)
{
    Console.WriteLine("Faylı yazmaq və ya oxumaq üçün hüquq yoxdur. Proqramı administrator kimi işə salın.");
}
catch (IOException ex)
{
    Console.WriteLine("Giriş-çıxış zamanı səhv baş verdi: " + ex.Message);
}
catch (Exception ex)
{
    Console.WriteLine("Gözlənilməz səhv: " + ex.Message);
}

Bu nümunədə tipik vəziyyət göstərilir: qeydi fayla yazmaq və sonra onu geri oxumaq cəhdi. Hər catch bloku müəyyən növ səhvi emal edir — fayl və ya qovluğun olmamasından tutmuş hüquq problemlərinə və ümumi I/O səhvlərinə qədər. Bu yanaşma proqramın ilk uğursuzluqda "yıxılmasının" qarşısını alır və istifadəçiyə nə baş verdiyini və nə etmək lazım olduğunu bildirir. Belə praktika tətbiqi daha etibarlı və dostyana edir.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION