Tablica uchwytów do odczytywanych plików

0

Pytanie pewnie dla Was będzie bardzo proste, ale ja dopiero co zaczynam się przesiadać na c# więc proszę o wyrozumiałość . Do rzeczy: chciałbym otworzyć kilka plików naraz ( ich ścieżki zostały zainicjowane w tablicy stringów filePath[i]).

for (int i = 0; i < numOfFiles; i++)
FileStream file = new FileStream(filePath[i], FileMode.Open)[i] ;

Error: c:\users\maciek\documents\visual studio 2010\Projects\File_comparsion\File_comparsion\MainWindow.xaml.cs(47,35): error CS0021: Cannot apply indexing with [] to an expression of type 'System.IO.FileStream'

Standardowe pytanie: dlaczego nie mogę zrobić takiej tablicy i jak dojść do tego o co mi chodziło.

0

new FileStream(filePath[i], FileMode.Open) zwraca referencję do utworzonego obiektu. Klasa FileStream nie definiuje indeksatora, stąd błąd.

Skoro chcesz korzystać z tablicy filePath to dlaczego w ogóle z niej nie korzystasz w tej pętli?

0

Dlaczego klasa FileStream nie definiuje indeksatora ? A z tablicy filePath skorzystałem w wywołaniu konstruktora. Also jaka jest alternatywna droga rozwiązania mojego problemu?

0

Ah, faktycznie, sama ścieżka. A po co miałaby definiować indeksator i po co właściwie chcesz go użyć?

0
kutacz napisał(a)

chciałbym otworzyć kilka plików naraz

Dodam że duuuuuuuuuużo plików, tak z kilkaset(chcę sprawdzić czy wszystkie są takie same), dlatego zgodnie z zasadą DRY użyłem pętli z tablicą, gdzie indeksator oznacza numer pliku.

0
kutacz napisał(a)

Dlaczego klasa FileStream nie definiuje indeksatora ? A z tablicy filePath skorzystałem w wywołaniu konstruktora. Also jaka jest alternatywna droga rozwiązania mojego problemu?

Nie wiem, co to jest "also" i nie rozumiem o jakiej alternatywie mówisz, skoro nawet jednej działającej wersji nie masz.

Jeśli chcesz otworzyć na raz kilka plików, to musisz zrobić kilka obiektów FileStream, czy jako oddzielne zmienne, czy jako tablica, jak Ci pasuje. Jednym obiektem, tak jak masz teraz, tego na pewno nie zrobisz.

0

No dobrze, ale po co indeksator dla pojedynczego obiektu FileStream?!

0
for (int i = 0; i < numOfFiles; i++)
FileStream [numOfFiles] file = new FileStream(filePath[i], FileMode.Open)[i] ;

Tak nie działa.

for (int i = 0; i < numOfFiles; i++)
FileStream  file [numOfFiles] = new FileStream(filePath[i], FileMode.Open)[i] ;

