我正在尝试在包含非拉丁字符的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;
}
答案 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之前main.cpp中的这段代码应该有所帮助:
#include <QTextCodec>
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf8"));
QTextCodec::setCodecForTr(QTextCodec::codecForName("utf8"));