Как я могу обрабатывать имена файлов с арабским текстом в Windows? - PullRequest
0 голосов
/ 11 февраля 2012

Я получил этот исходный код откуда-то в сети. Он ищет файлы на жестком диске и распечатывает путь к файлам:

#include <string>
#include <vector>
#include <iostream>

#include <windows.h>
#include <conio.h>



int SearchDirectory(std::vector<std::string> &refvecFiles,
                    const std::string        &refcstrRootDirectory,
                    const std::string        &refcstrExtension,
                    bool                     bSearchSubdirectories = true)
{
  std::string     strFilePath;             // Filepath
  std::string     strPattern;              // Pattern
  std::string     strExtension;            // Extension
  HANDLE          hFile;                   // Handle to file
  WIN32_FIND_DATA FileInformation;         // File information


  strPattern = refcstrRootDirectory + "\\*.*";

  hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation);
  if(hFile != INVALID_HANDLE_VALUE)
  {
    do
    {
      if(FileInformation.cFileName[0] != '.')
      {
        strFilePath.erase();
        strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;

        if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
          if(bSearchSubdirectories)
          {
            // Search subdirectory
            int iRC = SearchDirectory(refvecFiles,
                                      strFilePath,
                                      refcstrExtension,
                                      bSearchSubdirectories);
            if(iRC)
              return iRC;
          }
        }
        else
        {
          // Check extension
          strExtension = FileInformation.cFileName;
          strExtension = strExtension.substr(strExtension.rfind(".") + 1);

          if(strExtension == refcstrExtension)
          {
            // Save filename
            refvecFiles.push_back(strFilePath);
          }
        }
      }
    } while(::FindNextFile(hFile, &FileInformation) == TRUE);

    // Close handle
    ::FindClose(hFile);

    DWORD dwError = ::GetLastError();
    if(dwError != ERROR_NO_MORE_FILES)
      return dwError;
  }

  return 0;
}


int main()
{
  int                      iRC         = 0;
  std::vector<std::string> vecAviFiles;
  std::vector<std::string> vecTxtFiles;


  // Search 'c:' for '.avi' files including subdirectories
  iRC = SearchDirectory(vecAviFiles, "d:", "doc");
  if(iRC)
  {
    std::cout << "Error " << iRC << std::endl;
    return -1;
  }

  // Print results
  for(std::vector<std::string>::iterator iterAvi = vecAviFiles.begin();
      iterAvi != vecAviFiles.end();
      ++iterAvi)
    std::cout << *iterAvi << std::endl;

  // Search 'c:\textfiles' for '.txt' files excluding subdirectories
  /*
  iRC = SearchDirectory(vecTxtFiles, "c:\\textfiles", "txt", false);
  if(iRC)
  {
    std::cout << "Error " << iRC << std::endl;
    return -1;
  }

  // Print results
  for(std::vector<std::string>::iterator iterTxt = vecTxtFiles.begin();
      iterTxt != vecTxtFiles.end();
      ++iterTxt)
    std::cout << *iterTxt << std::endl;

  // Wait for keystroke
  _getch();
  */

  return 0;
}

Проблема в том, что, когда он находит имя файла с арабским текстом, он не отображается правильно; Это просто показывает "?????????????????????". Мне нужен путь к файлу для отправки на сервер. Есть ли способ решить проблему?

UPDATE: Я изменил код.

Новый код выглядит следующим образом:

#include <boost/filesystem.hpp>
namespace bf = boost::filesystem;
#include <string>
#include <iostream>
using namespace std;
string e_string = "Error";
int main()
{
    string fileName = "C:\\حم.txt";
    string destination = "D:\\log.txt" ;
    bf::path fileCopied(fileName);
    bf::path fileCopiedDestination (destination);
    if (!bf::exists(fileCopied) )
    {
        cerr << e_string;
    }
     if (!bf::exists(fileCopiedDestination))
        {
        cerr << e_string;
    }
    try
    {
        bf::copy_file(fileCopied,fileCopiedDestination);
    }
    catch(std::exception e)
    {
        cout << e.what();
    }
}

Этот код компилируется, но я получаю эту ошибку:

ErrorErrorstd::exception

Кроме того, процесс копирования завершается неудачей.

Я пытался изменить эту строку:
string fileName = "C:\\حم.txt";

до:
string fileName = "C:\\??.txt";

но напрасно.

Как мне скопировать этот файл?

Ответы [ 2 ]

2 голосов
/ 11 февраля 2012

Если ваша ОС - Windows, использование 8-битных символов для имен файлов - плохая идея;он будет ограничивать вас так называемой «кодовой страницей ANSI» (что-то не так).Определите UNICODE и _UNICODE и используйте API-интерфейсы Windows, которые принимают PWSTR.Это позволит вам иметь имена файлов в юникоде.

Если вам нужно написать переносимый код, вам может потребоваться разбить ваш код на переносимые и непереносимые части.При вызове реальных файловых API вы должны преобразовать из более разумной кодировки (UTF-8?) В имя файла для конкретной платформы (PWSTR в случае Windows; вы можете сделать это с MultiByteToWideChar и CP_UTF8 встраница с исходным кодом).

0 голосов
/ 11 февраля 2012

Вы "только начинающий", поэтому я настоятельно рекомендую это: загрузите Boost и используйте Boost.Filesystem .У него есть класс boost::filesystem::path, который представляет имя файла.Это все, что вы должны использовать для работы с именами файлов.Используйте функции Boost.Filesystem для поиска файлов и используйте объект boost::filesystem::path и специальный iostreams в Boost.Filesystem для открытия этих файлов.

Печать строк в кодировке Unicode в окне консоли is... не легко сделать в Windows.

...