Delete file in directory with extension - c++

Hi I'm trying to iterate through directories and remove files with the extension "~" here is my code
QString path = "/home/brett/sweetback";
QDirIterator it(path, QDirIterator::Subdirectories);
while (it.hasNext()) {
//ui.textEdit->append(QString(it.next()));
QFileInfo Info(it.next());
//ui.textEdit->append(QString(Info.fileName()));
QString testName = QString(Info.fileName());
QString subString = testName.right(1);
if(subString == QString("~")){
//wnat to remove file here
ui.textEdit->append(QString(subString));
remove(QString( testName));
}
}
I can list the file fine but cant figure out how to delete them

I think you're looking for QFile::remove()
It's a static member of QFile, so you would use it like this:
QFile::remove(testName);

bool QFile::remove(const QString & fileName) [static]
This is an overloaded function.
Removes the file specified by the fileName given.
Returns true if successful; otherwise returns false.
So, change your code:
remove(QString( testName));
to:
if (!QFile::remove(testName))
qDebug() << "Could not remove the file:" << testName;
Note that you do not need to cast a QString to QString explicitly. That is superfluous.
You could also use the non-static member method, and then you could even get the error string by using errorString() for the QFile instance when the deletion is not successful.
If you would also like to delete whole directories recursively having the desired ~ suffix, you would need to use the remove member method in QDir for such cases.

Related

Is there a way to loop through only jpg files?

