Inna twórczość > Platforma .NET

[C#] Obsługa błędów I/O

(1/5) > >>

MajkeI:
Napisałem prosty program konsolowy - podajemy ścieżkę i zamienia nazwy wszystkich plików w danym katalogu na takie same, tylko z wielkich liter.

Spoiler
--- Kod: ---using System;
using System.IO;

namespace Program {
    class Program {
        static void Main(string[] args) {
            string[] filePaths;
            while (true) {
                Console.Clear();
                Console.WriteLine("Input directory");
                filePaths = Directory.GetFiles(Console.ReadLine());

                if (filePaths.Length == 0) {
                    Console.WriteLine("No files in this directory!");
                } else {
                    Console.Clear();
                    Console.WriteLine("Changed files: ");

                    for (int i = 0; i < filePaths.Length; i++)
                    {
                        File.Move(filePaths[i], filePaths[i].ToUpper());
                        filePaths[i] = Path.GetFileName(filePaths[i]);
                        Console.WriteLine((i + 1) + ". " + filePaths[i]);
                    }
                }
               
                Console.ReadLine();
            }
        }
    }
}

--- Koniec kodu ---

Moje pytanie - jak zrobić obsługę błędów? Chodzi mi o przypadek, gdzie podamy błędną ścieżkę do folderu.
Znalazłem jakieś "DirectoryNotFoundException" jednak nie umiem z tego skorzystać. Ktoś pomoże?

EDIT: Ok, wykombinowałem - tylko, czy pod względem "czystości kodu" jest to dobrze zrobione?
Spoiler
--- Kod: ---using System;
using System.IO;

namespace Program
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] filePaths;
            while (true)
            {
                Console.Clear();
                Console.WriteLine("Input directory");
                try
                {
                    filePaths = Directory.GetFiles(Console.ReadLine());

                    if (filePaths.Length == 0)
                        Console.WriteLine("No files in this directory!");
                    else
                    {
                        Console.Clear();
                        Console.WriteLine("Changed files: ");

                        for (int i = 0; i < filePaths.Length; i++)
                        {
                            File.Move(filePaths[i], filePaths[i].ToUpper());
                            filePaths[i] = Path.GetFileName(filePaths[i]);
                            Console.WriteLine((i + 1) + ". " + filePaths[i]);
                        }
                    }
                }
                catch (DirectoryNotFoundException)
                {
                    Console.WriteLine("Directory is incorrect!");
                }
                Console.ReadLine();
            }
        }
    }
}

--- Koniec kodu ---

Hmm to tak przy okazji - jak zrobić, żeby przeszukiwało również podfoldery podanego katalogu?

inż. Avallach:
To nie jest czysty kod (ale dobrze że chociaż znasz to pojęcie).

Wyjątki, jak nazwa wskazuje, służą do obsługi sytuacji wyjątkowych. Takich których nie da się z góry przewidzieć i które normalnie raczej się nie powinny zdarzać. Czy podanie przez użytkownika złej ścieżki do folderu jest taką? Nie. To dość typowa sytuacja i można łatwo ją przewidzieć zanim spróbujesz coś z tego folderu odczytać (co spowodowałoby wyjątek). Po prostu użyj metody Directory.Exists(string path). Jeśli folder nie istnieje, to męcz użytkownika (nawet i do skutku) o podanie poprawnej ścieżki. A dopiero kiedy masz ścieżkę która istnieje, to z niej czytaj.

Ogólna zasada jest taka: nie próbuj obsługiwać wyjątków, których wystąpieniu możesz zapobiec. Prawie zawsze zapobieżenie wyjątkowi jest lepsze dla programu niż łapanie go. Sama próba łapania wyjątku jest darmowa. Jeśli wyjątek nie wystąpi, program nic nie "płaci". Ale jeśli już wystąpi, to cena jest nieprzyjemna i lepiej jej unikać.

Co do przeszukiwania katalogów - wyciągnij z tego osobną metodę i wywołuj ją rekursywnie na każdym podkatalogu znalezionym w obecnie przerabianym katalogu.

Z innych uwag - masz pętlę while (true) i żadnego wyjścia z niej. To bardzo nieeleganckie - jedynym sposobem na wyjście z takiej aplikacji jest zabicie jej.

MajkeI:
Ok, zgodnie z Twoimi wskazówkami:
Spoiler
--- Kod: ---using System;
using System.IO;
namespace Program
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] filePaths;
            ConsoleKeyInfo key;
            while (true)
            {
                Console.Clear();
                Console.WriteLine("Input directory");
                string path = Console.ReadLine();
                if (!Directory.Exists(path))
                    Console.WriteLine("Directory is incorrect!");
                else
                {
                    filePaths = Directory.GetFiles(path);
                    if (filePaths.Length == 0)
                        Console.WriteLine("No files in this directory!");
                    else
                        Console.WriteLine("Changed files: ");
                    for (int i = 0; i < filePaths.Length; i++)
                    {
                        File.Move(filePaths[i], filePaths[i].ToUpper());
                        filePaths[i] = Path.GetFileName(filePaths[i]);
                        Console.WriteLine((i + 1) + ". " + filePaths[i]);
                    }
                }
                Console.WriteLine("\n(Press ESCAPE to exit)");
                key = Console.ReadKey();
                if (key.Key == ConsoleKey.Escape)
                    return;
            }
        }
    }
}

--- Koniec kodu ---
Czy teraz jest ok? Da się z tego zrobić "clean code"? Na czym to polega?
A co mam zrobić jak chodzi o przeszukiwanie tych podfolderów?

inż. Avallach:
Nie musisz robić zmiennej key jeśli nie chcesz używać informacji o klawiszu nigdzie indziej. Wystarczy sprawdzić warunek:

--- Kod: ---if (Console.ReadKey().Key == ConsoleKey.Escape)
--- Koniec kodu ---
Zmienną wywal.
No i cytuję:

--- Cytat: Avallach w 2015-05-26, 22:21 ---Co do przeszukiwania katalogów - wyciągnij z tego osobną metodę i wywołuj ją rekursywnie na każdym podkatalogu znalezionym w obecnie przerabianym katalogu.

--- Koniec cytatu ---
Wyciąganie metod jest ściśle związane z pojęciem czystego kodu. Czy możesz w zwięzłym zdaniu powiedzieć co robi twoja metoda? Nie, bo w tej jednej metodzie jest cały twój program. Ona robi dużo różnych rzeczy składających się z mniejszych czynności. Tak nie powinno być. Jeśli potrafisz określić z jakich kroków to się składa, to naprawdę podziel ją na takie kroki. Jutro jak będę miał chwilę pokażę ci jak bym to zrobił, na razie spróbuj sam. Kodu nie musisz zmieniać, chodzi o poprzestawianie go do osobnych metod tam gdzie ma to sens (takie miejsce jest co najmniej jedno).

Sawik:
Avallach popraw mnie jeśli się mylę: 
W czystym kodzie metoda odpowiada za określoną czynność np. kopiuj tekst, zapisz do pliku, dzięki czemu nazewnictwo jest proste i logiczne. 

Nawigacja

[0] Indeks wiadomości

[#] Następna strona

Idź do wersji pełnej