List all files recursively function in MFC error? - c++

I want to list all my files and folders (include sub-folders) and show it into my list box so I think about writing a recursive function to display them. But the code work well if I show all files and folders in the selecting folder, but it can not scan in sub-folders (it show only the first folder and no more). Please help me to know what is the error?
This is my function (I add it into my Dialog class)
void CFileListingDlg::ListFile(CString path)
{
CFileFind hFile;
BOOL bFound;
CString filePath;
bFound=hFile.FindFile(path+L"\\*.*");
while(bFound)
{
bFound=hFile.FindNextFile();
if(!hFile.IsDots())
{
m_lFiles.AddString(hFile.GetFilePath());
//It work well with selecting folder if I remove this line
//But it shows only first folder when I use it
if(hFile.IsDirectory()) ListFile(hFile.GetFilePath()+L"\\*.*");
}
}
}
And then, I call it when click Browser button with the code
void CFileListingDlg::OnBnClickedBtnBrowse()
{
// TODO: Add your control notification handler code here
// TODO: Add your control notification handler code here
CFolderPickerDialog folderDialog(_T("E:\\Test"));
if(folderDialog.DoModal()==IDOK)
{
m_eFolder.SetWindowText(folderDialog.GetPathName());
m_lFiles.ResetContent();
ListFile(folderDialog.GetPathName());
}
}

Here is the proper way to implement recursive files listing:
void ListFiles(const CString& sPath, CStringArray& files)
{
CFileFind finder;
// build a string with wildcards
CString sWildcard(sPath);
sWildcard += _T("\\*.*");
BOOL bWorking = finder.FindFile(sWildcard);
while (bWorking)
{
bWorking = finder.FindNextFile();
// skip . and .. files; otherwise, we'd
// recur infinitely!
if (finder.IsDots())
continue;
// if it's a directory, recursively traverse it
if (finder.IsDirectory())
{
CString sFile = finder.GetFilePath();
files.Add(sFile);
ListFiles(sFile, files);
}
}
finder.Close();
}

Related

Zip directory recursion