I want to crop just only jpg files in a directory.
Tried if statement, but don't know what should inside if().
void Cutimage::load_images(string img_prefix)
{
for (const auto& entry : fs::directory_iterator(img_prefix)) {
cout << entry.path() << endl; //output all directory's filenames
if () { //I applied some statements but doesn't work
string path_string = entry.path().string();
crop_images(path_string);
}
}
No, the filesystem utilities of the standard library do not have such feature. However, it is fairly simple to iterate all directory entries, and conditionally perform an operation if the file name ends in ".jpg", which appears to be what you've attempted.
Tried if statement, but don't know what should inside if().
The directory entry has an member function that returns the full path of the directory. The path class has an member function that returns a string. The string class has a member function that returns true if the string ends with the sub string given as an operand. This appears to be what you're looking for.

How to pass in filename as a parameter and opening it properly?

void openfile(const string &db_filename) {
ifstream file;
file.open("db_filename");
if(file.is_open())
{
cout<<"true"<<endl;
}
else cout<<"false"<<endl;}
I have this simple code here that checks if file is open. However, whenever I run this, I get false. which means that the file is not open. I dont know why but Im sure that the files are in the same folder and the file name is entered correctly. Is there anything wrong with this code?
You are passing a string literal "db_filename" to open() instead of passing your db_filename string object. Simply remove the quotes:
file.open(db_filename);
If your version of the STL doesn't support passing a std::string to open(), call the string's c_str() method instead:
file.open(db_filename.c_str());

Properly storing QFiles in a collection

What is the best way to store multiple QFile in a collection? Would be best to use QList, array, or vectors?
I want to access the element of the collection as a QFile and not QFile*.
I'm trying to read a directory in Qt and store all the files in a collection. Then print all the file names to the screen.
How I'm reading the directory:
QDirIterator it(p_dir, QStringList() << "*.wav", QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext())
{
// Put file into collection
}
Currently I'm using QList to store the QFiles:
QList<QFile*> list;
I read that the best way to get file information is to use QFileInfo type. How could I set the QFileInfo file to be the element from my list?
I want to do something like:
QFileInfo info;
QListIterator<QFile*> i(list);
while(i.hasNext())
{
info.setFile(i);
}
But the above gives me:
error: no matching function for call to 'QFileInfo::setFile(QListIterator&)'
fi.setFile(i);
Keep in mind QFile inherits QObject, and as such is not copyable or movable. It is common practice to store pointers to such objects in containers rather than the objects themselves. As for which container to use, it doesn't really matter much, but QVector will be the most efficient.
QListIterator is a Java style iterator. So:
QListIterator::QListIterator(const QList<T> & list)
Constructs an iterator for traversing list. The iterator is set to be
at the front of the list (before the first item).
The iterator doesn't point to anything, if you want to get the actual object, use i.next() to give you a QFile* which you then will have to dereference, since setFile() takes in a QFile &, not a QFile *.
QFile is not copyable. In C++98, there's generally no way of storing it in a container, unless the container supports in-place construction. I don't know offhand of any such C++98 containers, although writing one wouldn't be all that hard.
In C++11, you can use any container that doesn't need to copy elements and supports emplacement, e.g. std::list:
// https://github.com/KubaO/stackoverflown/tree/master/questions/qfile-list-36391586
#include <QtCore>
#include <list>
void populate(std::list<QFile> & files) {
QDir dir(QCoreApplication::applicationDirPath());
for (auto fileName : dir.entryList(QDir::Files)) {
qDebug() << "adding file" << fileName;
files.emplace_back(fileName);
}
}
void iterate(std::list<QFile> & files) {
for (auto & file : files)
if (file.open(QIODevice::ReadOnly)) {
qDebug() << "successfully opened" << file.fileName();
}
}
int main(int argc, char ** argv) {
QCoreApplication app(argc, argv);
std::list<QFile> files;
populate(files);
iterate(files);
}
On my system, when run from Qt Creator, the output is:
adding file "main.o"
adding file "Makefile"
adding file "qfile-list-36391586"
successfully opened "main.o"
successfully opened "Makefile"
successfully opened "qfile-list-36391586"
Since QFile is a proper class implementing RAII of system resources, the files will get automatically closed by files::~list, before main returns.
I'm currently manipulating QFileInfo based on certain criterian/logics..but if I just filter all the complicated logic, it would be something like
QDir testDir("/home/mypath/to/dir");
QFileInfoList files = testDir.entryInfoList(); // #1. here you may use filters as I'm filtering based on a specific file extension
QFileInfoList myfiles;
for(int index = 0; index < files.size(); ++index)
{
const QFileInfo& info = files.at(index);
qDebug() << info.absoluteFilePath() << endl;
// #2. I've some sort of filters I used in #1 above that I compares here by utilizing info here, something like
//if (info.baseName().contains("anyPattern");
myfiles.push_back(info);
}
// Now you can view whatever you stored
for (int vw_idx = 0; vw_idx < myfiles.size(); ++vw_idx)
{
const QFileInfo& info = files.at(index);
qDebug() << info.absoluteFilePath() << endl;
}

Qt - c++ : about how to use QFileInfo without object

I'm sorry if this was asked before but I couldn't get the right words in search and that might have effected the search results , anyways I returned to c++ and I decided to program a simple tool , while I was programming I needed a way to search for a file in Qt , this is the code:
void Main_Sorter::SearchForFile(QString Path , QString extention , QString FileName)
{
QDirIterator dir(Path , QDirIterator::Subdirectories);
while(dir.hasNext())
{
dir.next();
if(QFileInfo(dir.filePath()).isFile())
if(QFileInfo(dir.filePath()).suffix() == extention)
if(QFileInfo(dir.filePath()).fileName() == FileName)
qDebug()<<"file found ! " + FileName;
}
}
I was wondering how are we using the class name alone here ? " QFileInfo " without an object to control it ? and how did we get an QFileInfo object from
QFileInfo(dir.filePath())
it's been too long since I used c++ but I don't remember using such things ?
To access static class data you can use :: operator, like
QFileInfo::someStaticData
Moreover, by typing
if(QFileInfo(dir.filePath()).isFile())
you are creating temporary QFileInfo object, which is deleted right after the if statement.
What you would probably want is to save the object to some local variable, like:
QFileInfo fileInfo(dir.filePath());
and use that variable in if statements:
if(fileInfo.isFile()) {
if(fileInfo.suffix() == extention)
....
}

Add a pre-declared path to a filename argument (LPCSTR)

I have a list of files I need to open in a certain function via a LPCSTR argument, but unfortunately they're located in certain folders (subdirectories of the main program root) with a very long path, and I don't want to type it in every time I want to pass the filenames.
To be more precise, I have the function D3DXCreateTextureFromFile() which asks for the filename, and for example, I have the files a.png, b.png, c.png located in the "...\Materials\Textures\Textures_For_This\Textures_For_That\More_Specific_Texture_Location\" subdirectory of the main program. How can I register this path and add it to the filename argument in a lean and mean way?
Like some sort of this:
D3DXCreateTextureFromFile(bla, **DECLARED_DIR** + a.png, bla)
//same for b.png, c.png
Or even a subfunction that unifies the path and the filename:
D3DXCreateTextureFromFile(bla, UnifyText(DECLARED_DIR, a.png), bla)
Yep, easiest to make a function to combine the directory with the filename and include separator if required. Because you want to pass this as an argument, you want to avoid allocating a string and having to clean it up... So use the C++ string class.
I generally do something like this:
string TexturePath( LPCSTR filename = NULL )
{
if( filename == NULL ) return string(TEXTURE_DIR);
return string(TEXTURE_DIR) + "\" + filename;
}
Of course, you'll be relying on that string being implicitly cast to LPCSTR later. If you want to be more explicit then do the (slightly ugly) call to string::c_str():
D3DXCreateTextureFromFile(bla, TexturePath("a.png").c_str(), bla)
[Edit]
Another way, if you are doing this single-threaded, is to use a static buffer:
LPCSTR TexturePath( LPCSTR filename = NULL )
{
static char pathBuf[MAX_PATH];
if( filename == NULL ) return TEXTURE_DIR;
sprintf( pathBuf, "%s\\%s", TEXTURE_DIR, filename );
return pathBuf;
}
String main_dir="C:\\\Materials\\Textures\\Textures_For_This\\Textures_For_That\\More_Specific_Texture_Location\\";
String files[]={"a.png","b.png","c.png"};
String fullpath=main_dir;
fullpath+=files[0];
D3DXCreateTextureFromFile(bla, fullpath.c_str(), bla);
If you're using C++ why not use a stringstream to concatenate the 2 strings together and then call .c_str() on the resulting string. Or you can use the c-style, strcat into a large enough buffer.