ubuntu--anfaenger
Anmeldungsdatum: 12. Oktober 2013
Beiträge: 1088
Wohnort: Belgien
|
Hallo, Ich hab ein kleines Programm gebastelt, um 2 Dateien als bytes zu vergleichen, um nach einem Backup zu schauen ob alles geklappt hat. Ich bin totaler Anfänger und mein Problem ist das diese Dateien nicht im selben Verzeichnis liegen. Meine Frage kann ich das Programm so umbauen, das die ganze Festplatte nach den Dateien Durchsucht wird? Hier der code: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 | #include <iostream>
#include <vector>
#include <fstream>
using namespace std;
template<typename T>
char* wie_bytes(T& i)
{
void* addr = &i;
return static_cast<char*>(addr);
}
int main()
{
cout << "Erste Datei: " << '\n';
string name;
cin >> name;
ifstream istr(name.c_str());
if(!istr){cerr << "Kann Datei 1 nicht lesen!!!" << '\n';
return 1;
}
vector<int>eins;
int i;
while(istr.read(wie_bytes(i), sizeof(int)))
eins.push_back(i);
cout << "Zweite Datei: " << '\n';
cin >> name;
ifstream uistr(name.c_str());
if(!uistr){cerr << "Kann Datei 2 nicht lesen!!!" << '\n';
return 2;
}
vector<int>zwei;
int t;
while(uistr.read(wie_bytes(t), sizeof(int)))
zwei.push_back(t);
if(i==t){
cout << "Dateien sind gleich!!!" << endl;
}
else
cout << "Dateien ungleich" << endl;
return 0;
}
|
|
ChickenLipsRfun2eat
Anmeldungsdatum: 6. Dezember 2009
Beiträge: 12067
|
Hallo! Du könntest natürlich alles durchsuchen und implementieren, was bei mehrfachem Vorkommen des Dateinamens passiert. Das würde aber wohl deinen Rahmen sprengen. Normalerweise übergibt man Dateinamen ja per Kommandozeilen-Argument, dafür müsstest du dein int main( void ) aber zu einem int main( int anzahl, char **arrayMitArgumenten ) umbauen und diese mit bspw. optarg parsen. Falls von der Standardeingabe gelesen werden soll, muss der Nutzer den Pfad korrekt angeben. Falls das eine Hausaufgabe oder sowas ist, pack bitte die Beschreibung dazu. Machen kann man vieles, die Frage ist wie immer: Was ist das Ziel?
|
ubuntu--anfaenger
(Themenstarter)
Anmeldungsdatum: 12. Oktober 2013
Beiträge: 1088
Wohnort: Belgien
|
Hallo ChickenLipsRfun2eat,
Falls von der Standardeingabe gelesen werden soll
Nee muss nicht, ich weiss es einfach nicht besser...
Falls das eine Hausaufgabe oder sowas ist, pack bitte die Beschreibung dazu
Ist keine Hausaufgabe, ich hab mir das selber so ausgedacht.
Was ist das Ziel?
Das Ziel ist 2Dateien nach einem Backup zu vergleichen,ohne selber in den Dateien reinschauen zu müssen..Das Problem ist das die Dateien nicht im selben Verzeichnis liegen. Ich würde mich freuen wenn ich den c_str() so umbauen könnte das er nach dem namen auch in anderen Verzeichnissen sucht als das Verzeichnis in dem der code liegt..
|
ChickenLipsRfun2eat
Anmeldungsdatum: 6. Dezember 2009
Beiträge: 12067
|
ubuntu--anfaenger schrieb: Ich würde mich freuen wenn ich den c_str() so umbauen könnte das er nach dem namen auch in anderen Verzeichnissen sucht als das Verzeichnis in dem der code liegt..
Dann müsstest du dir eine Suche implementieren, was sehr abenteuerlich werden kann und meine Fähigkeiten bei weitem übersteigt ☺ Ich würde das mit der bewährten Methode der Kommandozeilen-Argumente machen, wie das z.B. diff auch macht. diff ~/file1 /where/ever/on/your/system/file2
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11179
Wohnort: München
|
ubuntu--anfaenger schrieb: Ich hab ein kleines Programm gebastelt, um 2 Dateien als bytes zu vergleichen, um nach einem Backup zu schauen ob alles geklappt hat.
Geht es hier darum selber cmp nachzubauen oder kanntest du das Programm noch nicht?
cmp /pfad/zur/Datei1 /pfad/zur/Datei2
|
ChickenLipsRfun2eat
Anmeldungsdatum: 6. Dezember 2009
Beiträge: 12067
|
Mal ein kleines Parse-Beispiel. Fehlen natürlich noch Tests und die Dateibehandlung. Bin aber auch noch Anfänger, was C angeht ☺ 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 | #include <stdlib.h> // exit
#include <stdio.h> // printf, ( Dateioperationen )
#include <getopt.h> // Argumente parsen
int main( int anzArg, char **argArray ) {
// Verabschiedung an/aus: Standard: aus
int sayByeBye = 0; // in c++ geht auch bool. Funktioniert aber in C nicht.
// unser Verabschiedungsgruß
char byeBye[] = { 'B', 'y', 'e', '!', 0 }; // == "Bye!" in Arraydarstellung mit terminierender Null
char *pBye = byeBye; // Zeiger auf den Anfang des Abschiedstextes setzen
// Definieren der auswertbaren Argumente:
struct option options[] = {
{ "byeByeString", 1, NULL, 'b' }, // ungeprüfter String von der Kommandozeile als Abschiedsgruß
{ "sayByeBye", 0, NULL, 's' }, // Verabschiedung anschalten
{ NULL , 0, NULL, 0 } // END OF ARRAY: C-Style-Arrays brauchen immer NULL oder 0 (char) als Abschluss, siehe "Bye!"
};
// optind ist per default auf 1: Falls man die Argumente öfter parsen möchte, ist es sinnvoll dies manuell zu setzen
optind = 1; // options-index, optind 0 = Dateiname des Programms (z.B. "./myProg")
while( true ) {
char c = getopt_long( anzArg, argArray, "b:s", options, NULL ); // Hinweis: Mit / ohne Argumente!
// Keine Argumente:
if( c == -1 )
break;
switch( c ) {
case 'b':
// Benutzernachricht übernehmen:
pBye = argArray[ optind -1 ]; // Zeiger auf neuen String setzen
break;
case 's':
sayByeBye = 1; // true als boolean
break;
//default: Man kann eine Standardbehandlung angeben. So meckert der Parser nur, dass er das Kommando nicht kennt → Fehlerbehandlung :)
}
}
/* optargs sortiert alle Argumente, so dass aus
./prog -n filename1 -h3 -o lala filename2
ein
./prog -h3 -n -o lala filename1 filename2 wird.
Alle nicht-Optionen sind also ab optind + 1 erreichbar.
optind + 2 = zwei Dateinamen - oder zwei "Nicht-Argumente" */
if( optind + 2 != anzArg ) {
fprintf( stderr, "Usage: %s [options] <filename1> <filename2>\n"
"-s, --sayByeBye : sag mir auf Wiedersehen!\n"
"-b, --byeByeString : sag es mit meinen Worten!\n", argArray[0] );
exit( 1 );
}
const char* filename1 = argArray[ optind ];
const char* filename2 = argArray[ optind+1 ];
printf( "Folgende Dateinamen habe ich ermittelt:\nDatei1:%s\nDatei2:%s\n", filename1, filename2 );
if( sayByeBye == 1 )
printf( "%s\n", pBye );
return 0;
}
|
Man muss eine Weile drüber nachdenken, da Zählen immer sehr abenteuerliche Fehler verursachen kann (Zählt der jetzt von 0 an und muss ich eins abziehen - oder nicht? ) und ich wollte noch mehr zu den Arrays ausführen - aber das würde den Rahmen noch mehr sprengen. Ich hoffe, es hilft dir weiter. Zumindest hast du nun genug Futter für die Suchmaschinen 😉 Deine Dateibehandlung kannst du dann vor dem Abschiedsgruß ansetzen.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12826
|
ubuntu--anfaenger schrieb:
Das Ziel ist 2Dateien nach einem Backup zu vergleichen,ohne selber in den Dateien reinschauen zu müssen..
Was genau sollen denn die Kriterien für den Vergleich sein? Und: wie findest Du die beiden Dateien, die Du vergleichen willst? Suchst Du generell Doubletten? Oder gibt es irgendein Kriterium, anhand dessen Du die Dateien identifizieren kannst, die Du vergleichen willst? Das sollten wir erst mal klären, bevor es mit dem Coden losgeht. Und überhaupt: was bedeutet "ohne selber in den Dateien reinschauen zu müssen"? Dein Programm liest doch die Dateien - sogar komplett. Oder meinst Du, Du als Mensch musst sie nicht manuell vergleichen? Und übrigens: es gibt höchstwahrscheinlich bereits etwas, das Deine Anforderungen erfüllt - zur Not mit etwas Skripten außen rum. Das in C++ zu implementieren wäre dann eher eine Übung fürs C++-Lernen. Zu Deinem Programm: üblicherweise übergibt man die Dateinamen direkt als Argumente (siehe ChickenLipsRfun2eats Kommentar). Wenn man sie dann doch von Stdin lesen muss, nimmt man xargs . Außerdem hat Dein Programm das Problem, dass die beiden Dateien komplett in den Speicher gelesen werden müssen. Das kann bei großen Dateien zu Problemen führen. Da ist auf jeden Fall die Strategie besser, immer nur Teile zu lesen und zu vergleichen. Das macht die Implementierung natürlich ein bisschen komplizierter, aber deutlich effizienter, insbesondere, weil man beim ersten gescheiterten Vergleich abbrechen kann.
|
ubuntu--anfaenger
(Themenstarter)
Anmeldungsdatum: 12. Oktober 2013
Beiträge: 1088
Wohnort: Belgien
|
ChickenLipsRfun2eat schrieb: Dann müsstest du dir eine Suche implementieren, was sehr abenteuerlich werden kann und meine Fähigkeiten bei weitem übersteigt ☺
Ja das übersteigt dann auch meine 😳 seahawk1986 schrieb: Geht es hier darum selber cmp nachzubauen oder kanntest du das Programm noch nicht?
Nee cmp kannte ich nicht, danke. rklm schrieb
Was genau sollen denn die Kriterien für den Vergleich sein? Und: wie findest Du die beiden Dateien, die Du vergleichen willst? Suchst Du generell Doubletten? Oder gibt es irgendein Kriterium, anhand dessen Du die Dateien identifizieren kannst, die Du vergleichen willst? Das sollten wir erst mal klären, bevor es mit dem Coden losgeht.
Die Kriterien sind entweder sind 2Dateien gleich,(die bits sind gleich) oder nicht gleich..ich suche keine Doubletten. Ich finde die Datei in dem ich den Name der ersten Datei eingebe zb: test1.txt dann den Namen der 2ten Datei test2.txt, dann wird eingelesen und verglichen, das funktioniert auch sehr gut, solange die beiden Dateien im selben Verzeichnis liegen von wo aus das Program gestartet wird..wenn zb eine Datei in /home/Documents liegt die andere in /usr/share liegt klappt das nichtmehr ich wusste nicht das das so abenteuerlich wird..☹ hätte gedacht für sowas gibt es eine Standard Bibliothek in c++
meinst Du, Du als Mensch musst sie nicht manuell vergleichen?
Ja genau das meine ich.
Das in C++ zu implementieren wäre dann eher eine Übung fürs C++-Lernen.
Ja gerne!
Außerdem hat Dein Programm das Problem, dass die beiden Dateien komplett in den Speicher gelesen werden müssen. Das kann bei großen Dateien zu Problemen führen. Da ist auf jeden Fall die Strategie besser, immer nur Teile zu lesen und zu vergleichen. Das macht die Implementierung natürlich ein bisschen komplizierter, aber deutlich effizienter, insbesondere, weil man beim ersten gescheiterten Vergleich abbrechen kann.
Ja daran hatte ich noch nicht gedacht, aber die Dateien sind nicht sehr gross die ich damit vergleichen will. Ich hätte jetzt nicht gedacht das das so kompliziert wird.War davon ausgegangen, das mann einfach wenn über cin>> eingelesen wird den Pfad mitgeben könnte zb /home/Documents/datei1.txt.
|
dingsbums
Anmeldungsdatum: 13. November 2010
Beiträge: 3547
|
Das Ziel ist 2 Dateien nach einem Backup zu vergleichen,ohne selber in den Dateien reinschauen zu müssen.
Ich würde das mit md5sum machen.
| if [ "$(ms5sum /pfad/zu/original/datei1)" == "$(ms5sum /pfad/zu/backup/datei1)" ];then
echo dateien gleich
else
echo dateien ungleich
fi
|
Das Problem ist das die Dateien nicht im selben Verzeichnis liegen.
Das ist md5sum egal, siehe oben.
... um nach einem Backup zu schauen ob alles geklappt hat. [...] Meine Frage kann ich das Programm so umbauen, das die ganze Festplatte nach den Dateien Durchsucht wird?
Du weisst nicht, in welchen Pfaden sich Original und Backup befinden? Bedenklich... 😉 Zum Auffinden von Dateien anhand diverser Kriterien könntest du find verwenden.
|
unbuntuS12
Anmeldungsdatum: 2. Juni 2010
Beiträge: 1816
|
ubuntu--anfaenger schrieb: [...] um nach einem Backup zu schauen ob alles geklappt hat.
Ich weiß, es scheint hier drum zu gehen, sich programmiertechnisch auszuprobieren, aber ich will nicht unerwähnt lassen, dass so ungefähr alles jenseits von cp das automatisch prüft. Insbesondere rsync.
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12826
|
ubuntu--anfaenger schrieb:
Die Kriterien sind entweder sind 2Dateien gleich,(die bits sind gleich) oder nicht gleich..ich suche keine Doubletten. Ich finde die Datei in dem ich den Name der ersten Datei eingebe zb: test1.txt dann den Namen der 2ten Datei test2.txt, dann wird eingelesen und verglichen, das funktioniert auch sehr gut, solange die beiden Dateien im selben Verzeichnis liegen von wo aus das Program gestartet wird..wenn zb eine Datei in /home/Documents liegt die andere in /usr/share liegt klappt das nichtmehr ich wusste nicht das das so abenteuerlich wird..☹ hätte gedacht für sowas gibt es eine Standard Bibliothek in c++
Dann nimmst Du einfach das Kommandozeilenprogramm cmp . Jemand anders hat sich schon ausgiebig den Kopf über das Problem zerbrochen und ein allgemeines Tool dafür geschrieben, das das Problem effizient löst. dingsbums schrieb: Ich würde das mit md5sum machen.
Ich nicht, denn das ist weniger effizient. md5sum muss beide gesamten Dateien lesen - selbst, wenn der Fehler schon im zweiten Byte ist.
| if [ "$(ms5sum /pfad/zu/original/datei1)" == "$(ms5sum /pfad/zu/backup/datei1)" ];then
echo dateien gleich
else
echo dateien ungleich
fi
|
Der Ansatz funktioniert nicht, weil die Ausgabe von md5sum den Dateinamen beinhaltet und somit die beiden Zeichenketten nur gleich sind, wenn eine Datei mit sich selbst verglichen wird, was nicht besonders spannend ist. Du müsstest das über eine Eingabeumleitung regeln - dann ist für beide der ausgegebene Name "-". Aber s.o.
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17552
Wohnort: Berlin
|
Ich habe ja ewig kein c++ mehr gemacht, aber folgendes gilt ja allgemein: Der Code von Zeile 18 bis 29 mit Datei 1 wiederholt sich, bis auf die Unterscheidung 1/2 in den Zeilen 31-40. Sowas packt man in eine Funktion mit Parametern und Rückgabewert: | int i = liesDatei ("Erste", 1);
int t = liesDatei ("Zweite", 2);
|
Kann es sein, dass Du nur das letzte Zeichen vergleichst?
| if (i==t) {
cout << "Dateien sind gleich!!!" << endl;
}
else
cout << "Dateien ungleich" << endl;
|
Selbst unterschiedlich lange Dateien würde Dein Programm so nur zufällig erkennen. Bei Textdateien, die oft mit Punkt oder Zeilenumbruch enden eine wenig erfolgversprechende Strategie.
Meine Frage kann ich das Programm so umbauen, das die ganze Festplatte nach den Dateien Durchsucht wird?
Mein Verständnis, nicht aus der Fragestellung, sondern von der anschließenden Diskussion ist: Du hast eine Datei im aktuellen Verzeichnis, sagen wir "original.txt", und eine "backup.txt" die ist irgendwo, sagen wir in ~/backup/ Dann musst Du auf der Frage nach der zweiten Datei einfach den ganzen Pfad zu dieser 2. Datei angeben. Ich habe es zumindest so verstanden, dass Du schon weißt wo sie ist - sie darf ja auch anders heißen - wie sonst willst Du sie finden? - nur willst Du eben offen lassen, wo sie ist. Du kannst natürlich bloß den Namen eingeben, und den Rechner nach allen Dateien dieses Namens suchen lassen, aber das wäre ziemlich unpraktisch. Unpraktisch ist aber auch, dass Du bei der Eingabe keine Name-Completition hast und Dich nicht vertippen darfst. Wenn das keine C++-Übung ist, würde ich auch auf Linux-Hausmittel zurückgreifen, da hast Du Command-Completition und eine wahrscheinlich nicht leicht zu verbessernde, performante Lösung. Ansonsten gilt natürlich wie immer: Erst nach einer richtigen Lösung suchen, dann nach einer performanten, wenn die richtige nicht schon performant genug ist. Für den sporadischen Vergleich zweier kleiner Dateien (< 1MB) ist wahrscheinlich alles performant genug. Und apropos richtig fragen:
Ich bin totaler Anfänger und mein Problem ist das diese Dateien nicht im selben Verzeichnis liegen.
Wie äußert sich das Problem denn?
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17552
Wohnort: Berlin
|
Kleine Ergänzung: Ich habe es mal kompiliert und ausgeführt: | t201:~/proj/mini/forum > g++ datvgl.cc -o datvgl
t201:~/proj/mini/forum > echo "aha" > aha
t201:~/proj/mini/forum > echo "oha" > oha
t201:~/proj/mini/forum > ./datvgl
Erste Datei:
aha
Zweite Datei:
oha
Dateien ungleich
|
Vergleicht also doch mehr als das letzte Zeichen. Aber ich bin entschuldigt, als Nicht-C++-Mensch. ☺ 1
2
3
4
5
6
7
8
9
10
11
12
13
14 | t201:~/proj/mini/forum > echo "aha" > eho
t201:~/proj/mini/forum > ./datvgl
Erste Datei:
aha
Zweite Datei:
eho
Dateien sind gleich!!!
t201:~/proj/mini/forum > cp eho /tmp
t201:~/proj/mini/forum > ./datvgl
Erste Datei:
aha
Zweite Datei:
/tmp/eho
Dateien sind gleich!!!
|
Nie verwendet man im Deutschen mehr als ein Satzendezeichen in Folge - außer in Comics. Ein Ausrufezeichen ist eigentlich schon zuviel, da Du ja nicht weißt, was der User erwartet. Deiner Schilderung nach sollte der Normalfall sein, dass sie gleich sind, also wenn, dann ein Ausrufezeichen zum "ungleich" und den anderen Satz, aus Symetriegründen, mit einem Punkt abschließen. 😉 Dann noch zum Testen ein Trick: Das Lesen von Stdin kann über eine Pipe geschehen und so dumme Tipparbeit eliminieren: | t201:~/proj/mini/forum > echo -e "aha\n/tmp/eho"
aha
/tmp/eho
t201:~/proj/mini/forum > echo -e "aha\n/tmp/eho" | ./datvgl
Erste Datei:
Zweite Datei:
Dateien sind gleich!!!
|
Also bei mir funktioniert es, wenn ich dem ersten Anschein glaube. ☺
|
dingsbums
Anmeldungsdatum: 13. November 2010
Beiträge: 3547
|
rklm schrieb: dingsbums schrieb: | if [ "$(ms5sum /pfad/zu/original/datei1)" == "$(ms5sum /pfad/zu/backup/datei1)" ];then
|
Der Ansatz funktioniert nicht.
Stimmt. Sonst bemühe ich auch noch awk dazu. Aber ist ja mittlerweile eh irrelevant.
if [ "$(md5sum datei1 | awk '{print $1}')" == "$(md5sum datei2 | awk '{print $1}')" ];then
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12826
|
dingsbums schrieb:
Stimmt. Sonst bemühe ich auch noch awk dazu.
Es tut auch ein cut -d ' ' -f 1 .
|