I am working on creating zip archive using old Qt - ZipWriter class. The problem is when I want to add the directory. The default Qt code for addDirectory method - d->addEntry(ZipWriterPrivate::Directory, archDirName, QByteArray());. It does not add any content, only the empty directory. So, I have improved it to add the directories and content as well.
My code:
QList<QString> dirs;
int recursion = 0;
void ZipWriter::addDirectory(const QString &dirPath)
{
QDir archDir(dirPath);
archDir.setFilter(QDir::AllEntries | QDir::NoDotAndDotDot);
dirs << addDirSeparator(archDir.dirName());
if (archDir.exists()) {
QString archDirName = "";
if (recursion > 0) {
for (int i = recursion; i < dirs.count(); i++) {
archDirName = dirs.first().append(dirs.at(i));
}
} else {
archDirName = dirs.at(recursion);
}
if (!archDir.isEmpty()) {
const QStringList archFileList = archDir.entryList();
if (archFileList.count() > 0) {
for (QString archFile : archFileList) {
QFileInfo archFileInfo(QDir::toNativeSeparators(QString("%1/%2").arg(archDir.absolutePath(), archFile)));
if (archFileInfo.isDir()) {
recursion++;
addDirectory(archFileInfo.absoluteFilePath());
} else {
QFile zipFile(archFileInfo.absoluteFilePath());
zipFile.open(QIODevice::ReadOnly);
addFile(QString("%1%2").arg(archDirName, archFile), zipFile.readAll());
zipFile.close();
}
}
}
} else {
d->addEntry(ZipWriterPrivate::Directory, archDirName, QByteArray());
}
}
}
Now, it adds the directory and content recursively but it has issue when directory is on the same level, it appends it to the end. I think, I must use the STL container to keep track of the directory for example QMap but the question is how to get the current directory level? Any ideas? Thank you.
Updated: 01.05.2022
I have change my code to this:
void ZipWriter::addDirectory(const QString &dirPath)
{
QDirIterator dirIt(dirPath, QDir::AllEntries | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
while (dirIt.hasNext()) {
QString archDirPath = dirIt.next();
QFile zipFile(archDirPath);
zipFile.open(QIODevice::ReadOnly);
if (!dirIt.fileInfo().isDir()) {
addFile(archDirPath, zipFile.readAll());
}
zipFile.close();
}
}
It adds everything recursively and in correct order but I have another issue. Now, it adds the full path to the archive. For example, I want to add this folder and it's content to the archive: 22610.1_amd64_en-us_professional_00fb7ba0_convert.
In the archive I get: C:\Users\userProfile\Downloads\22610.1_amd64_en-us_professional_00fb7ba0_convert. Any ideas how to make this relative path or trim it? Thank you.
You can use QDirIterator to recursively iterate over directory and subdirectories, and I believe you dont need to add nonempty directories at all, just files will be fine.
And why would you use stl container in qt, please use qt containers.

MFC serialize C++

I'm trying to serialize a listbox in MFC.
I used this code :
CFileDialog fileDlg(FALSE, _T(".txt"), NULL, 0, _T("Text File (.txt)|*.txt|")
_T("All files (*.*)|*.*||"));
if (fileDlg.DoModal() == IDOK)
{
const int numItems = m_listBox.GetCount();
CString itemText;
CStdioFile file;
if (file.Open(fileDlg.GetFileName(), CStdioFile::modeCreate | CStdioFile::modeWrite))
{
for (int i = 0; i < numItems; ++i)
{
m_listBox.GetText(i, itemText);
file.WriteString(itemText);
file.WriteString(_T("\n"));
}
file.Close();
}
But the saved file is always empty.
I tried a lot of versions of functions that save from listbox to text file but it didn't work.
In your code you are using CFileDialog::GetFileName. Is that intentional? That will only pass in the file name.
I would use CFileDialog::GetPathName which returns the full path to the file.
And you should be using a debugger (compile in debug mode) so you can walk your code.
The CStdioFile::Open method can also be passed a pointer to an exception object. Have a look at the help.

Open function in Qt

I have been creating an application in qt. I have added open function in it, but was happening that when I open an already open file, it again opens the same file instead of pointing it to already opened file.
void MainWindow::actionOpen()
{
QFileInfo fileInfo = UIUtils::openFile(this);
if (!fileInfo.exists()) {
return;
}
if (!MainWindow::mdiMode && !maybeSave()) {
return;
}
openFile(fileInfo.filePath());
}
Please help me to solve the problem.
I'm not 100 % clear on what the issue is, but if you don't want to run the openFile function on files you've previously opened, you have to keep a record.
For instance, define a QList in your header file:
QList<QFileInfo> knownFiles;
And then keep it up to date and check it:
void MainWindow::actionOpen()
{
QFileInfo fileInfo = UIUtils::openFile(this);
if (!fileInfo.exists()) {
return;
}
if (!MainWindow::mdiMode && !maybeSave()) {
return;
}
bool fileIsKnown = false;
for(qint64 i=0; i<knownFiles.length(); i++)
if(knownFiles.at(i) == fileInfo)
{
fileIsKnown = true;
break;
}
if(!fileIsKnown)
{
knownFiles << fileInfo;
openFile(fileInfo.filePath());
}
}
I don't know what you mean when you say "instead of pointing it to already opened file.".

c++ mfc csv file read

i have a problem with csv file reading. I'm pretty new to mfc and i hope someone can help me. So...i have a button and with it i open file dialog and choose csv file. In csv file i have diferent shapes(rectangle,ellipse,pollygon) with color and position info(separtor is ;). Now i need to show this informations in a ListBox and here i'm stuck. I got so far(code)...and i don't know it's ok and i can't find any good help so i hope someone can give me a hint.
void CDialogDrawing::OnBnClickedButton2()
{
TCHAR filtri[] = _T("CSV files (*.csv)|*.csv||");
CString path;
CFileDialog dlg(TRUE, _T("csv"), _T("*.csv"), OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, filtri);
dlg.m_ofn.lpstrTitle = _T("Open...");
if(dlg.DoModal() == IDOK) //OK
{
path = dlg.GetPathName();
//
CStdioFile readFile;
CFileException fileException;
CString strLine;
if(readFile.Open(path, CFile::modeRead, &fileException))
{
while (readFile.ReadString(strLine));
{
seznamLikov.AddString(strLine);
}
}
else
{
CString strErrorMsg;
strErrorMsg.Format(_T("Can't open file %s , error : %u"), path, fileException.m_cause);
AfxMessageBox(strErrorMsg);
}
readFile.Close();
}
}
Trailing semi-colon after the while:
while (readFile.ReadString(strLine));
{
seznamLikov.AddString(strLine);
}
remove it as it is equivalent to:
while (readFile.ReadString(strLine)) {}
{
seznamLikov.AddString(strLine);
}
meaning AddString() will be invoked only once, after ReadString() fails.

How to display the selected file name in the ListControl in MFC in Visual Studio?

I have created a grid function using list control. There are two columns in the list. Data and NAME.
The user should select a file; and the data inside the file should be diplayed in first column "DATA" and file name should be displayed in the 2nd column "NAME".
I have written a code but nothing is appearing in the list
CFileFind finder;
bool bFound;
CString filename = "C:\\ Location\\*.txt";
bFound = finder.FindFile(filename);
if(bFound)
{
while(bFound)
{
bFound = finder.FindNextFile();
if(bFound)
{
m_List.AddString(finder.GetFileName()); //This is where the actual data is added
}
}
CStdioFile files;
CFileException exp;
CString strLine;
if (files.Open(filename, CFile::modeRead, &exp))
{
while(files.ReadString(strLine)){}
}
}
void CuserspecificationDlg::InsertItems()
{
HWND hWnd = ::GetDlgItem(m_hWnd, IDC_LIST1);
// Set the LVCOLUMN structure with the required
// column information
..
..
SetCell(hWnd,out,1,1); // where out is the Cstring variable for edit control
}
What can be the mistake?
Please see a tutorial on how to use List box here. You could define a member variable of type CListBox that is mapped to your list box via the control wizard.