俄语(或非拉丁语)文件名加载Qt Windows

时间:2014-05-27 11:30:13

标签: c++ windows macos qt utf-8

我正在尝试在包含非拉丁字符的Qt / C ++软件上加载文件。 用户使用俄语文件名报告的问题,我尝试使用下面的代码快速修复它。

示例文件名是(我不读或写俄语!):Летнийсад.dgr

bool QDepthmapView::loadFile(const QString &fileName)
{
    m_open_file_name = fileName;
    m_redraw_all = 1;
    // this fixes the problem on a MacOSX but NOT on Windows!
    QByteArray ba = fileName.toUtf8(); 
    char *file = ba.data();
    // end of fix
    if(pDoc->OnOpenDocument(file)) // quick fix for weird chars (russian filename bug report)
    {
        // removed 
    }
    return false;
}

上面的解决方案是我在网上找到的一个很脏的东西,它适用于我的MacOSX10.8,但似乎Windows处理非ASCII字符有点不同而且我不熟悉它。

我正在寻找一个多平台解决方案(该软件在Win,Mac和Linux上运行),用于加载非ASCII文件名。

关于以下评论的编辑: OnOpenDocument转到:

int QGraphDoc::OnOpenDocument(char* lpszPathName) 
{

   m_opened_name = QString(lpszPathName);

   int ok = m_meta_graph->read( lpszPathName );
// removed //

}

####
int read( const pstring& filename )
{
// cleared

#ifdef _WIN32
   ifstream stream( filename.c_str(), ios::binary | ios::in );
#else
   ifstream stream( filename.c_str(), ios::in );
#endif

//cleared

   stream.read( (char *) &version, sizeof( version ) );

// cleared
   }
####

template <class T>
istream& pmemvec<T>::read( istream& stream, streampos offset )
{
   if (offset != streampos(-1)) {
      stream.seekg( offset );
   }
   // READ / WRITE USES 32-bit LENGTHS (number of elements)
   // n.b., do not change this to size_t as it will cause 32-bit to 64-bit conversion problems
   unsigned int length;
   stream.read( (char *) &length, sizeof(unsigned int) );
   m_length = size_t(length);
   if (m_length >= storage_size()) {
      if (m_data) {
         delete [] m_data;
         m_data = NULL;
      }
      while (m_length >= storage_size())
         m_shift++;
      m_data = new T [storage_size()];
      if (!m_data)
         throw pexception( pexception::MEMORY_ALLOCATION, sizeof(T) * storage_size() );
   }
   if (m_length != 0) {
      stream.read( (char *) m_data, sizeof(T) * streamsize(m_length) );
   }
   return stream;
}

2 个答案:

答案 0 :(得分:4)

欢迎来到Windows本地编码的精彩世界。

Windows内部以UTF-16工作(正如QString那样),但它的&#34;遗产&#34; narrow-char API使用&#34;本地代码页&#34;,它通常与系统代码页相同(尽管它可以基于每个线程进行自定义 - 但不是,它不能设置为UTF-8) 。

这意味着大多数使用char直接传递给Windows API的函数(通常在C / C ++文件工具中发生)都需要使用当前代码页编码的字符串。

QString支持toLocal8Bit方法,以便在当前系统编码中提供其内容的窄字符表示形式,该代码应该是Windows上的本地CP和任何合理配置的UNIX上的UTF-8

问题是,QString到UTF-8是无损转换,因为它们都可以代表所有Unicode代码点; QString到本地代码页而不是那么多 - 例如,俄语字符无法在通常的Windows-1252 CP中编码。

出于这个原因,使用toLocal8Bit,您可以为流提供所需编码的文件名,但您无法打开包含当前代码页中未包含的字符的文件。

长话短说:通常避免任何问题的方法是始终将路径保留为QString并使用QFile打开文件。 QFile通过调用&#34; widechar&#34;来内部处理这种精神错乱。具有UTF-16字符串的Windows API版本,并在UNIX系统上适当地转换为UTF-8。

如果您真的需要使用其他文件处理功能,您有两种选择:使用toLocal8Bit并放弃使用&#34;非本地&#34;处理文件。 Windows上的名称,或为Windows提供与wchar_t一起使用的单独代码路径(直到宽版本的C库和Windows API函数)。

答案 1 :(得分:1)

这取决于你的Qt版本,如果它是Qt4.x.x,那么在QApplication之前m​​ain.cpp中的这段代码应该有所帮助:

#include <QTextCodec>
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf8"));
QTextCodec::setCodecForTr(QTextCodec::codecForName("utf8"));