DatExporter.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #include <DatFile.h>
  2. #include <DatSubsystems/DatExporter.h>
  3. #include <DatSubsystems/DatFileSystem.h>
  4. #include <BinaryData.h>
  5. #include <SubfileData.h>
  6. #include <SubFile.h>
  7. #include <string>
  8. #include <fstream>
  9. #include <algorithm>
  10. namespace LOTRO_DAT {
  11. DatExporter::DatExporter(DatFile *datFilePtr) : dat(datFilePtr) {
  12. }
  13. /*!
  14. * \author Gi1dor
  15. * \date 05.07.2018
  16. * Извлечение в папку всех файлов, имеющих заданный тип
  17. * \param[in] type Тип файлов
  18. * \param[in] output_directory_path путь к папке, куда будут записаны файлы. Имя экспортируемого файла - file_id.ext, где file_id - id файла, ext - его расширение
  19. *
  20. * \returns DatOperationResult.value - количество извлечённых файлов
  21. */
  22. DatOperationResult<int> DatExporter::ExtractAllFilesByType(const FILE_TYPE &type, std::string output_directory_path) {
  23. int success_exported = 0;
  24. int iterated_files = 0;
  25. dat->GetStatusModule().SetStatus(DatStatus::E_EXTRACTING);
  26. dat->GetStatusModule().SetFinishedParts(0);
  27. dat->GetStatusModule().SetTotalParts(dat->GetFileSystem().GetInitialisedFilesNumber());
  28. dat->GetStatusModule().SetDebugMessage("Starting extracting files of type " + std::to_string(type) + ", this may take long time, please be patient!");
  29. LOG(INFO) << "Extracting files by type " + std::to_string(type) + "to database...";
  30. auto operation = dat->GetFileSystem().PerformOperationOnAllFiles([&iterated_files, &success_exported, this, type, &output_directory_path](std::shared_ptr<SubFile>& file) -> void {
  31. iterated_files++;
  32. dat->GetStatusModule().SetFinishedParts(iterated_files);
  33. dat->GetStatusModule().SetTotalParts(dat->GetFileSystem().GetInitialisedFilesNumber());
  34. if ((file->FileType() & type) == NO_TYPE)
  35. return;
  36. SubfileData export_file = file->PrepareForExport(dat->GetFileSystem().GetFileData(*file, 8).value);
  37. dat->GetStatusModule().SetDebugMessage("Extracting file " + std::to_string(file->file_id()) + " (Files by type -> directory)");
  38. if (export_file.Empty())
  39. return;
  40. bool result;
  41. if (type == TEXT)
  42. result = WriteStringToFile(export_file.text_data, output_directory_path + std::to_string(file->file_id()) + file->Extension()).result;
  43. else
  44. result = export_file.binary_data.WriteToFile(output_directory_path + std::to_string(file->file_id()) + file->Extension());
  45. if (result)
  46. success_exported++;
  47. });
  48. LOG(INFO) << "Extracting files: successfully exported " << success_exported << " files";
  49. dat->GetStatusModule().SetDefaultStatus();
  50. return DatOperationResult<int>(success_exported, SUCCESS);
  51. }
  52. /*!
  53. * \author Gi1dor
  54. * \date 05.07.2018
  55. * Извлечение файла по его id
  56. * \param[in] file_id id файла
  57. * \param[in] output_filename - имя файла, куда будет записаны данные.
  58. */
  59. DatOperationResult<> DatExporter::ExtractFileById(long long file_id, std::string output_filename) {
  60. dat->GetStatusModule().SetStatus(DatStatus::E_EXTRACTING);
  61. dat->GetStatusModule().SetFinishedParts(0);
  62. dat->GetStatusModule().SetTotalParts(1);
  63. dat->GetStatusModule().SetDebugMessage("Extracting file " + std::to_string(file_id) + " to file " + output_filename);
  64. auto operation_GetFile = dat->GetFileSystem().GetFile(file_id);
  65. if (operation_GetFile.result == ERROR) {
  66. dat->GetStatusModule().SetDefaultStatus();
  67. return DatOperationResult<>(ERROR, "EXTRACTFILEBYID: File not found! id = " + std::to_string(file_id));
  68. }
  69. std::shared_ptr<SubFile> file = operation_GetFile.value;
  70. auto operation_GetFileData = dat->GetFileSystem().GetFileData(*file, 8);
  71. if (operation_GetFileData.result == ERROR) {
  72. dat->GetStatusModule().SetDefaultStatus();
  73. return DatOperationResult<>(ERROR, "EXTRACTFILEBYID: Can't get data for id = " + std::to_string(file_id));
  74. }
  75. SubfileData export_data = file->PrepareForExport(operation_GetFileData.value);
  76. bool result;
  77. if (file->FileType() == TEXT)
  78. result = WriteStringToFile(export_data.text_data, output_filename + file->Extension()).result;
  79. else
  80. result = export_data.binary_data.WriteToFile(output_filename + file->Extension());
  81. dat->GetStatusModule().SetDefaultStatus();
  82. if (!result)
  83. return DatOperationResult<>(ERROR, "EXTRACTFILEBYID: Cannot write to file" + output_filename + file->Extension());
  84. return DatOperationResult<>(SUCCESS);
  85. }
  86. /*!
  87. * \author Gi1dor
  88. * \date 05.07.2018
  89. * Извлечение в базу данных всех файлов, имеющих заданный тип
  90. * \param[in] type Тип файлов
  91. * \param[in] db Указатель на объект базы данных
  92. *
  93. * \returns DatOperationResult.value - количество извлечённых файлов
  94. */
  95. DatOperationResult<int> DatExporter::ExtractAllFilesByType(const FILE_TYPE &type, Database *db) {
  96. if (!db)
  97. return DatOperationResult<int>(0, ERROR, "EXTRACTALLBYTYPETODB: database is nullptr");
  98. dat->GetStatusModule().SetStatus(DatStatus::E_EXTRACTING);
  99. dat->GetStatusModule().SetFinishedParts(0);
  100. dat->GetStatusModule().SetTotalParts(dat->GetFileSystem().GetInitialisedFilesNumber());
  101. dat->GetStatusModule().SetDebugMessage("Initialising extraction of files by type " + std::to_string(type) + "to database... This may take long time, please be patient!\"");
  102. LOG(INFO) << "Extracting files by type " + std::to_string(type) + "to database...";
  103. int success_exported = 0;
  104. int iterated_files = 0;
  105. auto operation = dat->GetFileSystem().PerformOperationOnAllFiles([&success_exported, &iterated_files, this, type, db](std::shared_ptr<SubFile>& file) {
  106. iterated_files++;
  107. dat->GetStatusModule().SetFinishedParts(iterated_files);
  108. if ((file->FileType() & type) == NO_TYPE)
  109. return;
  110. dat->GetStatusModule().SetDebugMessage("Extracting file " + std::to_string(file->file_id()) + " (Files by type -> database)");
  111. SubfileData export_file = file->PrepareForExport(dat->GetFileSystem().GetFileData(*file, 8).value);
  112. bool result = db->PushFile(export_file);
  113. if (result)
  114. success_exported++;
  115. });
  116. LOG(INFO) << "Extracting files: successfully exported " << success_exported << " files";
  117. dat->GetStatusModule().SetDefaultStatus();
  118. return DatOperationResult<int>(success_exported, SUCCESS);
  119. }
  120. /*!
  121. * \author Ivan Arkhipov
  122. * \date 21.10.2018
  123. * Извлечение в базу данных файла с заданным id
  124. * \param[in] file_id ID файла
  125. * \param[in] db Указатель на объект базы данных
  126. */
  127. DatOperationResult<> DatExporter::ExtractFileById(long long file_id, Database *db) {
  128. if (!db)
  129. return DatOperationResult<>(ERROR, "EXTRACTFILEBYIDTODB: database is nullptr");
  130. dat->GetStatusModule().SetStatus(DatStatus::E_EXTRACTING);
  131. dat->GetStatusModule().SetFinishedParts(0);
  132. dat->GetStatusModule().SetTotalParts(1);
  133. LOG(INFO) << "Extracting file with id = " << file_id << "to database...";
  134. auto operation_GetFile = dat->GetFileSystem().GetFile(file_id);
  135. if (operation_GetFile.result == ERROR) {
  136. dat->GetStatusModule().SetDefaultStatus();
  137. return DatOperationResult<>(ERROR, "EXTRACTFILEBYIDTODB: File not found! id = " + std::to_string(file_id));
  138. }
  139. std::shared_ptr<SubFile> file = operation_GetFile.value;
  140. auto operation_GetFileData = dat->GetFileSystem().GetFileData(*file, 8);
  141. if (operation_GetFileData.result == ERROR) {
  142. dat->GetStatusModule().SetDefaultStatus();
  143. return DatOperationResult<>(ERROR, "EXTRACTFILEBYIDTODB: Can't get data for id = " + std::to_string(file_id));
  144. }
  145. SubfileData export_data = file->PrepareForExport(operation_GetFileData.value);
  146. bool result = db->PushFile(export_data);
  147. dat->GetStatusModule().SetDefaultStatus();
  148. if (!result)
  149. return DatOperationResult<>(ERROR, "EXTRACTFILEBYIDTODB: Cannot export file" + std::to_string(file_id));
  150. LOG(INFO) << "Successfully exported file " << file_id << " to database";
  151. return DatOperationResult<>(SUCCESS);
  152. }
  153. /*!
  154. * \author Gi1dor
  155. * \date 05.07.2018
  156. * Запись строки в формате UTF-16 в файл
  157. * \param[in] str Строка для записи в файл
  158. * \param[in] path Путь к файлу, в который строка будет записана
  159. *
  160. * \warning Путь к файлу должен быть корректным (папки должны существовать). Если и сам файл существует, то он будет перезаписан
  161. */
  162. DatOperationResult<> DatExporter::WriteStringToFile(const std::u16string &str, const std::string &path) {
  163. std::basic_ofstream<char16_t> output_stream(path, std::ios::out);
  164. if (!output_stream.is_open())
  165. return DatOperationResult<>(ERROR, "WRITESTRINGTOFILE: cant open file " + path);
  166. output_stream << str;
  167. output_stream.close();
  168. return DatOperationResult<>();
  169. }
  170. };