2012-05-27 12 views
1
#ifndef UNICODE 
#define UNICODE 
#endif 

#include <Windows.h> 
#include <cstdio> 
#include <fstream> 

using namespace std; 

int main() 
{ 
    FILE* resFile; 
    char multiByteStr[256]; 
    ifstream oFile; 
    FILE* exampleFile; 
    TCHAR buffer[256];  
    system("chcp 65001"); 

    resFile = _wfopen(L"foo",L"w, ccs=UTF-8");    
    fwprintf(resFile,L"%s",L"C:\\exsistingFolder\\zażółć gęśłą jaźń ☺☻♥♦• ć.txt");  
    fclose(resFile); 

    oFile.open(L"foo");  
    oFile.getline(multiByteStr,256,'\n');  
    oFile.close();  

    MultiByteToWideChar(CP_UTF8,0,multiByteStr,256,buffer,256);  
    wprintf(L"%s",buffer); 

    exampleFile = _wfopen(buffer,L"w, ccs=UTF-16LE");  
    fwprintf(exampleFile,L"%s",buffer);  
    fclose(exampleFile); 

    system("pause"); 
    return 0; 
} 

正如你所看到的,程序應該創建文件「foo」的resFile包含該文件的完整路徑創建,並且這個新的文件exampleFile應該包含對自身的路徑。儘管在Visual Studio 2010自動調試期間,該緩衝區具有正確的字符串,但不會創建exampleFile。爲什麼?
另一件事:爲什麼wprintf不輸出擴展字符,儘管我已將控制檯的字體切換到Lucida控制檯 - 可以處理uncode字符的字體。UTF-8到寬字符轉換

詩篇。 exampleFile指向NULL,即使在_wfopen之後,緩衝區的最後一個字符也是'/0'

+0

'buffer' NULL終止了嗎?你是否在'oFile.close'後檢查了調用的返回值? – dirkgently

+0

[製作寬字符文件](http://stackoverflow.com/questions/10769023/making-wide-char-file) –

+0

要將Unicode打印到控制檯,除了'wprintf'之外,還需要'_setmode' (但不包括'chcp') - 請參閱http://blogs.msdn.com/b/michkap/archive/2008/03/18/8306597.aspx。 – Philipp

回答

1

的解決方案是非常trivial- _wfopen創造了UTF-8編碼與BOM一個文件,MultiByteToWideChar函數不會刪除BOM,所以我們需要手動解決這個問題。

2

你沒有做任何錯誤處理。最重要的是,當調用MultiByteToWideChar()時,您告訴它將轉換整個multiByteStr緩衝區,但大部分緩衝區都包含垃圾,因爲您事先未將其歸零。您必須使用緩衝區中的實際字符數,而不是緩衝區的最大大小。 MultiByteToWideChar()很可能會返回您忽略的錯誤。代碼中還有其他幾個失敗點。您需要經常檢查錯誤,特別是在與OS進行交互時。

試試這個:

#define UNICODE 

#include <Windows.h> 
#include <cstdio> 
#include <fstream> 

using namespace std; 

void pause() 
{ 
    wcin.ignore(); 
    wcin.get(); 
} 

int main() 
{ 
    FILE* resFile; 
    char multiByteStr[256] = {0}; 
    ifstream oFile; 
    FILE* exampleFile; 
    WCHAR buffer[256] = {0}; 

    SetConsoleOutputCP(CP_UTF8); 

    resFile = _wfopen(L"foo",L"w, ccs=UTF-8"); 
    if (!resFile) { 
     wprintf(L"Unable to create foo"); 
     goto done; 
    } 

    fwprintf(resFile,L"%s",L"C:\\exsistingFolder\\zażółć gęśłą jaźń ☺☻♥♦• ć.txt"); 
    fclose(resFile); 

    if (!oFile.open(L"foo")) { 
     wprintf(L"Unable to open foo"); 
     goto done; 
    } 

    oFile.getline(multiByteStr,255,'\n'); 
    oFile.close(); 

    if (MultiByteToWideChar(CP_UTF8,0,multiByteStr,-1,buffer,256) == 0) { 
     wprintf(L"Unable to convert UTF-8 to UTF-16. Error: %u", GetLastError()); 
     goto done; 
    } 

    exampleFile = _wfopen(buffer,L"w, ccs=UTF-16LE"); 
    if (!exampleFile) { 
     wprintf(L"Unable to create file: %s", buffer); 
     goto done; 
    } 

    fwprintf(exampleFile,L"%s",buffer); 
    fclose(exampleFile); 

    wprintf(L"created file: %s", buffer); 

done: 
    pause(); 
    return 0; 
} 
+0

簡單起見,我的代碼中已經刪除了錯誤處理。 MultiByteToWideChar函數幫助了我一點,但它沒有解決我的問題。 – 0x6B6F77616C74

1

爲什麼混搭你的I/O庫?這裏是一個純(視窗)C解決方案,減去錯誤檢查:

#include <stdio.h> 
#include <stdlib.h> 

int main() 
{ 
    FILE* pFile; 
    wchar_t buffer[256]; 

    _wfopen_s(&pFile,L"foo",L"w, ccs=UTF-8"); 
    fputws(L"C:/existingFolder/zażółć gęśłą jaźń ☺☻♥♦• ć.txt",pFile); 
    fclose(pFile); 

    _wfopen_s(&pFile,L"foo",L"r, ccs=UTF-8"); 
    fgetws(buffer,_countof(buffer),pFile); 
    fclose(pFile); 

    _wfopen_s(&pFile,buffer,L"w, ccs=UTF-16LE"); 
    fputws(buffer,pFile); 
    fclose(pFile); 

    return 0; 
} 
+0

你有沒有試過這個?它會引發運行時「debug assertion failed」消息框,就像我的程序一樣。 – 0x6B6F77616C74

+0

只要'C:/ existingFolder'存在,它就可以正常運行。將錯誤檢查添加到您的版本。如果文件沒有打開,它將會崩潰,因爲文件句柄將爲空。以適當的格式保存源文件也很重要。我使用了UTF-16LE(帶有BOM)。 –

+0

我的錯誤,感謝這件事,它很有用,它有效,但它仍然不是我的問題的答案。 – 0x6B6F77616C74