Laden...

Dateien eindeutig unterscheiden

Erstellt von pringels vor 17 Jahren Letzter Beitrag vor 15 Jahren 3.610 Views
P
pringels Themenstarter:in
24 Beiträge seit 2006
vor 17 Jahren
Dateien eindeutig unterscheiden

Hallo,
ich habe folgendes Problem:
in meiner Mdi-Anwendung kann ich eine Datei öffnen und mache dann ein neues Child-Fenster auf. Damit eine Datei nicht zweimal gleichzeitig geöffnet wird, habe ich ein

Dictionary<string dateiname, Form meinMdiChild>

. Wenn de r Dateiname (incl. Pfad) als Key schon drin steht, wird kein neues Fenster geöffnet, sondern das vorhandene aktiviert.
Läuft super.
Nun habe ich mich aber selbst ausgetrickst. Da der Ordner, indem meine zu öffnenden Dateien liegen so einen langen Pfad hat, habe ich mir eine Abkürzung gebaut. In einer Batch-Datei lege ich ein virtuelles Laufwerk V: an. Also:

subst V: C:\langer\Pfad\zu\meiner\Datei

Nun kann ich die gleiche Datei doch zweimal öffnen, nämlich über

  1. V:\meine_dat.ei
  2. C:\langer\Pfad\zu\meiner\Datei\meine_dat.ei
    Beides ist aber die gleiche Datei.
    Wie kann ich feststellen, ob es die gleichen Dateien sind?
    Oder anders gefragt, was kann ich anstelle des Dateinamens als key für mein Dictionary verwenden?
    Danke
    pringels
2.223 Beiträge seit 2005
vor 17 Jahren

nabend,
um nicht deine Vorgehensweise total zu ändern
würde ein replace von 'C:\langer\Pfad\zu\meiner\Datei' in 'v:'

dein Problem nicht lösen ?

mfg

V
52 Beiträge seit 2006
vor 17 Jahren

das hilft zwar wenn er das programm nur selbst benutzt (und eben replace benutzt), aber nicht wenn ein anderer nutzer subst benutzt.

entweder du löst subst auf, oder du lässt die datei vom betriebssystem sperren (ka wie das in .net geht 😁 ) und dann kannst du sie beim zweiten öffnen eh nur schreibgeschützt oder garnich öffnen.

mfg v1vec

P
pringels Themenstarter:in
24 Beiträge seit 2006
vor 17 Jahren
Danke

An das sperren (lock?) habe ich auch schon gedacht.
Hatte gehofft, das es eine Eigenschaft, z.B. des FileInfo-Objects gibt, über die ich das herausfinden kann.

@blackcoin:
replace nützt mir in diesem Fall wirklich nichts...

87 Beiträge seit 2006
vor 17 Jahren

Hi

    FileStream file1 = File.Open(dateiPfad1, FileMode.Open);
    FileStream file2 = File.Open(dateiPfad2, FileMode.Open);
    if (file1.GetHashCode().Equals(file2.GetHashCode()))
    {
        ...
    }

schon mal so was in der art versucht? oder einfach gleich mit .Equals? ich hoffe mal das das wirklich auf denn FileStream anwendet und so die dateien binär vergleicht.

MfG

Tilton

"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra

The Humble Programmer by Edsger W. Dijkstra

121 Beiträge seit 2006
vor 17 Jahren

Hallo,

Du kannst an zwei verschiedenen Pfaden nicht erkennen, ob sie die selbe physikalische Datei beschreiben, meines Erachtens.
Deshalb würde ich TiltonJH s Idee mit dem Hashing aufgreifen, und zwei Dateien identisch sein lassen, wenn Hash und Größe übereinstimmen.
[ Vielleicht ist in Filesystemen mit symbolischen Links noch nicht einmal der Dateiname ohne Pfad ein Kriterium, aber ich bin keiner, der sich bei Linux auskennt.]

Gruß Hape

