[gelöst]unverständliche ausgabe, need help

Alles rund um die Programmierung mit Qt
Antworten
QtNoob
Beiträge: 10
Registriert: 8. Oktober 2007 14:06

[gelöst]unverständliche ausgabe, need help

Beitrag von QtNoob »

Ziel des Programms ist Dateien von einem Verzeichnis(sagen wir rootfolder) in ein anderes Verzeichnis(targetfolder, hat auch Unterverzeichnisse) welches Dateien mit gleichem string hat, zu verschieben.

Deklarationen

QString str1;
QString str2;
QString path;
QString pathfile;
QString rootfile;
QString targetfile;
QString ziel;

QStringList filelist;
QStringList targetfilelist;
QStringList filePathlist;

filelist enthält alle dateien aus einem ordner (z.b bilder) aber nur als fileName()
dh.
japan-_-3.gif
japan-_-4.gif
paste-_-5.png
open-_-5.png
...

das gleiche gilt für targetfilelist, es enthält aber eine liste anderer Dateien aus einem anderen Verzeichnis(durchsucht auch unterordner)
d.h.
japan-_-1.gif
japan-_-2.gif
paste-_-1.png
open-_-1.png
...

filepathlist ist genauso wie targetfilelist, aber enthält zusätzlich pfadangaben
d.h.
/home/qt/work/qt/projekt/pics2/japan1/japan-_-1.gif
/home/qt/work/qt/projekt/pics2/japan1/japan-_-2.gif
/home/qt/work/qt/projekt/pics2/paste/paste-_-1.gif
/home/qt/work/qt/projekt/pics2/open/open-_-1.png
...

rootfile holt die strings mit for schleife aus filelist
japan-_-1.gif
...

targetfile das gleiche mit targetfilelist
japan-_-3.gif
...

pathfile das gleiche mit filepathlist
/home/qt/work/qt/projekt/pics2/japan1/japan-_-1.gif

str1 holt sich den string von rootfile bis zu dem zeichen -_- (str1 kann öfters z.b japan heißen)
str2 holt sich den string von targetfile bis zu dem zeichen -_- (str2 auch)

Hier ein kleiner teil vom code, welches auch der wichtigste ist

Code: Alles auswählen

void MyWidget::compareFiles()
{ 
    listWidget->clear();
    QString str1;
    QString str2;
    QString path;
    QString pathfile;
    QString rootfile;
    QString targetfile;
    QString ziel;
    int f = 0;
    int v = 0;
    
    for (int i = 0; i< filelist.size(); ++i)
    {  rootfile = filelist.at(i);
       str1 = rootfile.section("-_-", 0, 0); 
    		
       for (int i = 0; i < targetfilelist.size(); ++i)
       { targetfile = targetfilelist.at(i);	  
         str2 = targetfile.section("-_-", 0, 0);
    	
         for(int i = 0; i<filePathlist.size(); i++)
         {
           pathfile = filePathlist.at(i);
		        
           if (str1.localeAwareCompare(str2))
           { if (pathfile.contains(str1))
             { path = pathfile.section(targetfile, 0, 0);               
	     } 
	             
            ziel = path + rootfile; 
	       
	    QString start = directoryComboBox->currentText() + rootfile;  
            QFile::rename(start , ziel);      
	    
	   }	   
	 }      
    }
    listWidget->addItem(rootfile + " moved to " + ziel);
    filesMovedLabel->setText(QString("%1").arg(listWidget->count()) + " file(s) moved");
    }    
}
das ganze funktioniert auch, aber er hängt an den dateinamen komischerweise noch den dateinamen aus targetfile rein

Ich habe das ganze ausgeben lassn wie er die dateien verschiebt:
japan-_-3.gif moved to /home/qt/work/qt/projekt/pics2/japan1/japan-_-1.gifjapan-_-3.gif
japan-_-4.gif moved to /home/qt/work/qt/projekt/pics2/japan1/japan-_-1.gifjapan-_-4.gif
open-_-5.png moved to /home/qt/work/qt/projekt/pics2/open/open1-_-1.pngopen-_-5.png
paste-_-5.png moved to /home/qt/work/qt/projekt/pics2/paste/paste-_-1.pngpaste-_-5.png
usw...

