關於cout,wcout輸出的測試,以及printf,wprintf 輸出中文,記憶體中直接輸出映像給網頁問題

來源:互聯網
上載者:User

一:cout,wcout輸出測試

調試環境:VS2005 UNICODE

程式碼片段如下

 

_setmode(fileno(stdout),_O_BINARY);<br />TCHAR *pBuf = NULL;<br />SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);<br />SafeArrayUnaccessData (varBLOB.parray);</p><p>wcout<<pBuf<<endl; //輸出應該為pBuf指向的從資料庫讀出的映像部分位元據(正確函數用法下面在介紹)<br />cout<<&pBuf<<endl; //2 pBuf指標的地址<br />cout<<static_cast<void *>(pBuf)<<endl; //3 pBuf指向的位元據塊首地址(如果想輸出一個指標所指的地址,只要把此指標強制轉換成 void * 即可,C++ Primer 3 中,cout一章有此例子)</p><p>cout<<endl;<br />TCHAR *test = L"adf";<br />cout<<test<<endl; //4 test指向的字串常量首地址,至於為啥不是adf,原因在於test是寬位元組,而cout是單位元組輸出函數,所以變成輸出test的字串第一個位元組首地址</p><p>wcout<<test<<endl; // 此處輸出為正確的adf,控制台中顯示似乎還有一個空格。。</p><p>cout<<endl;<br />char *testb = "abc";<br />cout<<testb<<endl; // 輸出正確,且沒空格<br />wcout<<testb<<endl; // 此處輸出雖然也為字元,(與上一個例子不相反 - -!)但是字元中間有空格。。<br />//字元中間有空格的原因查明,是代碼前有一段 _setmode(fileno(stdout),_O_BINARY);設定成二進位就會有空格。改成 _setmode(fileno(stdout),_O_TEXT);無空格<br />

 

 

顯示結果如下: 

 

 

另:

TCHAR *test = L"adf";<br />cout<<test<<endl; //輸出為寬字元"a"低位元組地址0049504C<br />wcout<<test<<endl; //輸出結果為"adf";<br />test++;<br />cout<<test<<endl; //輸出為寬字元"a"高位元組地址0049504E<br />wcout<<test<<endl; //輸出結果為"df"<br />cout<<test[0]<<endl; // 輸出結果為100,應該為a的低位元組值<br />wcout<<test[0]<<endl; //輸出結果為a<br />cout<<test[1]<<endl; //輸出結果為102,應該為a的高位元組值<br />wcout<<test[1]<<endl; //輸出結果為d</p><p>cout<<L"adsafb"<<endl; //輸出結果為字串首地址

 

 

二,從資料庫中讀出的映像位元據直接輸出給瀏覽器

_variant_t varRecord(strRecord);<br />_variant_t varSQL(strSQL);</p><p>pRePtr->Open(varSQL,varRecord,adOpenStatic,adLockReadOnly,adCmdText);</p><p>if(pRePtr->GetRecordCount() == 0)<br />{<br />getnoneimage();<br />pRePtr->Close();<br />pRePtr.Release();<br />pRePtr = NULL;<br />return TRUE;<br />}</p><p>//讀出位元據<br />long lDataSize = pRePtr->GetFields()->GetItem("data")->ActualSize;///得到資料的長度<br />if(lDataSize > 0)<br />{<br />_variant_t varBLOB;<br />varBLOB = pRePtr->GetFields()->GetItem("data")->GetChunk(lDataSize);<br />if(varBLOB.vt == (VT_ARRAY | VT_UI1)) ///判斷資料類型是否正確,VT_UI1指無符號1位元組整數(BYTE)數組</p><p>{<br />TCHAR *pBuf = NULL;<br />SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);<br />fflush(stdout);<br />_setmode(_fileno(stdout),_O_TEXT);<br />fprintf(stdout,"Content-Type:image/jpeg;/n/n");<br />_setmode(_fileno(stdout),_O_BINARY);<br />cout.write((char*)pBuf,lDataSize ); //用此函數可以正確輸出映像。 方法一<br /> //wcout<<pBuf<<endl; //此函數只輸出一部分就結束了,(見第一張圖中的第一行),可能還需要其他步驟 PS:個人猜想,映像資料中有wcout 所認為的結束符。。</p><p>//以下幾種方法,經測試均可以正常輸出映像</p><p>//方法二: </p><p>//long n = 0 ;</p><p>//while(n < lDataSize) //lDataSize 的值為映像塊資料的長度</p><p>//{<br />//cout<<((char*)pBuf)[n]; //正確<br />//n++;<br />//}</p><p>//方法三<br />//long n = 0 ;</p><p>//while(n < lDataSize/2 )<br />//{</p><p>//wcout<<pBuf[n];<br />//n++;<br />//}</p><p>//方法四:<br />//wcout.write(pBuf,lDataSize/2); </p><p>//cout.write(pBuf,lDataSize) // 出錯,因為cout 輸出的是char*型<br />SafeArrayUnaccessData (varBLOB.parray);<br />fflush(stdout);<br />_setmode(_fileno(stdout),_O_TEXT);<br />