Tak als... tfu tfu RÓWNIEŻ nie działa.
Jestem załamany, już nie wiem co robić ;(

0

Strumienie, które chcesz otworzyć, również musisz gdzieś trzymać. Potrzebujesz zatem dodatkowej tablicy typu

FileStream[]

Najszybciej osiągniesz swój cel z użyciem

Enumerable.Select

na tablicy nazw plików:

FileStream[] fileStreams = filePath.Select(path => File.Open(path, FileMode.Open)).ToArray();

Edit:
Pamiętaj, żeby zwolnić zaalokowane zasoby, i uchwyty poprzez

Dispose

otwartych strumieni.

I jeszcze mała uwaga. Jeśli chcesz sprawdzić, czy N > 2 obiektów (w Twoim przypadku plików) jest identycznych, nie musisz mieć ich w rękach (tu w pamięci) wszystkich na raz. Wystarczy, że będziesz je porównywał parami.

0
Rev napisał(a)

No dobrze, ale po co indeksator dla pojedynczego obiektu FileStream?!

Nie wiem czy to do mnie pytanie, ale powiedziałbym, że po c****. ;P

kutacz napisał(a)

Jestem załamany, już nie wiem co robić ;(

Najlepiej zrobisz, jeśli poczytasz jakąś książkę o języku C#. Twój problem to nieumiejętność zadeklarowania tablicy i jej wypełnienia, to są podstawy.

const char star napisał(a)

Najszybciej osiągniesz swój cel z użyciem

Enumerable.Select

na tablicy nazw plików:

FileStream[] fileStreams = filePath.Select(path => File.Open(path, FileMode.Open)).ToArray();

Masz rację, tylko moim zdaniem to zbytnie mącenie w głowie początkującemu.

I jeszcze mała uwaga. Jeśli chcesz sprawdzić, czy N > 2 obiektów (w Twoim przypadku plików) jest identycznych, nie musisz mieć ich w rękach (tu w pamięci) wszystkich na raz. Wystarczy, że będziesz je porównywał parami.

Jeśli identyczność plików oznacza ich identyczną zawartość, to też trzeba przemyśleć algorytm porównujący, a nie sądzę, żeby autor miał w ogóle na niego sensowny pomysł, skoro zaczyna od otwierania wszystkich plików na raz. Porównywanie parami wszystkich plików również jest bez sensu.

0
somekind napisał(a)

Porównywanie parami wszystkich plików również jest bez sensu.

Jestem pewien, że jest to jedyna sensowna metoda sprawdzenia identyczności elementów w jakimś zbiorze.
Pisząc parami, nie miałem na myśli porównywania każdy z każdym, a raczej porównanie dowolnego ze wszystkimi innymi.

public static bool AreEqual(IEnumerable<object> xs)
{
  // z pominięcim wszelkich testów na null, empty itd. 
  
  object first = xs.First();

  return xs.All(x => x.Equals(first));
}

Czyli innymi słowy relacja równości jest przechodnia ( z definicji ).

2

Ja bym tam się najpierw zabrał za porównywanie rozmiarów plików, dopiero jak są takie same to wtedy można je otwierać i lecieć bajt po bajcie.
Btw. pokazywanie rozwiązania przy użyciu LINQ, komuś kto nie potrafi nawet z tablic korzystać jest mocno optymistycznym podejściem, żeby nie powiedzieć naiwnym :D

0

W książce było tak :

Programming C#, 4th Edition
By Jesse Liberty

Publisher : O'Reilly
Pub Date : February 2005
ISBN : 0-596-00699-3

Instantiate an array using the new keyword. For example:

myIntArray = new int[5];

This declaration creates and initializes an array of five integers, all of which are initialized to the value 0.

Zrozumiałem, że tablice w C# tworzy się według wzoru:

NazwaKlasy [rozmiar_tablicy] nazwaObiektuKlasy = new NazwaKlasy(parametry_konstruktora)[rozmiar_tablicy]; 

a tu nie wiadomo skąd wyjątek :/

0

A w przykładzie widzisz gdzieś wywołanie konstruktora?

0

To źle zrozumiałeś, proponuję lecieć z materiałem wolniej, bo bez dokładnego zrozumienia co się dzieje to nie ma po prostu sensu.

0

W literaturze nie znalazłem odpowiedzi na swoje pytanie (w książkach jest dużo przydatnych informacji, ale niestety nie ma wszystkiego i wielu rzeczy trzeba nauczyć się na własną rękę).

Konstrukcję tablic z klasami wydedukowałem w następujący sposób

typy podstawowe w c# są klasami --> zamiast int można wstawić inną klasę z ewentualnym konstruktorem . Wydawało mi się to proste i logiczne, lecz najwidoczniej ludzie odpowiedzialni za konstrukcję języka mieli bardziej zawiły sposób rozumowania .

0
kutacz napisał(a)

Konstrukcję tablic z klasami wydedukowałem w następujący sposób

typy podstawowe w c# są klasami --> zamiast int można wstawić inną klasę z ewentualnym konstruktorem . Wydawało mi się to proste i logiczne, lecz najwidoczniej ludzie odpowiedzialni za konstrukcję języka mieli bardziej zawiły sposób rozumowania .

Twój sposób jest zawiły i jest to raczej delikatne określenie. Zasady tworzenia tablic są banalne i nie trzeba ich dedukować, wystarczy przeczytać ze zrozumieniem.

Zamiast int można wstawić inną klasę. Po prostu. Skąd wytrzasnąłeś konstruktor, którego nie ma w przykładzie?

0

Poznaj moje dobre serce. Potrzebujesz coś MNIEJ WIĘCEJ takiego:

//definiowanie TABLICY obiektów typu FileStream. W każdym elemencie jednak masz null
FileStream[] fileTab = new FileStream[filePaths.Length];
for( int i = 0 ; i < filePaths.Length;i++)
{
   //definiowanie już konkretnych obiektów w konkretnych elementach utworzonej wcześniej tablicy
   fileTab[i] = new FileStream(filePaths[i]);
}
0

Zastanów się jeszcze raz, czy na pewno potrzebujesz całej tablicy otwartych na raz plików.
Nie twierdzę że to błąd, tylko jest duże prawdopodobieństwo że to przesada.

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