wenn ich aber statt if (pathfile.contains(str1)), if (pathfile.contains(targetfile)) reinschreibe, verschiebt er alle dateien durcheinander :roll:
japan-_-3.gif moved to /home/qt/work/projekt/pics2/paste/japan-_-3.gif
japan-_-4.gif moved to /home/qt/work/projekt/pics2/paste/japan-_-4.gif
open-_-5.png moved to /home/qt/work/qt/projekt/pics2/japan1/open-_-5.png
paste-_-5.png moved to /home/qt/work/qt/projekt/pics2/japan1/paste-_-5.png

an was liegt es?ich habe so eine vermutung das es an meinen schleifen liegt, jedoch hocke ich seit 2 tagen schon dran und finde immer noch nichts xD

falls weiterer code gewünscht wird werde ich dies hinzufügen.
Zuletzt geändert von QtNoob am 25. Oktober 2007 15:35, insgesamt 7-mal geändert.
FaS
Beiträge: 184
Registriert: 25. Mai 2006 19:48
Kontaktdaten:

Beitrag von FaS »

Ich würde mal sagen es ist nicht ganz verständlich was die konkrete Aufgabe ist.
das gleiche gilt für targetfilelist, es enthält aber eine liste anderer Dateien aus einem anderen Verzeichnis(durchsucht auch unterordner)
Wenn die Zielliste andere Dateien enthält und auch noch in versch. Ordnern, diese in der Quellliste aber nicht auftauchen, was macht es dann für ein Sinn sie dorthin zu verschieben...
Deine Schleifen scheinen irgendwie auch nicht ganz logisch, und

Code: Alles auswählen

str1.localeAwareCompare(str2)
ist meines erachtens dasselbe wie

Code: Alles auswählen

str1 != str2
nur ineffizienter -- war das gewollt?
Vielleicht erklärst du dein Problem mal etwas abstrakter aber deutlicher, und wozu beachtest du die Namen nur bis "-_-"??
Wenn das Problem folgendes ist:

Code: Alles auswählen

Quelle   Ziel
Datei1   Pfad2/Datei2
Datei2   Pfad1/Datei1
Datei3   Pfad3/Datei3
und du lediglich die korrekte Zuordnung suchst (Datei1 -> Pfad1/Datei1), warum sagst du es dann nicht einfach? Werd aus deinen Angaben nicht schlau.

MfG,
FaS
QtNoob
Beiträge: 10
Registriert: 8. Oktober 2007 14:06

Beitrag von QtNoob »

Wenn die Zielliste andere Dateien enthält und auch noch in versch. Ordnern, diese in der Quellliste aber nicht auftauchen, was macht es dann für ein Sinn sie dorthin zu verschieben...
z.b wenn man bilder hat, da ich weiß das meine bilder sich erst ab dem zeichen "-_-" unterscheiden
z.b bild-_-1.jpg, bild-_-2.jpg
und möchte es in ein verzeichnis stecken das schon z.b bild-_-3.jpg, bild-_-4.jpg enthält

(das prog soll einfach nur das ausschneiden erleichtern, bei vielen dateien)

1. ich gebe ihm einen ordner an:
2. er packt alle dateien in einer liste (filelist)
3. er geht die zielliste(targetfilelist) durch und schaut ob es dateien mit dem gleichen string schon existieren, falls ja packt die dateien aus filelist in den ordnern, welche schon dateien haben mit dem gleichen string

Code: Alles auswählen

str1.localeAwareCompare(str2)
ist meines erachtens dasselbe wie

Code: Alles auswählen

str1 != str2 
stimmt nicht, ist dasselbe wie

Code: Alles auswählen

str1 == str2
aber da hat er probleme mit der codierung deswegen localeAwareCompare()
Vielleicht erklärst du dein Problem mal etwas abstrakter aber deutlicher, und wozu beachtest du die Namen nur bis "-_-"??
siehe oben, die dateien haben bis zu dem -_- den gleichen string
und du lediglich die korrekte Zuordnung suchst (Datei1 -> Pfad1/Datei1), warum sagst du es dann nicht einfach? Werd aus deinen Angaben nicht schlau.
falsch, siehe oben ;)