更簡單的輸出方法為:

if(varBLOB.vt == (VT_ARRAY | VT_UI1)) ///判斷資料類型是否正確<br />{</p><p>TCHAR *pBuf = NULL;<br />pBuf = (TCHAR*)(_bstr_t)(varBLOB);</p><p>fflush(stdout);<br />_setmode(_fileno(stdout),_O_TEXT);<br />fprintf(stdout,"Content-Type:image/jpeg;/n/n");<br />_setmode(_fileno(stdout),_O_BINARY);<br />wcout.write(pBuf,lDataSize/2);<br />fflush(stdout);<br />_setmode(_fileno(stdout),_O_TEXT);<br />}

 

三,cout,wcout,printf,wprintf等函數的中文輸出問題

轉篇文章

 

需要說明的是,我的開發環境是VS 2005(標準庫當然也是微軟實現的),不保證其它環境下是相同的效果。

 

 

 

 

 

  1、cout和wcout

 

 

  在預設的C locale下,cout可以直接輸出中文,但對於wcout卻不行(至少VS 2005下不行)。對於wcout,需要將其locale設為本地語言才能輸出中文:

  wcout.imbue(locale(locale(),"",LC_CTYPE));  // ①

  也有人用如下語句的,但這會改變wcout的所有locale設定,比如數字“1234”會輸出為“1,234”。

  wcout.imbue(locale(""));

  2、ofstream和wofstream

  在預設的C locale下,ofstream能正確輸出中文到檔案中,但不支援中文檔案名稱;wofstream支援中文檔案名稱,但不能向檔案中輸出中文。要解決這個問題,需要在開啟檔案之前將全域locale設為本地語言。將全域locale設為本地語言後,ofstream和wofstream的問題都解決了,但 cout和wcout卻不能輸出中文了。要讓cout和wcout輸出中文,需要將全域locale恢複原來的設定,如下所示:

  locale &loc=locale::global(locale(locale(),"",LC_CTYPE));  // ②

  ofstream ofs("ofs測試.txt");

  wofstream wofs(L"wofs測試.txt");

  locale::global(loc);  // ③

  ofs<<"test測試"<<1234<<endl;

  wofs<<L"Another test還是測試"<<1234<<endl;

  3、printf和wprintf

  加上這兩位C語言中的老兄,問題更加複雜。考慮如下語句(注意s的大小寫):

  printf("%s", "multibyte中文/n");  // ④

  printf("%S", L"unicode中文/n");  // ⑤

  wprintf(L"%S", "multibyte中文/n");  // ⑥

  wprintf(L"%s", L"unicode中文/n");  // ⑦

  預設情況下,⑤、⑦兩條語句不能輸出中文,這兩條語句中字串的形式是unicode形式的。如果在所有輸出語句之前加上如下語句將C語言的全域locale設定為本地語言(C語言中只有全域locale)就可以正常輸出了:

  setlocale(LC_CTYPE, "");  // ⑧

  但這會導致cout和wcout不能輸出中文(汗,的確麻煩),將C語言的全域locale恢複後cout和wcout就正常了,如下所示:

  setlocale(LC_CTYPE, "C");  // ⑨

  但恢複後,printf和wprintf輸出Unicode文本又不正常了(輸出MultiByte文本總是正常的)。總不能每寫一個 printf/wprintf就設定一次然後再恢複一次吧?所以,建議不要混用iostream和printf/wprintf,實在要混用,那就讓 printf/wprintf只輸出MultiByte字串,這樣不需要調用setlocale(),也就不會影響到cout和wcout.

  總結

  總之,用iostream、printf/wprintf輸出中文,有點麻煩。概括起來要點如下:

  ·如果要用wcout,需要在使用之前按語句①將其locale設定為本地語言;

  ·如果要用ofstream或wofstream,要在開啟檔案之前按語句②將全域locale設為本地語言並儲存初始的全域locale.然後在開啟檔案之後,按語句③將全域locale恢複為初始值;

  ·不要混用iostream和printf/wprintf.如果要混用,只用printf/wprintf輸出MultiByte字串;

  ·單獨使用printf/wprintf時,如果要輸出Unicode字串,需要按語句⑧設定C語言的全域locale.如果只輸出MultiByte字串,則不需設定。

 

 

而我自己的代碼中,用wprintf輸出中文需要執行以下段代碼即可,且wcout也可正常輸出中文

TCHAR szACP[16];<br />wsprintf(szACP, _T(".%d"), GetACP());<br />_tsetlocale(LC_CTYPE, szACP);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.