121 Beiträge seit 2006
vor 17 Jahren

Hallo,

eigentlich ist das Blödsinn was ich da schreibe!
Nimmt man nämlich eine Datei und macht daraus eine Kopie mit anderem Namen, dann...... wäre das Verfahren ja nicht in der Lage, die beiden Dateien zu trennen.

Also vergeßt was ich geschrieben habe 🙂
Gruß Hape

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo TiltonJH,

der Vergleich ist m.E. nicht zielführend. Außerdem vergleicht Equals in den seltensten Fällen binär. In der Regeln werden nur die Referenzen auf die Objekte und nicht die Objekte selbst verglichen.

herbivore

87 Beiträge seit 2006
vor 17 Jahren

Hi, ja is mir gestern dann auch noch durch den kopf gegangen das equals da nich gut is, dann wohl eher so was❔


    ...
    FileStream file1 = File.Open(dateiPfad1, FileMode.Open);
    FileStream file2 = File.Open(dateiPfad2, FileMode.Open);
    if (file1.GetHashCode() == file2.GetHashCode())
    {
        ...
    }
...

da der hash code ja so hoffe ich auf grundlage der datei erzeugt wird? pfad und auch attribute der datei im hash code mit zu nutzen wäre nich so super, weil ergebnis wird verfälscht oder?

MfG

Tilton

"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra

The Humble Programmer by Edsger W. Dijkstra

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo TiltonJH,

da GetHashCode in FileSteam unverändert von Object geerbt wurde, kann ich deine Hoffnung nicht teilen. 🙂

herbivore

87 Beiträge seit 2006
vor 17 Jahren

🤔
hmm, auch mist hat jemand einen andern vorschlag?
gibs da evtl. schon ne andere klasse mit der man einen hash code über eine datei erzeugen kann?
oder muss ich mir hier selber noch eine klasse schreiben die sowas richtig kann?

MfG

Tilton

"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra

The Humble Programmer by Edsger W. Dijkstra

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo TiltonJH,

ich wüsste erstmal keinen Weg, wie das gehen soll. Bin mir nicht mal sicher, ob FileStream überhaupt weiß, welches der "echte" Pfad einer Datei ist.

herbivore

87 Beiträge seit 2006
vor 17 Jahren

Moin,

so das Problemchen hat mir keine Ruhe gelassen und da ich sowas auch gut für das Prog was gerade schreibe gebrauchen kann, hab ich da mal eine Klasse geschrieben, welche das jetzt hinbekommt. Das Dateien-Vergleichen läuft über das vergleichen der MD5-Hash codes, sollte also sehr Zuverlässig sein.

Hier nun der Code:


using System;
using System.Security.Cryptography;
using System.IO;
using System.Text;

namespace System.IO
{
    static class FileCompare
    {
        public static bool binaryCompare(string filePath1, string filePath2)
        {
            if (File.Exists(filePath1) && File.Exists(filePath2))
            {
                MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

                byte[] binaryMD5_1 = md5.ComputeHash(File.OpenRead(filePath1));
                byte[] binaryMD5_2 = md5.ComputeHash(File.OpenRead(filePath2));

                StringBuilder strBuilder1 = new StringBuilder(32);
                StringBuilder strBuilder2 = new StringBuilder(32);

                foreach (byte binary in binaryMD5_1)
                {
                    strBuilder1.Append(binary.ToString("x2"));
                }
                foreach (byte binary in binaryMD5_2)
                {
                    strBuilder2.Append(binary.ToString("x2"));
                }

                if (strBuilder1.ToString() == strBuilder2.ToString()) return true;
                else return false;
            }
            else return false;
        }
    }
}

Das erstellen der MD5-Hash-Codes ist zeitlich natürlich von der größe der jeweiligen Dateien abhängig.
Weis jemand ob eine "foreach"-Schleife oder eine eine normale "for"-Schleife (die auch über alle Einträge läuft) performanter ist? Oder sind die gleich?

