2012-11-13 117 views
1

我試圖打開一個文件以便稍後處理它。我的問題是,如果我的文件名不是ANSI(阿拉伯文,印地文...)fopen_sfopen拒絕打開它並給我一個Invalid argument錯誤。我不能用CreateFile()要做到這一點,所以我想檢查我的任何文件名是由fopen或不(嘗試打開它),並創建一個臨時文件,而不是支持:檢查fopen不支持的文件名

QString fileN=QString::fromWCharArray(fname); 
QFileInfo file(DIRPath+"/"+fileN); 
bool Supported=true; 
if(file.exists()) { 
    QString temp; 
    char* Fname=(char*)malloc(260*sizeof(char)); 
    strcpy(Fname,(QString(DIRPath+"/"+fileN).toStdString()).c_str()); 
    FILE* Filedesc; 
    errno_t err=fopen_s(&Filedesc,Fname,"rb"); 
    if(Filedesc!=NULL) { 
     qDebug()<<"\nfile opened "; 
     fclose(Filedesc); 
    } else if(err==22) { 
     qDebug()<<"\nfail to open file error 22: Invalid argument"; 
     temp=QString(DIRPath+"/Temp"+QString::number(nb)); 
     Supported=false; 
    } else qDebug()<<"\nfail to open file error"<<GetLastError()<<"errno"<<errno<<"strerrno"<<strerror(errno); 
    Fname=NULL; 
    free(Fname); 
    ... 

我的問題是:任何人都可以澄清UNICODE/ANSI的混淆?我到目前爲止安全還是有更多的預防措施要考慮?有沒有更安全的方法來檢查給定的名稱是不是ANSI?

在此先感謝您,任何幫助將不勝感激。

編輯1

我試過,但白白:CreateFile()返回INVALID_HANDLE_VALUEGetLastError()返回0

//WCHAR fname[]=L"D:/أحدالأنشطة.txt"; 
char* name="D:/أحدالأنشطة.txt"; 
wchar_t* nameW=(wchar_t*)malloc(sizeof(wchar_t)*17); 
qDebug()<<"s :"<<mbstowcs(nameW,name,17); 
//QString path=QString::fromWCharArray(fname,17); 
//QString path=QString::fromLatin1(name,17); 

HANDLE fileHandle = CreateFile( nameW,     // file to open 
            GENERIC_READ,   // open for reading 
            FILE_SHARE_READ,  // share for reading 
            NULL,     // default security 
            OPEN_EXISTING,   // existing file only 
            FILE_ATTRIBUTE_NORMAL, // normal file 
            NULL); 

if (fileHandle == INVALID_HANDLE_VALUE) 
    { 
     qDebug()<<"CreateFile failed!\n"<<GetLastError(); 
     nameW=NULL; 
     free(nameW); 
     return 2; 
    }else 
      qDebug()<<"CreateFile succeeded!\n"; 

int fd = _open_osfhandle((intptr_t) fileHandle, _O_RDONLY); 
FILE* fstr = _fdopen(fd, "r"); 
QFile indirect; 
if (!indirect.open(fstr, QIODevice::ReadOnly)) 
    qDebug()<<"QFile open against file descriptor failed!\n"; 
    else 
     { 
      qDebug()<<"QFile open against file descriptor succeeded!\n";      
      indirect.close(); 
     } 

// This will fail 
QFile direct(path); 
if (!direct.open(QIODevice::ReadOnly)) 
    qDebug()<<"QFile open of filename directly failed!\n"; 
    else 
    { 
    qDebug()<<"QFile open of filename directly succeeded!\n"; 
    direct.close(); 
    } 
    nameW=NULL; 
    free(nameW); 

EDIT 2

QString fname(QFile::decodeName("D:/أحدالأنشطة.txt")); 
      QFile qFile(fname); 

      bool b=qFile.open(QIODevice::ReadOnly); 
      if(b) 
      { 
       FILE* filedesc = fdopen(qFile.handle(), "rb"); 
       if(filedesc!=NULL) 
       { 
        char* nb=(char*)malloc(2*sizeof(char)); 
        qDebug()<<"opened "; 
        size_t size=fread(nb,sizeof(char),2,filedesc); 
        fclose(filedesc); 
        qDebug()<<"filedesc closed size "<<size<<"nb "<<QString::fromAscii(nb,2); 
        nb=NULL; 
        free(nb); 

       }else qDebug()<<"filedesc failed error"<<strerror(errno); 


      }else 
       qDebug()<<"qFile failed error"<<strerror(errno); 
+0

請正確縮進代碼。將使閱讀(並幫助你)更容易。你編程的操作系統是什麼?這對決定如何幫助你起着巨大的作用。如果你正在使用Qt,你爲什麼打亂Fopen? – RedX

+5

fopen_s()看起來像「Visual C++」,所以很難理解爲什麼你不能使用Windows的CreateFile()。 QString看起來像QT,所以很難理解你爲什麼不使用QFile。 –

+0

謝謝,我在windows下工作,我需要文件名來傳遞我的應用程序的另一部分(用c編寫的算法,使用fopen打開我的文件)我不能說這個部分,所以我不得不處理fopen的工作()或QFile' – Oumaya

回答

3

你應該使用一個QFile打開文件,然後通過QFile::handle()到你的C函數。在C代碼中,您將使用fdopen()FILE*流與文件描述符相關聯。請注意,您在fdopen()中使用的模式應與您在QFile::open()中使用的模式兼容。例如:

void c_func(int fd) 
{ 
    FILE* file = fdopen(fd, "rb"); 
    // ... 
} 
+0

這是一個好主意,我測試了它,它只適用於ANSI文件名,它使用unicode失敗,QFile :: open失敗,使用unicode文件名 – Oumaya

+0

您可能忘記了將Unicode打開它之前的字符串。你應該使用QFile :: decodeName()。例如'QString fname(QFile :: decodeName(「D:/أحدالأنشطة。txt」));' –

+0

它也不起作用,我不知道爲什麼:(我添加了代碼,如果可以幫助 – Oumaya