dirent.h - kodowanie polskich znaków

0

Witam, potrzebowałem zaimplementować w swoim programie jakieś proste pakowanie wszystkich plików i folderów w danym folderze do 1 pliku i potem wypakowywanie tego tak aby otrzymać taką samą strukturę - mam tylko problem z polskimi znakami w nazwach plików i folderów, jeśli moglibyście mnie naprowadzić na błąd to byłbym bardzo wdzięczny.

Załączam kod:

 #include <list>
#include <string>
#include <dirent.h>
#include <cstdio>
#include <windows.h>

typedef struct {
	std::string path;
	unsigned lenght_of_path;
	char type;
	unsigned size;
	char *data;
} single_element;



int pack(std::string root_directory, std::list<single_element> *all_elements)
{
	single_element temp;
	temp.data = NULL;
	FILE *processed;

	DIR *directory;
	struct dirent *ent;
	if ((directory = opendir(root_directory.c_str())) != NULL)
	{
		while ((ent = readdir(directory)) != NULL)
		{
			std::string actual_path = root_directory;
			std::string packed_file = ent->d_name;
			if (packed_file != "." && packed_file != "..") 
			{
				if (ent->d_type == 16384)
				{
					actual_path += "\\";
					actual_path += packed_file;
					temp.data = NULL;
					temp.type = 'D';
					temp.path = actual_path;
					temp.lenght_of_path = actual_path.length();
					temp.size = 0;
					all_elements->push_back(temp);
					pack(actual_path,all_elements); 
				}
				else 
				{
					actual_path += "\\";
					actual_path += packed_file;
					processed = fopen(actual_path.c_str(),"rb");
					if (processed != NULL)
					{
						temp.path = actual_path;
						temp.lenght_of_path = actual_path.length();
						temp.type = 'F'; //F is for FILE;
						fseek (processed,0,SEEK_END);
						temp.size = ftell(processed);
						all_elements->push_back(temp);
						all_elements->back().data = new char[all_elements->back().size];
						rewind(processed);
						fread(all_elements->back().data,all_elements->back().size,1,processed);
						fclose(processed);
					}
				}
			}
		}
	}
	closedir (directory);
	return 0;
}

int save(std::string file_name, std::list<single_element> all_elements)
{
	file_name += ".pak";
	FILE *packed = fopen(file_name.c_str(),"wb");
	int ammount  = all_elements.size();
	fwrite((const void*)&ammount,sizeof(int),1,packed);
	for (std::list<single_element>::iterator i = all_elements.begin(); i != all_elements.end(); i++) 
	{
		fwrite((const void*)&i->lenght_of_path,sizeof(unsigned),1,packed);
		fwrite(i->path.c_str(),i->lenght_of_path,1,packed);
		fwrite((const void*)&i->type,sizeof(char),1,packed);
		if (i->type == 'F') //if its file write also data and it's size
		{
			fwrite((const void*)&i->size,sizeof(unsigned),1,packed);
			fwrite(i->data,i->size,1,packed);
		}

	}
	fclose(packed);
	return 0;
}

int load(std::string file, std::list<single_element> *all_elements)
{
	char *buf = NULL;
	file += ".pak";
	FILE *packed = fopen(file.c_str(),"rb");
	single_element temp;
	int ammount;
	fread((void*)&ammount,sizeof(int),1,packed);
	for (int i = 0; i < ammount; i++)
	{
		fread((void*)&temp.lenght_of_path,sizeof(unsigned),1,packed);
		buf = new char[temp.lenght_of_path+1];
		fread(buf,temp.lenght_of_path,1,packed);
		buf[temp.lenght_of_path] = '\0';
		temp.path = buf;
		delete buf;
		buf = NULL;
		fread((void*)&temp.type,sizeof(char),1,packed);
		all_elements->push_back(temp);
		if (temp.type == 'F')
		{
			fread((void*)&all_elements->back().size,sizeof(unsigned),1,packed);
			all_elements->back().data = new char[all_elements->back().size];
			fread(all_elements->back().data,all_elements->back().size,1,packed);
		}
		else
		{
			all_elements->back().size = 0;
			all_elements->back().data = NULL;
		}
	}
	fclose(packed);
	return 0;
}

int extract(std::string root_directory, std::list<single_element> all_elements)
{
	CreateDirectory(root_directory.c_str(),NULL);
	std::list<single_element>::iterator i = all_elements.begin();
	while (i != all_elements.end())
	{
		if (i->type == 'D')
		{
			CreateDirectory(i->path.c_str(),NULL);
			i = all_elements.erase(i);
		}
		else ++i;
	}
	i = all_elements.begin();
	while (i != all_elements.end()) 
	{
		FILE *extracted;
		extracted = fopen(i->path.c_str(),"wb");
		fwrite(i->data,i->size,1,extracted);
		fclose(extracted);
		++i;
	}
	return 0;

}
	
int main()
{
	std::list<single_element> all;
	std::string root = "Test";
	pack(root,&all);
	save(root,all);
	load(root,&all);
	extract(root,all);
	return 0;
}

Żeby przetestować zróbcie w folderze swojego projektu jakiś folder a w nim plik z polskimi znakami w nazwie, również nazwy folderów nie działają.

0

Czego się spodziewasz używając typu string?

0

Czy powinienem ożyć wstring oraz odpowiednich funkcji dla Wide Characters z nagłówka dirent?

0
#include <windows.h>

Zawsze przed <windows.h> dodawaj dwa #define - w parametrach kompilatora albo w samym kodzie:

#define UNICODE
#define _UNICODE
#include <windows.h>

#include <list>
#include <string>
#include <cstdio>
#include <filesystem>

// #include <dirent.h>

To wymusi używanie unikodowych stringów w funkcjach WinAPI.

Nie używaj <dirent.h>. To jakiś uniksowy wynalazek niestandardowy pod Windows. Używaj funkcji WinAPI albo standardowego nagłówka <filesystem>.

1 użytkowników online, w tym zalogowanych: 0, gości: 1