Liczenie plików w katalogach ograniczenie biblioteki

0

Witam.

Jak poradzić sobie z ograniczeniem chamskiej biblioteki:

An unhandled exception of type 'System.OutOfMemoryException' occurred in Delimon.Win32.IO.dll
Delimon.Win32.IO.DLL

Folder na którym się wysypuje tą piękną informacją ma 1,7 mln plików. Gdy miał ich znacznie mniej (600 tyś) problemu nie było ...

Funkcja na której się sypie (cholera wie czemu właśnie na niej.... przecież w niej nie ma plików spełniających kryteria nazwy:

  pliki_cd_dodawanie = (
        from plik in Delimon.Win32.IO.Directory.GetFiles(di.FullName, "*.*", Delimon.Win32.IO.SearchOption.AllDirectories)
            where (plik.Contains("cd1") || plik.Contains("cd 1") || plik.Contains("CD1") ? true : plik.Contains("CD 1"))
                    select plik).Count();
0

Funkcja na której się sypie (cholera wie czemu właśnie na niej.... przecież w niej nie ma plików spełniających kryteria nazwy:

Zapytam: a to nie jest tak, że najpierw tworzysz kolekcję plików, których nazwa spełnia kryteria *.* (czyli wszystko) która zawiera te 1.7miliona plików

a dopiero później przeszukujesz te 1.7miliona używając kryteriów:

plik.Contains("cd1") || plik.Contains("cd 1") || plik.Contains("CD1") ? true : plik.Contains("CD 1")

i dlatego brakuje Ci ramu, bo wpakowałeś 1.7miliona?


btw:

Co sądzisz o Directory.GetFiles? (to zwraca kolekcje ścieżek typu "C:\Windows\test.file", ale przecież da się wyodrębnić końcówkę "test.file")

Co sądzisz o zastosowaniu nazwa_pliku.ToLower()? aby zamiast sprawdzania CD1 i cd1, to sprawdzać tylko cd1

https://msdn.microsoft.com/pl-pl/library/07wt70x2(v=vs.110).aspx

var arr = Directory.GetFiles(@"C:\Windows");

int filesCount = 0;
foreach (var c in arr)
{
    if (c.ToLower().Contains("cd1"))
    {
        Console.WriteLine(c);
        filesCount++;
    }
}
Console.WriteLine(filesCount);

albo takie?

public static bool nameIsValid(string name)
{
    name = name.ToLower();
    return name.Contains("cd") || name.Contains("cd1");
}

var arr = Directory.GetFiles(@"C:\test_files").Where(x => nameIsValid(x));
1

Nie rozumiem po co pobierać wszystkie pliki, a potem je filtrować jakimiś pętlami czy LINQ, zamiast po prostu podać wzorzec wyszukiwania do Directory.GetFiles: https://msdn.microsoft.com/en-us/library/wz42302f(v=vs.110).aspx

0

@somekind

Bo źle go używasz.

Mógłbyś to rozwinąć?

@youmound

A to?

https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/gcallowverylargeobjects-element

On 64-bit platforms, enables arrays that are greater than 2 gigabytes (GB) in total size.

Add this lines to App.config

<runtime>
    <gcAllowVeryLargeObjects enabled="true" />    
</runtime>
There's a 2 GiB limitation on all objects in .NET, you are never allowed to create a single object that exceeds 2 GiB. If you need a bigger object you need to make sure that the objects is built from parts smaller than 2 GiB, so you cannot have an array of continuous bits larger than 2 GiB or a single string longer larger than 512 MiB, I'm not entirely sure about the string but I've done some testing on the issue and was getting OutOfMemoryExceptions when I tried to allocate strings bigger than 512 MiB.

These limits though are subject to heap fragmentation and even if the GC does try to compact the heap, large objects (which is somewhat of an arbitrary cross over around 80K) end up on the large object heap which is a heap that isn't compacted. Strictly speaking, and somewhat of a side note, if you can maintain short lived allocations below this threshold it would be better for your overall GC memory management and performance.

https://stackoverflow.com/questions/6107322/memory-limitations-in-a-64-bit-net-application

https://blogs.msdn.microsoft.com/joshwil/2005/08/10/bigarrayt-getting-around-the-2gb-array-size-limit/

#Edit

Sprawdzałem i działa, ale dodatkowo musisz odznaczyć

git.PNG

0

@WeiXiao: z tego co widzę, to @youmound stosuje search pattern "*.*". Jakby użył sensownego, to może liczba zwróconych plików byłaby mniejsza i problemu by nie było. To nazywam złym użyciem.

0

@somekind a ja to nazywam nie rozumieniem co program liczy ... bo gdybyś rozumiał to byś tak nie pisał
do tego powtórze jeszcze raz w katalogu gdzie się wywala nie jest używana reguła CD 1 , cd 1 itd.

0

No właśnie, reguła nie jest używana i pewnie dlatego się wywala. Wyciągasz wszystkie pliki ze wszystkich podkatalogów tą instrukcją: Delimon.Win32.IO.Directory.GetFiles(di.FullName, "*.*", Delimon.Win32.IO.SearchOption.AllDirectories). Użyj maski i sprawdź, czy działa.
Albo najlepiej nie używaj tej biblioteki w ogóle, skoro jest taka chamska. :P

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