mein problem ist, er verschiebt es in die richtigen ordner aber hängt da beim verschieben noch komischerweise ein string rein von einen targetfile, und ich weiß nicht wieso, da ich den teil eigentlich schon abschneide und nur noch den pfad habe.

gruß

ps. hab oben filepathlist die pfade verändert, evtl ums besser zu verstehen
FaS
Beiträge: 184
Registriert: 25. Mai 2006 19:48
Kontaktdaten:

Beitrag von FaS »

ahhh ok jez weiß ich was du willst ;-)

1)

Nochmal zum localeAwareCompare: aus der Doku:
int QString::localeAwareCompare ( const QString & other ) const
[...]
Compares this string with the other string and returns an integer less than, equal to, or greater than zero if this string is less than, equal to, or greater than the other string.
[...]
Mit
if (str1.localeAwareCompare(str2))
prüfst du quasi ob das Ergebnis != 0 ist (0==false, -1, 1 und alles andere ist ==true). Und wenn die beiden Strings gleich sind, ist das Ergebnis ja wohl ==0 und die if-Abfrage negativ.

-----
2)
aber da hat er probleme mit der codierung deswegen localeAwareCompare()
Soweit ich weiß ist in QString immer alles gleich codiert: UTF-8. Und localeAwareCompare bezieht sich doch nur auf Zahlen-/Datumsformate usw oder nicht?

-----
----- zum Thema
3)

a) Konflikte:
Was, wenn es in mehreren Ordnern äquivalente Dateien gibt?
Was, wenn "-_-" im Verzeichnisnamen auftaucht?
usw..

b) Der Fehler:
Du läufst targetfilelist und filePathlist nicht gleichzeitig ab, d.h. bei

Code: Alles auswählen

path = pathfile.section(targetfile, 0, 0);
könnte pathfile=="/home/qt/work/qt/projekt/pics2/japan1/japan-_-1.gif" sein und targetfile=="japan-_-2.gif" - daher wird der Text nicht abgeschnitten.
Aber auch so finde ich hast du ein paar break;s vergessen und da targetfilelist und filePathlist gleich sortiert sind, solltest du beides nicht nacheinander durchlaufen, benutz den Zähler von targetfilelist auch für den filePathlist-Zugriff. Dann müsste zumindest dein Urproblem fürs erste beseitigt sein. Guck dir aber mal genau deine Schleifen an und überleg wann du welche abbrechen musst usw..

MfG,
FaS
QtNoob
Beiträge: 10
Registriert: 8. Oktober 2007 14:06

Beitrag von QtNoob »

also es tut nun soweit, komisch da hockt man ewig dran und dann kommt jemand und gibt tips und es tut dann :D

Code: Alles auswählen

void MyWidget::compareFiles()
{ 
    listWidget->clear();
    QString str1;
    QString str2;
    QString path;
    QString pathfile;
    QString rootfile;
    QString targetfile;
    QString ziel;
     
    for (int i = 0; i< filelist.size(); ++i)
    {  rootfile = filelist.at(i);
       str1 = rootfile.section("-_-", 0, 0); 
    
 		
       for (int i = 0; i < targetfilelist.size() && i < filePathlist.size(); ++i)
       { targetfile = targetfilelist.at(i);	  
         str2 = targetfile.section("-_-", 0, 0);
    	
    	 pathfile = filePathlist.at(i);
            
           if (str1 == str2)
           { if (pathfile.contains(targetfile))
             { 
	       path = pathfile.section(targetfile, 0, 0);
	            
               ziel = path + rootfile; 
	       
	       QString start = directoryComboBox->currentText() + rootfile;  
               QFile::rename(start , ziel);      
	     }           
	   }	   
    }
    listWidget->addItem(rootfile + " moved to " + ziel);
 
    filesMovedLabel->setText(QString("%1").arg(listWidget->count()) + " file(s) moved");
    
    }    
}
danke nochmals :wink:
ich hoffe das stimmt so, auf jedenfall funktioniert es.

