unzip and untar into new directory
I have a file that is file.tar.gz and I would like to implement an open function from GUI menu that allows the user to select the tar.gz file and the application unzip, untar, and place those files in a specified directory. I don't think there is a Qt function that can do all of the above (but maybe some) but I was curious on any suggestions on how to implement this functionality.
Thanks for any help!
Re: unzip and untar into new directory
use QProcess to start an unzip utility e.g. 7z or equivalent.
Re: unzip and untar into new directory
Is there anyway to do it without using QProcess? I am trying to avoid needing to install any third party software with my application.
Re: unzip and untar into new directory
Ok so I have decided to use peazip for the QProcess but I do not understand how to use QProcess very well. I downloaded the peazip portable and placed the executable in the same directory as my application. I tried to do the following:
Code:
MainWindow::open()
{
arguments << "-ext2here" << "file.tar.gz";
unarchive->start("peazip", arguments);
// other things happen
}
Unfortunately nothing seems to be happening so I am curious what I am missing. Thanks for any help!
Re: unzip and untar into new directory
What sort of 'nothing' is happening? Is the QProcess object emitting an error() signal? Where is the peazip executable in relation to the current working directory of your process?
Re: unzip and untar into new directory
how are you testing? by debugging through an IDE or just running your program 'manually'? If the former, you probably just have a problem where your app is not run from the same location as the unzip utility
Re: unzip and untar into new directory
Duh! I was running it in debug mode and didn't put the peazip executable in the correct directory... It seems to be working fine now!!
I do have another question that might be answered here, can you do an OS check with Qt? I don't see a Linux version of the peazip portable so I am thinking I will need a #if statement to check for Windows OS and use peazip but if it is Linux use standard unix unarchiving/archiving commands. How would you call the unix terminal to unzip and untar a file?
Thanks again for any help!
Re: unzip and untar into new directory
So I am able to have the QProcess execute the unzip and untar but when I try and run something after the untar nothing appears to be happening.
Code:
{
if(okToContinue())
{
QString fileName
= QFileDialog::getOpenFileName(this, tr
("Open file.tar.gz file"),
".", tr
("gzip tarball" "(*.tar.gz)"));
if(!fileName.isEmpty())
{
arguments << "-ext2here" << fileName;
unarchive->start("peazip", arguments);
if(unarchive->waitForFinished())
{
fileName.remove(".gz");
arguments.clear();
arguments << "-ext2here" << fileName;
int exitCode = unarchive->execute("peazip", arguments);
if(unarchive->waitForFinish())
{
fileName.remove("file.tar");
// this is the path that is extracted from tar and the .csv is what I am after
fileName.append(("tmp/file/A.csv"));
loadFile(fileName);
}
}
}
}
}
It never seems to make it inside the second waitForFinish if statement. What am I doing wrong?
Thanks for help!
Re: unzip and untar into new directory
why are you mixing execute/start? Why are you allocating on the heap when you only want a local instance?
I believe the problem is that you are using execute, which is a static method, therefore the finished state required for 'waitForFinished' is not modified.
Re: unzip and untar into new directory
I was just experimenting with how QProcess works that is why the execute/start mixture is being used. The second question was again just me mimicking an exmaple I saw in the Qt Assitant manual. I went ahead and switched QProcess to allocate on the stack instead of the heap (which is definitely a better idea). Anyway I can't seem to figure out how to make the unzip and untar work and then have the newly created directory pick up the new file created in there.
I keep getting the following error:
Cannot read File:
C:/.../tmp/file/A.csv
The system cannot find path specified..
I am a little confused as to why it can't find it when I go to the file directory and everything is as it should be.
Here is the new code I am using:
Code:
void MainWindow::open()
{
if(okToContinue())
{
QString fileName
= QFileDialog::getOpenFileName(this, tr
("Open file.tar.gz file"),
".", tr
("gzip tarball" "(*.tar.gz)"));
if(!fileName.isEmpty())
{
arguments << "-ext2here" << fileName;
unarchive.start("peazip", arguments);
if(unarchive.waitForFinished())
{
unarchive.close();
fileName.remove(".gz");
arguments.clear();
arguments << "-ext2here" << fileName;
unarchive.start("peazip", arguments);
if(unarchive.waitForFinished())
{
unarchive.close();
fileName.remove("file.tar");
cout << fileName.toStdString() << endl;
fileName.append(("tmp/file/A.csv"));
cout << fileName.toStdString() << endl;
}
}
loadFile(fileName);
}
}
}
My problem is when loadFile is being called the file is not being found and I am not sure why that is. FYI, I wasn't unziping and untaring automatically at first so I know if the fileName being passed to loadFile is correct it works as it should.
Thanks for any help!
Added after 20 minutes:
It appears to be a permission problem maybe... I am still unsure but this code should help a little bit I think.
Code:
if(!fileName.contains("global_urn_r.csv"))
{
QMessageBox::warning(this, tr
("Loading Error"), tr
("Must open a global_urn_r.csv file in order to load properly"));
return false;
}
{
QMessageBox::warning(this, tr
("Unable to Load File"), tr
("Cannot read file %1:\n%2.").
arg(inFile.
fileName()).
arg(inFile.
errorString()));
statusBar()->showMessage(tr("Loading canceled"), 2000);
return false;
}
Re: unzip and untar into new directory
Figured out that the loadFile function is running when the file is being untared... Not sure why it doesn't wait until untar is done?
Re: unzip and untar into new directory
probably down to you re-using the same QProcess instance. Create a new instance for the second run.
Re: unzip and untar into new directory
Tried that theory out as well and unfortunately doesn't seem to matter. But I was able to just make a while loop to wait until I find the directory I am looking for. This appears to be working but then I get completely lost as to why I can't traverse the directory. The code seems to find the directory then the very next statement says that it didn't find it, very confusing so I will just show it to you.
Code:
untar.start("peazip", arguments);
if(untar.waitForFinished())
{
untar.close();
fileName.remove("file.tar");
while(!dir.cd("tmp"))
cout << "Waiting for tmp to be created\n";
}
if(dir.cd("tmp"))
cout << "tmp has been created and found\n";
if(!dir.cd("tmp"))
qWarning("Cannot find the \"/tmp\" directory");
else
{
if(!dir.cd("file"))
qWarning("Cannot find the \"/file\" directory");
else
{
QFile file(dir.
filePath("A.csv"));
if(!file.exists())
qWarning("A.csv");
else
loadFile(file.fileName());
}
}
I don't understand why the output is the following:
Waiting for tmp to be created
...
tmp has been created and found
Cannot find "/tmp" directory
I am really confused as to why one line finds it the other doesn't...
Re: unzip and untar into new directory
do you have directory tmp/tmp ? If not, what are you thinking?
And also, what on earth are you doing with infinite loops waiting for directories? It just such a hack! If you really need to wait for file system things, then use qfilesystemwatcher
Re: unzip and untar into new directory
The directory path is correct it is C:\...\tmp\file\A.csv. Anyway on to your second question, I am still very new to Qt (just been using it about a year or so) and I haven't worked with traversing directories on my own. The infinite loops, in theory aren't infinite loops but if the files weren't extracted correctly then it could potentially have some serious issues. I know it is a hack but for now that is the only way I know how to keep checking directories. I have read some of the stuff on QFileSystemWatcher but I don't know how to use it properly although I will try. Could you maybe show me a sample of how that class would be used for what I am trying to do?
Re: unzip and untar into new directory
if the directory is c:\...\tmp\a.csv, you cannot say you are also correct to look for c:\...\tmp\tmp, which is what you are doing.
Re: unzip and untar into new directory
Oh I see what I did there, that was just me not understanding that cd took it to that directory when it found it. So when I successfully cd to temp, then the next call to cd tmp doesn't exst. I understand I made a mistake there. However I am still not sure how to use QFileSystemWatcher, I tried using a connect statement like the following:
Code:
connect(&watcher,
SIGNAL(directoryChanged
(QString),
this,
SLOT(directoryUpdated
(QString));
Where 'this' is the QMainWindow and the slot is a newly created slot that should be picking when the directory changes. In the slot function I currently have a simple cout statement so that I know it was making the connection however it doesn't appear that it is ever making it to the slot function. Basically I took out the first while loop while(!dir.cd("tmp")) inside of the if statement and got ride of all the other code and just have the following:
Code:
watcher.addPath(fileName); // path where the tarball is being extracted
// connection statement here
Any Ideas what I am doing wrong?
Re: unzip and untar into new directory
Quote:
Originally Posted by
jshafferman
Where 'this' is the QMainWindow and the slot is a newly created slot that should be picking when the directory changes. In the slot function I currently have a simple cout statement so that I know it was making the connection however it doesn't appear that it is ever making it to the slot function. Basically I took out the first while loop while(!dir.cd("tmp")) inside of the if statement and got ride of all the other code and just have the following:
Code:
watcher.addPath(fileName); // path where the tarball is being extracted
// connection statement here
Any Ideas what I am doing wrong?
why don't you just show some complete code. Instead everybody has to code and compile in their head. It's not very endearing...
Re: unzip and untar into new directory
No problem here is the full chunk of code that I am trying to execute...
Code:
void MainWindow::open()
{
if(okToContinue())
{
QString fileName
= QFileDialog::getOpenFileName(this, tr
("Open file.tar.gz file or A.csv"),
".", tr
("Data Files (*.tar.gz *.tar *.csv)"));
if(!fileName.isEmpty() && fileName.contains("tar.gz"))
{
arguments << "-ext2here" << fileName;
unarchive.start("peazip", arguments);
if(unarchive.waitForFinished())
{
unarchive.close();
fileName.remove(".gz");
arguments.clear();
arguments << "-ext2here" << fileName;
}
untar.start("peazip", arguments);
if(untar.waitForFinished())
{
untar.close();
fileName.remove("file.tar");
while(!dir.cd("tmp"))
cout << "Waiting for tmp to be created\n";
}
if(dir.cd("tmp"))
{
cout << "tmp has been created and found\n";
if(dir.cd("file"))
{
cout << "file has been created and found\n";
cout << "Absolute path: " << dir.absolutePath().toStdString() << endl;
// says 11 when it should be 40...
while(dir.count() < 40)
{
cout << "Number of files: " << dir.count() << endl;
dir.refresh();
}
QFile file(dir.
filePath("A.csv"));
if(file.exists())
{
cout << "A.csv has been created and found\n";
cout << "Filename is: " << file.fileName().toStdString() << endl;
loadFile(file.fileName());
}
else
{
cout << "Cannot find A.csv\n";
}
}
}
}
else if(!fileName.isEmpty() && fileName.contains("A.csv"))
{
loadFile(fileName);
}
}
}
That is my 'hack' way of doing it right now. This is me trying to figure out how QFileSystemWatcher works in order to make it work without the nasty hacks.
Code:
void MainWindow::open()
{
if(okToContinue())
{
QString fileName
= QFileDialog::getOpenFileName(this, tr
("Open file.tar.gz file or A.csv"),
".", tr
("Data Files (*.tar.gz *.tar *.csv)"));
if(!fileName.isEmpty() && fileName.contains("tar.gz"))
{
arguments << "-ext2here" << fileName;
unarchive.start("peazip", arguments);
if(unarchive.waitForFinished())
{
unarchive.close();
fileName.remove(".gz");
arguments.clear();
arguments << "-ext2here" << fileName;
}
untar.start("peazip", arguments);
if(untar.waitForFinished())
{
untar.close();
fileName.remove("file.tar");
}
QFileSystem watcher;
watcher.addPath(fileName);
connect(&watcher,
SIGNAL(directoryChanged
(String
),
this,
SLOT(directoryModified
(QString));
}
}
void MainWindow::directoryModified(const QString& path)
{
QMessageBox::information(this,
"Directory Modified",
"Your Directory is modified");
// not sure what I am going to do yet...
}
When I run the 'correct' way of doing things I never see the information box pop up... So I am assuming I am somehow not using QFileSystemWatcher class correctly. Any help is greatly appreciated.
Re: unzip and untar into new directory
you put the watcher on the stack...