c# jak sprawdzić ilość plikow w danym katalogu?

0

Witam.
za pomocą poniższej funkcji ustalam sobie katalog w ktorym chciałbym sprawdzić ilość plików o danym rozszerzeniu. jezeli we wskazanym katalogu są podkatalogi to zapisuje je sobie w ComboBoxie (dla innych celów).

if (DialogResult.OK == FolderSet.ShowDialog())
            {
                // Folder został wybrany
                DirCondition.Text = FolderSet.SelectedPath;
                DirConditionList.Items.Clear();
                string[] TabKat = Directory.GetDirectories(DirCondition.Text);
                foreach (string DirKat in TabKat)
                {
                    string[] Sciezka = DirKat.Split(new char[] { '\\' });
                    foreach (string SCR in Sciezka) Katalog = SCR;
                    DirConditionList.Items.Add(Katalog);
                }
             }
```
Po wybraniu katalogu chciałbym przeszukać jego zawartość (wraz z podkatalogami) czy znajdują sie tam pliki o danym rozszerzeniu. i danej wielkości (pliki które chce znaleźć , zawsze mają 1696 (0x6A0) bajtów)
Czy jest jakaś gotowa funkcja aby tego dokonać ?
0

Możesz skorzystać z metod Path.GetExtension, Directory.GetFiles oraz właściwości FileInfo.Length:

string[] filesPaths = Directory.GetFiles(dirPath);
int matchingFilesCount = 0;
foreach (string path in filesPaths)
{
    if (Path.GetExtension(path) == myExtension && new FileInfo(path).Length == 1696)
    {
        matchingFilesCount++;
    }
}

Warto się zastanowić także nad potencjalną osobną funkcją sprawdzającą warunki:

bool MatchesConditions(string filePath)
{
    return Path.GetExtension(filePath) == myExtension
        && new FileInfo(filePath).Length == 1696;
}
string[] filesPaths = Directory.GetFiles(dirPath);
int matchingFilesCount = 0;
foreach (string path in filesPaths)
{
    if (MatchesConditions(path))
    {
        matchingFilesCount++;
    }
}
2

GetFiles przyjmuje też pattern w konstruktorze, którego możesz użyć do wyszukiwania plików z konkretnym rozszerzeniem https://docs.microsoft.com/pl-pl/dotnet/api/system.io.directory.getfiles?view=netframework-4.8 co powinno wpłynąć na szybkość rozwiązania. Możesz też od razu dostać listę wraz z podkatalogami

0

Ogólnie jest tak, ze już przy Waszej pomocy sobie poradziłem z przeszukaniem podkatalogów w celu znalezienia plików o spełniających kryteriach - dziękuje bardzo ;-)

Ale... napotkałem następny problem. Pliki, które wyszukuje są plikami o tej samej długości bajtów, plik ten zawiera kondycje technologiczne, zawierają takie dane, jak prędkość w mm/min, czas w sekundach itd. Oczywiste dla mnie było, aby te pliki sobie wczytać do tablicy byte, założyłem również, ze w tych plikach bajty odpowiadające za dane parametry będą w tych samych miejscach, wiec odczytując jakiś parametr, wystarczy, ze podam ofset, niestety gdy otrzymałem wszystkie pliki kondycji a jest ich prawie 400szt , to okazało się ze niestety pliki są tej samej długości, to dane w nich nie są zawsze na tych samych miejscach ;-(

W zawartości każdego pliku są dane podstawowe, jak np, informacja o tym do czego służy dana kondycja. przed odczytaniem wszystkich plików chciałem sobie załadować do jakiegoś combobox lub do jakiejś tabeli podstawowe informacje w celu późniejszego wyboru dokładnie jednej z nich i wczytać ją ze wszystkimi danymi do późniejszej edycji. Ponieważ dane są w rożnych miejscach to musiałbym odczytać cały plik, zdekodować z niego dane i podstawowe dane załadować do comboboxa, Zastanawiałem się czy może nie lepiej by było wczytać wszystkie 400 plików i zapamiętać je w jakiś tablicach.

Możecie mi doradzić jak podejść do tego tematu ?

0

[OT]aż się prosi o użycie bazy zamiast plików ale rozumiem, że pliki to zewnętrzne rozwiązanie[/OT]
wg mnie rozwiązanie z wczytaniem wszystkich plików na starcie i ich zdekodowanie do jakiejś logicznej struktury ma sens, szczególnie że tych danych nie będzie jakoś dużo (1000 plików po 2kB, doliczając nawet narzut struktur w które to opakujesz nie powinno zająć więcej jak 10-20MB w pamięci)

0

Oki, więc można by spróbować załadować pliki do tablic, musiałbym dynamicznie stworzyć tablice dla danych z plików i drugą tablice z listą tych plików. mógłby mi ktoś naświetlić jak to zrobić (kiedyś próbowałem zrobić jakieś tablice dynamicznie ale nie doszedłem do tego co robiłem źle, i zastosowałem inne rozwiązanie ) dziś nawet nie pamiętam jak ten temat ugryźć ;-(

0

Nie pisz tablicy, która synchronizuje się z inna tablicą, po indexsach, takie rzeczy można robić nisko poziomo lub w pythonie. W c# to strzał w kolano.
Nie dokonca znam Twój problem, jeśli w tych plikach są "te same" dane tylko zapisane trochę innaczej, to możesz napisać klase, lub kilka klas, z tym samym interfejsem. Każda klasa będzie posiadala ścieżke do pliku, odczytane dane jako właściwości, i metode do odczytu tych danych. Nie musi być to nic sprytnego ani wyrafinowanego, ani optymalnego. Chodzi o odciecie się od niskopoziomowego bałaganu, zebyś mógł, sobie ładnie te dane zorganizować.

0

napisać klasę, myślę.... ze to dobry pomysł, i wtedy odczytywać dane ze zmiennych w nowej klasie, niby fajny Pomysł, ale powiedz mi jak mam zdefiniować elementy danej klasy? ogólnie zakładam, ze otwierając nowy plik muszę zdefiniować nowy element stworzonej klasy, Muszę posiadać więc licznik elementów mojej klasy i odwoływać się później do każdego elementu osobno. Jak mam identyfikować później te elementy ?

0

Pomysł, ale powiedz mi jak mam zdefiniować elementy danej klasy?

Nie rozumiem, w jakim celu chcesz je później identyfikować. Nie rozumiem jaki problem chcesz rozwiązać. to za leży jakie masz dane i co chcesz znimi zrobić.

Jak mam identyfikować później te elementy
Muszę posiadać więc licznik elementów mojej klasy i odwoływać się później do każdego elementu
osobno. Jak mam identyfikować później te elementy ?

Najprościej trzymać każdą instancje klasy w liście, będzie tak jak w oryginalnym pomyśle, ale bez bólu głowy o synchronizacje 2 tablic. Klasa będzie miała pole z nazwą pliku wiec, możesz rozpoznawać je po tym.

List<int> lista = new  List<int>();
lista.Add(1);
lista.Add(22);
lista.Add(333);
Console.WriteLine(lista[1]); //22 
0

możesz pokazać strukturę tych plików? a właściwie struktury, bo mówisz że się różnią

0

w załączniku przykładowe pliki.

Wg mnie w komórce 0x10 jest offset do adresu 1 linii technologicznej i wydaje mi się, ze jest to tak:
Od adres 0x69F odejmujemy offset czyli wartość z komórki 0x10. tak uzyskany adres będzie początkiem danych 1 technologii, odczytujemy te dane aż do adresu 0x69f i przeskakujemy do adresu 0x20 aby kontynuować. Następnie pozostałe linie technologiczne są co 0x40 (w sumie 17 linii. Oprócz tego są inne dane, które muszę rozgryźć. Odczytanie 17 technologii to już połowa sukcesu. Nie wiem dlaczego i w jaki sposób jest generowany ten offset. na razie nie mam pomysłu od czego jest uzależniony :-(

0
        /// <summary>
        /// Klasa wyszukująca pliki w folderze
        /// </summary>
        public class DirectoryScan
        {
            /// <summary>
            /// Inicjuje nowe wystapienie instancji obiektu <see cref="DirectoryScan"/>
            /// </summary>
            public DirectoryScan()
            {

            }
            
            /// <summary>
            /// Wzór delegata do selekcjonowania znalezionych plików
            /// </summary>
            /// <param name="FilePatch">Ścieżka do pliku</param>
            /// <returns>Zwraca true, jeżeli plik spełnia określone zależności</returns>
            public delegate bool FileValidateDelegate(string FilePatch);
            /// <summary>
            /// Metoda wykorzystywana do selekcjonowania znalezionych plików. Zobacz <see cref="FileValidateDelegate"/>
            /// </summary>
            public FileValidateDelegate IsFileValidMethod { get; set; } = (string FilePatch) => {
                FileInfo fileInfo = new FileInfo(FilePatch);
                return (fileInfo.Length == 1696 && fileInfo.Extension == ".txt") ? true : false;
            };
            /// <summary>
            /// Wzór delegata konwertującego wyselekcjonowany plik na inny obiekt
            /// </summary>
            /// <param name="FilePatch">Ścieżka do pliku</param>
            /// <returns>Zwraca obiekt wyjściowy</returns>
            public delegate object ConvertDelegate(string FilePatch);
            /// <summary>
            /// Metoda używana do konwertowania ścieżki do wyselekcjowanego pliku na obiekt wyjściowy. Zobacz <see cref="ConvertDelegate"/>
            /// </summary>
            public ConvertDelegate ConvertMethod { get; set; } = (string FilePatch) =>
            {
                return new FileInfo(FilePatch);
            };

            /// <summary>
            /// Przeszukuje folder <see cref="DirectoryPatch"/> i wszystkie jego podfoldery w poszukiwaniu plików spełniających dane kryteria
            /// </summary>
            /// <param name="DirectoryPatch">Ścieżka do folderu</param>
            /// <returns>Zwraca wszystkie pliki spełniające kryteria</returns>
            private IEnumerable<string> ScanEveryDirectoryInPatchAndFindSpecifiedFiles(string DirectoryPatch)
            {
                IEnumerable<string> Files = Directory.GetFiles(DirectoryPatch).Where(x => IsFileValidMethod(x));
                string[] SubDirs = Directory.GetDirectories(DirectoryPatch);
                foreach (string SubDir in SubDirs)
                    Files = Files.Concat(ScanEveryDirectoryInPatchAndFindSpecifiedFiles(SubDir));
                return Files;
            }

            /// <summary>
            /// Pobiera wszystkie pliki z określonego fodleru i podfolderów, filtruje je <see cref="IsFileValidMethod"/> a następnie konwertuje na inny obiekt za pomocą <see cref="ConvertMethod"/>
            /// </summary>
            /// <param name="DirectoryPatch">Ścieżka do folderu</param>
            /// <returns></returns>
            public IEnumerable<object> FindFilesAndConvert(string DirectoryPatch)
            {
                return ScanEveryDirectoryInPatchAndFindSpecifiedFiles(DirectoryPatch).Select(x => ConvertMethod(x));
            }

        }

Zastąp **FileValidateDelegate **, następnie stwórz klasę w której będziesz przechowywał informacje pobrane z pliku i wstaw metodę konwersji na swoją klasę w miejsce ConvertDelegate.

0

Widzę, ze kolega tutaj zrobił nową klasę wyszukiwania plików ;-)

ja problem rozwiązałem w prosty sposób ;-)

  if (DialogResult.OK == FolderSet.ShowDialog())
            {
                // Folder został wybrany
                IloscPlikow = 0;
                IloscKatalogow = 0;
                DirCondition.Text = FolderSet.SelectedPath;
                DirConditionList.Items.Clear();

                string[] filesDir = Directory.GetFiles(FolderSet.SelectedPath);
                foreach (string path in filesDir)
                {
                    if (Path.GetExtension(path) == ".CNB" && new FileInfo(path).Length == 1696)
                    {
                        // w podkatalogu znajdują się pliki ".CNB"
                        // w (path) znajduje się scieżka wraz z nazwą pliku
                        // TestFilesFind.Text += ((path)+"\r\n");

                        // Wg mnie tutaj mógłbym wykorzystać moją funkcję do odczytania pliku kondycji i stworzeniu nowego obiektu
                        
                         Kondycja (path);
 
                                           
                        IloscPlikow++;
                    }
                }

                string[] TabKat = Directory.GetDirectories(DirCondition.Text);

                foreach (string DirKat in TabKat)
                {
                    // Wybrany folder posiada podfoldery
                    // liste podfolderów umieść w ComboBoxie

                    string[] filesPaths = Directory.GetFiles(DirKat);
                    foreach (string path in filesPaths)
                    {
                        if (Path.GetExtension(path) == ".CNB" && new FileInfo(path).Length == 1696)
                        {
                            // w podkatalogu znajdują się pliki ".CNB"
                            // w (path) znajduje się scieżka wraz z nazwą pliku
                            // TestFilesFind.Text += ((path) + "\r\n");

                            // Wg mnie tutaj mógłbym wykorzystać moją funkcję do odczytania pliku kondycji i stworzeniu nowego obiektu
                        
                         Kondycja (path);

                            IloscPlikow++;
                        }       
                    }              
                    string[] Sciezka = DirKat.Split(new char[] { '\\' });
                    foreach (string SCR in Sciezka) Katalog = SCR;
                    {
                        DirConditionList.Items.Add(Katalog);
                        IloscKatalogow++;
                    }
             
                }

                InfoConditionNr.Text = Convert.ToString(IloscPlikow);
                InfoDirNr.Text = Convert.ToString(IloscKatalogow);
             }

Teraz tylko interesuje mnie jak mam zrobić funkcje :

Kondycja (path)

ta funkcja musiałaby przy każdym wywołaniu:

  • odczytać cały plik do tablicy typu byte,
  • stworzyć nowy obiekt z nową klasą tupu "Technologia"
  • zapisać do zmiennych obiektu "Technologia" wszystkie parametry, które plik zawiera. (tutaj wiadomo, ze tych danych będzie bardzo dużo) ale pomysł mi się wydaje bardzo fajny.

oki to jedna sprawa.
Mam pytanie, Tworząc obiekty typu "Technologia" , których będzie około 300 to w dalszej części programu muszę jakoś mieć dostęp do tych danych,
będę musiał np do tabeli wczytać tylko kondycję, która będzie spełniała pewne kryteria. w tym celu będę musiał za każdym razem odczytać pewne zmienne klasy "Technologia" aby przefiltrować kondycje spełniające moje wyszukiwania.

Czyli w chwili gdy będę wykonywał funkcje
Kondycja(path);
muszę tworzyć obiekt np TabTechNr001, TabTechNr002, ... TabTechNr100 .... TabTechNr300,
nie wiem jak tworzyć obiekty z kolejnymi numerami ;-(

0

Nie wiem jak wygląda Twój plik z którego chcesz wczytywać dane. To ma kluczowe znaczenie, ponieważ:
Plik1.txt
Imię: Jan, Wiek: 23, Nazwisko: Kowalski
Plik2.txt
Imię: Jolanta, Wiek: 123, Nazwisko: jakaśtam

Przez to, że wartość opisująca wiek może być w sensie długości tablicy znaków różnej długości tracisz całą rozpiskę gdzie co się znajduje bajt po bajcie:
Taki przykład czytania

public static class Converter
        {
            public static string GetSurname(byte[] array, int Length)
            {
                return BitConverter.ToString(array, 0, Length);
            }
            public static int GetAge(byte[] array)
            {
                return BitConverter.ToInt32(array, 5);
            }
        }

Jeżeli to nie tajemnica wyślij chociaż część tego pliku z pozmienianymi danymi to pomogę Ci to zapisać do klasy :)

0

muszę tworzyć obiekt np TabTechNr001, TabTechNr002, ... TabTechNr100 .... TabTechNr300,
nie wiem jak tworzyć obiekty z kolejnymi numerami ;-(

Nie tworzysz obiektów z numerami, tworzysz obiekt, i dodajesz je do listy. Miałeś przykład wyżej. Nazwa obiektu nie ma specjalnego znaczenia, z puktu widzenia logiki.

0

Nie tworzysz obiektów z numerami, tworzysz obiekt, i dodajesz je do listy. Miałeś przykład wyżej. Nazwa obiektu nie ma specjalnego znaczenia, z puktu widzenia logiki.<

Właśnie chyba tego nie rozumiem ;-( nie rozumiem jak działają kolekcje obiektów (bo chyba tutaj o tym mowa )
Obiekt można zdefiniować i będzie miał zawsze taką samą stukturę. Kolekcja obiektów to taka tablica ? a jak się później odnieść do np 11 obiektu w kolekcji ? można w ogóle tak, czy tylko na zasadzie przeszukiwania wszystkich obiektów w celu znalezienia obiektu o danych cechach ?

Jeżeli to nie tajemnica wyślij chociaż część tego pliku z pozmienianymi danymi to pomogę Ci to zapisać do klasy <

wysłałem kilka plików w poprzednich postach.

1 użytkowników online, w tym zalogowanych: 0, gości: 1