Wenn jemand noch Verbesserungsvorschläge oder sonstige konstruktive Kritik hat würde mich das freuen.

MfG

Tilton

"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra

The Humble Programmer by Edsger W. Dijkstra

121 Beiträge seit 2006
vor 17 Jahren

Hi TiltonJH,
... md5.ComputeHash(...), ...ok, und dann:
da findest Du aber bestimmt noch einen kürzerer Weg, um zwei bytes[] Arrays zu vergleichen 😉
Gruß Hape

87 Beiträge seit 2006
vor 17 Jahren

?( wie meinst das jetzt? ich will doch nicht die byte[] vergleichen sondern die jeweiligen dateien

Tilton

"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra

The Humble Programmer by Edsger W. Dijkstra

121 Beiträge seit 2006
vor 17 Jahren

Hi,
Dein Coding vergleicht zwei byte[] Arrays, mit Hilfe der zwei StringBuilders, deshalb schreibe ich das...


if (strBuilder1.ToString() == strBuilder2.ToString())

ich möchte Dich wirklich nicht verwirren, aber Dein Coding tut das.
Gruß Hape


                byte[] binaryMD5_1 = md5.ComputeHash(File.OpenRead(filePath1));
                byte[] binaryMD5_2 = md5.ComputeHash(File.OpenRead(filePath2));

                StringBuilder strBuilder1 = new StringBuilder(32);
                StringBuilder strBuilder2 = new StringBuilder(32);

                foreach (byte binary in binaryMD5_1)
                {
                    strBuilder1.Append(binary.ToString("x2"));
                }
                foreach (byte binary in binaryMD5_2)
                {
                    strBuilder2.Append(binary.ToString("x2"));
                }

                if (strBuilder1.ToString() == strBuilder2.ToString()) return true;
                else return false;

87 Beiträge seit 2006
vor 17 Jahren

habs begriffen... (glaube ich)... so besser?


using System;
using System.Security.Cryptography;
using System.IO;

namespace System.IO
{
    static class FileCompare
    {
        public static bool binaryCompare(string filePath1, string filePath2)
        {
            if (File.Exists(filePath1) && File.Exists(filePath2))
            {
                MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
                byte[] binaryMD5_1 = md5.ComputeHash(File.OpenRead(filePath1));
                byte[] binaryMD5_2 = md5.ComputeHash(File.OpenRead(filePath2));
                bool returnType = true;
                for (int i = 0; i < binaryMD5_2.Length; i++)
                {
                    if (binaryMD5_1[i] != binaryMD5_2[i])
                    {
                        returnType = false;
                        break;
                    }
                }
                return returnType;
            }
            else return false;
        }
    }
}

MfG

Tilton

"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra

The Humble Programmer by Edsger W. Dijkstra

121 Beiträge seit 2006
vor 17 Jahren

Hi,
ja genau so gehts,
nur kannst Du noch abkürzen, indem Du auf returnType verzichtest und bei beim ersten ungleichen dann return false machst, nach der Schleife dann return true, falls das File nicht da ist, return false (letzteres hast du ja schon).

Gruß Hape

87 Beiträge seit 2006
vor 17 Jahren

hmmm... ja das seh ich ein...


using System;
using System.Security.Cryptography;
using System.IO;

namespace System.IO
{
    static class FileCompare
    {
        public static bool binaryCompare(string filePath1, string filePath2)
        {
            if (File.Exists(filePath1) && File.Exists(filePath2))
            {
                MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
                byte[] binaryMD5_1 = md5.ComputeHash(File.OpenRead(filePath1));
                byte[] binaryMD5_2 = md5.ComputeHash(File.OpenRead(filePath2));
                for (int i = 0; i < binaryMD5_1.Length; i++) 
                    if (binaryMD5_1[i] != binaryMD5_2[i]) return false;
                return true;
            }
            else return false;
        }
    }
}

so das dürfte dann die endgültige Version sein... und man kann den Thread als gelöst bezeichnen

MfG
Tilton

"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra

The Humble Programmer by Edsger W. Dijkstra

121 Beiträge seit 2006
vor 17 Jahren

...... und nun gibt es eine nützliche Funktion mehr 🙂

Gruß Hape

B
1.529 Beiträge seit 2006
vor 17 Jahren

Öffne alle Dateien einfach mit FileAccess.ReadWrite und FileShare.Read.
Sobald du jetzt versuchst, die selbe Datei ein zweites Mal zu öffnen, gibt es ne Exception.

EDIT: Man sollte FileAccess und FileShare sowie immer mit angeben.

87 Beiträge seit 2006
vor 17 Jahren

das mag ja sein, aber mit meiner methode kann ich auch kopien der selber datei ausfindig machen...

MfG

Tilton

"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra

The Humble Programmer by Edsger W. Dijkstra

B
1.529 Beiträge seit 2006
vor 17 Jahren

Das ist mir schon klar.
Nur wenn ich dein Posting

...ich habe folgendes Problem:
in meiner Mdi-Anwendung kann ich eine Datei öffnen und mache dann ein neues Child-Fenster auf. Damit eine Datei nicht zweimal gleichzeitig geöffnet wird...

heranziehe, stellt meine Methode eine praktische und durchaus gängige (und vor allem unkomplizierte) Möglichkeit dar, dass gleichzeitige Öffnen der selben Datei zu verhindern.

Durch die Prüfung auf Identität mittels eines Hash verhinderst du aber das gleichzeitige Öffnen von gleichen Dateien. Dies kann jedoch erwünscht sein (wenn ich zum Beispiel eine Kopie erzeuge und diese verändern und verschicken will).
Vor allem halte ich einen solchen Ansatz für sinnlos (und kontraproduktiv), da ich ja nur die Datei schliessen muss, um mit der Kopie arbeiten zu können. Dies erscheint mir jedoch im höchsten Maße unergonomisch.

Das Programm sollte meines Erachtens nur sicherstellen, dass der Benutzer nicht die selbe Datei mehrfach öffnet. Jedoch darf mir eine MDI-Anwendung nicht verbieten eine Kopie einer Datei anzulegen und zur gleichen Zeit diese und das Original geöffnet zu haben.
Ein Programm mit einer solchen willkürlichen und sinnfreien Einschränkung würde bei mir sehr schnell im NUL-Device landen...

87 Beiträge seit 2006
vor 17 Jahren

Original von Borg
...
Ein Programm mit einer solchen willkürlichen und sinnfreien Einschränkung würde bei mir sehr schnell im NUL-Device landen...

X(

ne mal im ernst, der anfangs post war ja nicht von mir, sondern von "pringels" und deine methode ist in dem problem von ihm sicher die bessere methode, mir ging es aber eben darum auch kopien zu finden...
und ob dann das progi melden kann das es sich um eine kopie der datei handelt oder nich... wenn ich so drüber nach denke könnte man beide sachen sogar kombinieren (also jetzt für mein prog), na ja mal sehn...

MfG

Tilton

"In der Informatik geht es genauso wenig um Computer wie in der Astonomie um Teleskope."
Edsger W. Dijkstra

The Humble Programmer by Edsger W. Dijkstra

182 Beiträge seit 2006
vor 15 Jahren
FileStream file1 = File.Open(dateiPfad1, FileMode.Open);
    FileStream file2 = File.Open(dateiPfad2, FileMode.Open);
    if (file1.GetHashCode().Equals(file2.GetHashCode()))
    {
        ...
    }

Damit Bekommt man den HashCode von dem Object aber wie bekommt man den HashCode einer Datei?

Real programmers don't comment.
If it was hard to write, it should be hard to understand!

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Hufy90,

kommt darauf an, was du unter Hashcode einer Datei verstehst. Such mal nach MD5. Könnte sein, dass du das meinst.

herbivore