btw, ich verstehe nicht wieso ich break;s einfügen sollte, habe noch nie in for & if schleife breaks reingebaut, kenne es nur von switch schleifen
FaS
Beiträge: 184
Registriert: 25. Mai 2006 19:48
Kontaktdaten:

Beitrag von FaS »

break bedeutet bei Schleifen dasselbe wie woanders auch, dass sie abgebrochen werden (nur die innerste Schleife, in der dieses Schlüsselwort auftaucht).
Du suchst doch zu jeder Quelldatei ihren Bestimmungsort anhand bereits vorhandener Dateien in den Zielverzeichnissen. Hast du diesen gefunden, verschiebst du sie dort hin. Ohne das break sucht der Algorithmus aber weiter nach neuen Bestimmungsorten und findet diesen bei jeder Datei, die den Anforderungen entspricht, also sogar mehrmals pro Verzeichnis - aber die Quelldatei hat doch schon längst ihr Zuhause gefunden. Du hast nur Glück, dass QFile::rename bei Fehlversuchen einfach false zurückgibt, ineffizient/redundant ist es trotzdem. Und noch schlimmer: Wenn es in anderen Verzeichnissen zufällig auch passende Dateien gibt, ändert der "ziel" entsprechend, rename liefert weiterhin false, aber in deiner Log-Liste erscheint dann der neue Zielordner, in der die Datei überhaupt garnicht verschoben wurde, da du diese Status-Sachen erst am Ende der Schleife machst. Man sollte aber immer schön zusammenhängende Sachen auch zusammen schreiben, dann hättest du auch so gemerkt, dass deine Schleife viel zu weit geht.
Und man könnte sagen deine doppelte Listengröße-Abfrage im if() schützt vor Abstürzen/Fehlern, aber in Wirklichkeit vertuscht sie diese, falls vorhanden. Dasselbe gilt für dein "str1 == str2"-Test, ich hab das mal rausgenommen in ein assert(), d.h. es werden diese Dinge hier einfach erwartet und diese Zusicherung prüft das und gibt ggf. eine Fehlermeldung aus. Falls dein Compiler das nicht unterstützt, lösch die beiden asserts oder lass es wie du es hattest, ist ja auch wurscht... aber break nicht vergessen.

Code: Alles auswählen

void MyWidget::compareFiles()
{
  assert( targetfilelist.size() == filePathlist.size() );

  listWidget->clear();
  QString str1;
  QString str2;
  QString path;
  QString pathfile;
  QString rootfile;
  QString targetfile;
  QString start;
  QString ziel;
   
  for( int i = 0; i < filelist.size(); ++i )
  {
    rootfile = filelist.at(i);
    str1 = rootfile.section( "-_-", 0, 0 );

    for( int i = 0; i < filePathlist.size(); ++i )
    {
      targetfile = targetfilelist.at(i);    
      str2 = targetfile.section( "-_-", 0, 0 );
      assert( str1 == str2 );
     
      pathfile = filePathlist.at(i);
      
      if( pathfile.contains( targetfile ) )
      {
        path = pathfile.section( targetfile, 0, 0 );
          
        ziel = path + rootfile;
      
        start = directoryComboBox->currentText() + rootfile;
        QFile::rename( start , ziel );
        
        listWidget->addItem( rootfile + " moved to " + ziel );
        filesMovedLabel->setText( QString("%1").arg(listWidget->count()) + " file(s) moved" );
        
        break;
      }
    } // for filePathlist
  } // for filelist
}
QtNoob
Beiträge: 10
Registriert: 8. Oktober 2007 14:06

Beitrag von QtNoob »

verständlich was du geschrieben hast, ich hatte vor lauter schleifen den Durchblick verloren :roll:
Wieder was dazu gelernt.
Ich habe dein code mal compiliert, aber sobald die Methode aufrufe
kommt ein error bei der Zeile assert( str1 == str2 );
Assertion `str1 == str2' failed.

nächste Frage : Ich habe es mal unter Windows compiliert, es tut nur das halbe Programm, verschieben funktioniert gar nicht.
Das was tut ist: Ich habe ein tableWidget und darin werden die Dateien von filelist gelistet, ich bin gerade am forschen ob es an den Pfadangaben liegt, aber wenn das Auflisten geht wieso dann nicht verschieben, weil die Pfadangaben genauso übergeben werden.

/edit1, ich werde es versuchen selbst zu lösen und den fehler-bereich einzuschränken

/edit2 filelist scheint leer zu sein...geh ich mal näher untersuchen

/edit3 gelöst, ein QDir::separator() hat gefehlt, welches unter linux hinzufügt wird und unter windows nicht.
FaS
Beiträge: 184
Registriert: 25. Mai 2006 19:48
Kontaktdaten:

Beitrag von FaS »

Bei Qt wird unabhängig vom darunterliegenden System ein slash (/) als Verzeichnisseparator verwendet, QDir::separator() liefert unter Windows aber den backslash (\). D.h. wenn es damit bei dir funktioniert, hast du irgendwo was falsch gemacht oder manuell irgendwo den backslash benutzt..
Assertion `str1 == str2' failed.
Ja is klar is blödsinn das ganze. Man muss, wenn überhaupt, das Ende von pathfile mit targetfile vergleichen, da diese gleich sein müssen. Aber eigentlich ist diese targetfilelist eh überflüssig.
Und auch mein if-Vergleich da unten ist schwachsinn.

Korrigiert und ohne targetfilelist:
(Man könnte auch noch vor den beiden Schleifen 2 Listen erstellen mit vorberechneten targetfile- und targetalias-Einträgen der filePathlist, da diese in der 2. Schleife jedes mal neu berechnet werden, und zwar für jeden Eintrag aus der 1. Liste immer wieder neu. Wäre dann also schneller)

Code: Alles auswählen

void MyWidget::compareFiles()
{
  listWidget->clear();
  QString rootfile;
  QString pathfile;
  QString targetfile;
  QString rootalias;
  QString targetalias;
  QString start;
  QString ziel;
  int iPathEnd;
   
  for( int i = 0; i < filelist.size(); ++i )
  {
    rootfile = filelist.at(i);
    rootalias = rootfile.left( rootfile.lastIndexOf( "-_-" ) ).toLower();
    
    for( int i = 0; i < filePathlist.size(); ++i )
    {
      pathfile = filePathlist.at(i);
      iPathEnd = pathfile.lastIndexOf( '/' );
      targetfile = pathfile.mid( iPathEnd + 1 );
      targetalias = targetfile.left( targetfile.lastIndexOf( "-_-" ) ).toLower();
     
      if( rootalias == targetalias )
      {
        start = directoryComboBox->currentText() + rootfile;
        ziel = pathfile.left( iPathEnd ) + rootfile;
     
        QFile::rename( start , ziel );
       
        listWidget->addItem( rootfile + " moved to " + ziel );
        filesMovedLabel->setText( QString("%1").arg(listWidget->count()) + " file(s) moved" );
       
        break;
      }
    } // for filePathlist
  } // for filelist
}
QtNoob
Beiträge: 10
Registriert: 8. Oktober 2007 14:06

Beitrag von QtNoob »

wieder was falsch, damit wären wir fast bei meinem alten problem :wink:
Die Ausgabe:
japan-_-3.gif moved to /home/qt/work/qt/projekt/pics2/japan1japan-_-3.gif
japan-_-4.gif moved to /home/qt/work/qt/projekt/pics2/japan1japan-_-4.gif
paste-_-5.png moved to /home/qt/work/qt/projekt/pics2/pastepaste-_-5.png
open-_-5.png moved to /home/qt/work/qt/projekt/pics2/open1open1-_-5.png

diesmal verschiebt er alles in den übergeordneten ordner
Bei Qt wird unabhängig vom darunterliegenden System ein slash (/) als Verzeichnisseparator verwendet, QDir::separator() liefert unter Windows aber den backslash (\). D.h. wenn es damit bei dir funktioniert, hast du irgendwo was falsch gemacht oder manuell irgendwo den backslash benutzt..
in Windows ist die Verzeichnisangabe ja so:
z.b U:\pics2
und er weiß damit nicht, das er in dem Ordner suchen soll, deswegen hab ich auch ein QDir::separator() eingefügt am ende, so denke ich jedenfalls
FaS
Beiträge: 184
Registriert: 25. Mai 2006 19:48
Kontaktdaten:

Beitrag von FaS »

in Windows ist die Verzeichnisangabe ja so:
z.b U:\pics2
Qt ist ein systemunabhängiges Toolkit und dazu gehört auch die Dateisystem-Kapselung. Selbst in Windows sollte die Ausgabe U:/pics2 sein, und da Qt-Funktionen dies meist auch so erwarten solltest du es auch einhalten, also auch keine QDir::separator() oder expliziz '\\' verwenden usw., diese Sachen werden nur benötigt wenn man Verzeichnisangaben ausßerhalb von Qt verwenden muss. Falls du z.B. vom Benutzer Verzeichnisangaben erhältst, wandelt man diese mit QDir::fromNativeSeparators() um.

Zum Problem:
Da fehlt doch bloß ein 1 Zeichen aus pathfile, nämlich '/'. Ändere

Code: Alles auswählen

        ziel = pathfile.left( iPathEnd ) + rootfile;
in

Code: Alles auswählen

        ziel = pathfile.left( iPathEnd+1 ) + rootfile;
Und noch eine mögliche Fehlerquelle: Ich weiß nicht was directoryComboBox->currentText() zurückliefert, wenn es wirklich in jedem Fall den letzten slash anhängt, also "C:/", oder "C:/dir/" ist alles in Ordnung, wenn es das niemals tut, z.B. "C:" oder "C:/dir", muss das

Code: Alles auswählen

        start = directoryComboBox->currentText() + '/' + rootfile;
heißen, wenn teilweise z.B. "C:/" und "C:/dir", dann kannst du das so machen, damit werden ggf. doppelte slashes entfernt:

Code: Alles auswählen

        start = QDir::cleanPath( directoryComboBox->currentText() + '/' + rootfile );
QtNoob
Beiträge: 10
Registriert: 8. Oktober 2007 14:06

Beitrag von QtNoob »

ja deine methode funktioniert auch soweit, habs auch näher angeschaut, hätte ich auch so machen können, aber jeder denkt halt anders^^
Es ist in der tat etwas komisch mit meiner Verzeichnisangabe.

Code: Alles auswählen

void MyWidget::find()
{
     filesTable->setRowCount(0);
     
     QString path = directoryComboBox->currentText();

     QDir directory = QDir(path);
     QStringList files;

     if (!directory.exists())
     { QMessageBox::information(this, tr("Information"),
                               tr("Verzeichnis nicht gefunden."),
                               QMessageBox::Ok); }
     else
     { files = directory.entryList(QStringList(filters),
                                 QDir::Files | QDir::NoSymLinks);

       showFiles(directory, files);
       for(int i = 0; i < files.size(); i++)
       { addFiles(path + QDir::separator() + files.at(i)); } 
//        { addFiles(directory + files.at(i)); } 
       writeTargetDir(); }
            
}

void MyWidget::addFiles( QString file )
{
    QFileInfo f( file );
    
    if ( f.isFile() )
    { filelist.append( f.fileName() ); }
}
er kriegt die Verzeichnisangabe so übergeben, wenn unter linux einen ordner auswähle :
/home/qt/work/qt/projekt/pics/
dh. mit dem QDir::separator() kommt noch ein / dazu,
aber wenn ich das weglasse, ist in windows meine filelist leer

unter windows, wenn ich einen ordner auswähle
D:/upload/projekt/pics

ist ja eigentlich auch logisch das dann ein / fehlt, unter Linux dürft ihm das doppel // wohl nicht stören, geht zwar aber nicht schön gelöst.
FaS
Beiträge: 184
Registriert: 25. Mai 2006 19:48
Kontaktdaten:

Beitrag von FaS »

dann ändere doch

Code: Alles auswählen

addFiles(path + QDir::separator() + files.at(i));
in

Code: Alles auswählen

addFiles( QDir::cleanPath( path + '/' + files.at(i) ) );
MfG,
FaS
QtNoob
Beiträge: 10
Registriert: 8. Oktober 2007 14:06

Beitrag von QtNoob »

wow nun tut alles :D
nun gut, ich glaube der thread ist endgültig gelöst, danke für die hilfe :wink:
Antworten