CStdioFile的Writestring无法写入中文的问题
以下代码文件以CStdioFile向无法向文本中写入中文(用notepad.exe查 看不到写入的中文)
CStdioFile file;
file.Open(…);
file.WriteString(_T("abc你好"));//只能写入abc
解决办法:
使用setlocale语句设定区域
#include <locale>//头文件
CStdioFile file;
file.Open(…);
char* old_locale = _strdup( setlocale(LC_CTYPE,NULL) );
setlocale( LC_CTYPE, "chs" );//设定
file.WriteString(_T("abc你好"));//正常写入
setlocale( LC_CTYPE, old_locale );
free( old_locale );//还原区域设定
简化处理可以仅使用语句setlocale( LC_CTYPE, "chs" )。
setlocale:
函数原形为:char *setlocale( int category, const char *locale );
头文件:<locale.h>
所支持的操作系统为:ANSI, Win 95, Win NT
对于简体中文可以使用如下设置:setlocale( LC_ALL, "chs" );
为什么一定要调用setlocale呢?
因为在C/C++语言标准中定义了其运行时的字符集环境为"C",也就是ASCII字符集的一个子集,那么mbstowcs在工作时会将cstr中所包含 的字符串看作是ASCII编码的字符,而不认为是一个包含有chs编码的字符串,所以他会将每一个中文拆成2个ASCII编码进行转换,这样得到的结果就 是会形成4个wchar_t的字符组成的串,那么如何才能够让mbstowcs正常工作呢?在调用mbstowcs进行转换之间必须明确的告诉 mbstowcs目前cstr串中包含的是chs编码的字符串,通过setlocale( LC_ALL, "chs" )函数调用来完成,需要注意的是这个函数会改变整个应用程序的字符集编码方式,必须要通过重新调用setlocale( LC_ALL, "C" )函数来还原,这样就可以保证mbstowcs在转换时将cstr中的串看作是中文串,并且转换成为2个wchar_t字符,而不是4个。
本地化设置需要具备三个条件:
a. 语言代码 (Language Code)
b. 国家代码 (Country Code)
c. 编码(Encoding)
本地名字可以用下面这些部分来构造:
语言代码_国家代码.编码 比如(zh_CN.UTF-8, en_US等)
locale的别名表见 /usr/lib/X11/locale/locale.alias(以Debian GNU/Linux为例)
setlocale语言字符串参考
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ALENTAM/archive/2008/04/11/2281121.aspx
另外还有一种方法就是重新写CStdioFile的派生类CStdioFileEx(网上有)。
//好像C++中没有类能够读些Unicode格式的文本文件,所以我写了下面这个类。用法很简单,大家尝试几下就明白了。
#pragma once
class CStdioFileEx: public CStdioFile
{
public:
CStdioFileEx();
CStdioFileEx( LPCTSTR lpszFileName, UINT nOpenFlags );
virtual BOOL Open( LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError = NULL );
virtual BOOL ReadString(CString& rString);
BOOL ReadWideString(CStringW& rString);
BOOL ReadAnsiString(CStringA& rString);
virtual void WriteString(LPCTSTR lpsz);
void WriteWideString(LPCWSTR lpsz);
void WriteAnsiString(LPCSTR lpsz);
bool IsUnicodeFormat() {return m_bIsUnicodeText;}
unsigned long GetCharCount();
// Additional flag to allow Unicode text format writing
enum {modeWriteUnicode = 0x100000};
static bool IsFileUnicode(const CString& sFilePath);
protected:
UINT PreprocessFlags(const CString& sFilePath, UINT& nOpenFlags);
bool m_bIsUnicodeText;
};
//。cpp文件
#include "stdafx.h"
#include "StdioFileEx.h"
//在UCS 编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,
//所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符"ZERO WIDTH NO-BREAK SPACE"。这样
//如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。
//因此字符"ZERO WIDTH NO-BREAK SPACE"又被称作BOM。
//UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8编码是
//EF BB BF。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。
//Windows就是使用BOM来标记文本文件的编码方式的。
//有些老的浏览器和文本编辑器不支持BOM。
#define UNICODE_BOM 0xFEFF//Unicode "byte order mark" which goes at start of file
CStdioFileEx::CStdioFileEx(): CStdioFile()
{
m_bIsUnicodeText = false;
}
CStdioFileEx::CStdioFileEx(LPCTSTR lpszFileName,UINT nOpenFlags)
:CStdioFile(lpszFileName, PreprocessFlags(lpszFileName, nOpenFlags))
{
}
BOOL CStdioFileEx::Open(LPCTSTR lpszFileName,UINT nOpenFlags,CFileException* pError /*=NULL*/)
{
PreprocessFlags(lpszFileName, nOpenFlags);
return CStdioFile::Open(lpszFileName, nOpenFlags, pError);
}
BOOL CStdioFileEx::ReadString(CString& rString)
{
#ifdef _UNICODE
return ReadWideString(rString);
#else
return ReadAnsiString(rString);
#endif
}
BOOL CStdioFileEx::ReadWideString(CStringW& rString)
{
_ASSERTE(m_pStream);
rString = L""; // empty string without deallocating
if(m_bIsUnicodeText)
{
// If at position 0, discard byte-order mark before reading
if(GetPosition() == 0)
{
wchar_t bom;
Read(&bom, sizeof(wchar_t));
}
const int nMaxSize = 128;
LPWSTR lpsz = rString.GetBuffer(nMaxSize);
LPWSTR lpszResult;
int nLen = 0;
for (;;)
{
lpszResult = fgetws(lpsz, nMaxSize+1, m_pStream);
rString.ReleaseBuffer();
// handle error/eof case
if (lpszResult == NULL && !feof(m_pStream))
{
Afx_clearerr_s(m_pStream);
AfxThrowFileException(CFileException::genericException, _doserrno,
m_strFileName);
}
// if string is read completely or EOF
if (lpszResult == NULL ||
(nLen = (int)lstrlenW(lpsz)) < nMaxSize ||
lpsz[nLen-1] == '/n')
break;
nLen = rString.GetLength();
lpsz = rString.GetBuffer(nMaxSize + nLen) + nLen;
}
//remove crlf if exist.
nLen = rString.GetLength();
if (nLen > 1 && rString.Mid(nLen-2) == L"/r/n")
{
rString.GetBufferSetLength(nLen-2);
}
return rString.GetLength() > 0;
}
else
{
CStringA ansiString;
BOOL bRetval = ReadAnsiString(ansiString);
//setlocale(LC_ALL, "chs_chn.936");//no need
rString = ansiString;
return bRetval;
}
}
BOOL CStdioFileEx::ReadAnsiString(CStringA& rString)
{
_ASSERTE(m_pStream);
rString = ""; // empty string without deallocating
if(!m_bIsUnicodeText)
{
const int nMaxSize = 128;
LPSTR lpsz = rString.GetBuffer(nMaxSize);
LPSTR lpszResult;
int nLen = 0;
for (;;)
{
lpszResult = fgets(lpsz, nMaxSize+1, m_pStream);
rString.ReleaseBuffer();
// handle error/eof case
if (lpszResult == NULL && !feof(m_pStream))
{
Afx_clearerr_s(m_pStream);
AfxThrowFileException(CFileException::genericException, _doserrno,
m_strFileName);
}
// if string is read completely or EOF
if (lpszResult == NULL ||
(nLen = (int)lstrlenA(lpsz)) < nMaxSize ||
lpsz[nLen-1] == '/n')
break;
nLen = rString.GetLength();
lpsz = rString.GetBuffer(nMaxSize + nLen) + nLen;
}
//remove crlf if exist.
nLen = rString.GetLength();
if (nLen > 1 && rString.Mid(nLen-2) == "/r/n")
{
rString.GetBufferSetLength(nLen-2);
}
return rString.GetLength() > 0;
}
else
{
CStringW wideString;
BOOL bRetval = ReadWideString(wideString);
//setlocale(LC_ALL, "chs_chn.936");//no need
rString = wideString;
return bRetval;
}
}
// Purpose: Writes string to file either in Unicode or multibyte, depending on whether the caller specified the
// CStdioFileEx::modeWriteUnicode flag. Override of base class function.
void CStdioFileEx::WriteString(LPCTSTR lpsz)
{
#ifdef _UNICODE
WriteWideString(lpsz);
#else
WriteAnsiString(lpsz);
#endif
}
void CStdioFileEx::WriteWideString(LPCWSTR lpsz)
{
ASSERT(lpsz != NULL);
if (lpsz == NULL)
{
AfxThrowInvalidArgException();
}
if(m_bIsUnicodeText)
{
ASSERT(m_pStream != NULL);
// If writing Unicode and at the start of the file, need to write byte mark
if(GetPosition() == 0)
{
wchar_t cBOM = (wchar_t)UNICODE_BOM;
CFile::Write(&cBOM, sizeof(wchar_t));
}
if (fputws(lpsz, m_pStream) == _TEOF)
AfxThrowFileException(CFileException::diskFull, _doserrno, m_strFileName);
}
else
{
USES_CONVERSION;
WriteAnsiString(CW2A(lpsz));
}
}
void CStdioFileEx::WriteAnsiString(LPCSTR lpsz)
{
ASSERT(lpsz != NULL);
if (lpsz == NULL)
{
AfxThrowInvalidArgException();
}
if(!m_bIsUnicodeText)
{
ASSERT(m_pStream != NULL);
if (fputs(lpsz, m_pStream) == _TEOF)
AfxThrowFileException(CFileException::diskFull, _doserrno, m_strFileName);
}
else
{
USES_CONVERSION;
WriteWideString(CA2W(lpsz));
}
}
UINT CStdioFileEx::PreprocessFlags(const CString& sFilePath, UINT& nOpenFlags)
{
m_bIsUnicodeText = false;
// If we have writeUnicode we must have write or writeRead as well
if (nOpenFlags & CStdioFileEx::modeWriteUnicode)
{
ASSERT(nOpenFlags & CFile::modeWrite || nOpenFlags & CFile::modeReadWrite);
m_bIsUnicodeText = true;
}
// If reading in text mode and not creating...
else if (nOpenFlags & CFile::typeText && !(nOpenFlags & CFile::modeCreate) && !(nOpenFlags & CFile::modeWrite ))
{
m_bIsUnicodeText = IsFileUnicode(sFilePath);
}
//如果要读写Unicode格式的文本文件, 必须切换到typeBinary方式, 因为这会影响fputws/fgetws的工作方式(具体情况参考MSDN)。
if (m_bIsUnicodeText)
{
nOpenFlags &= ~(CFile::typeText);
nOpenFlags |= CFile::typeBinary;
}
return nOpenFlags;
}
// Purpose: Determines whether a file is Unicode by reading the first character and detecting
// whether it's the Unicode byte marker.
bool CStdioFileEx::IsFileUnicode(const CString& sFilePath)
{
CFile file;
wchar_t cFirstChar;
CFileException exFile;
bool bIsUnicode = false;
// Open file in binary mode and read first character
if (file.Open(sFilePath, CFile::typeBinary | CFile::modeRead, &exFile))
{
// If byte is Unicode byte-order marker, let's say it's Unicode
if (file.Read(&cFirstChar, sizeof(wchar_t)) > 0 && cFirstChar == (wchar_t)UNICODE_BOM)
{
bIsUnicode = true;
}
file.Close();
}
else
{
// Handle error here if you like
}
return bIsUnicode;
}
unsigned long CStdioFileEx::GetCharCount()
{
int nCharSize;
unsigned long nByteCount, nCharCount = 0;
if (m_pStream)
{
// Get size of chars in file
nCharSize = m_bIsUnicodeText ? sizeof(wchar_t): sizeof(char);
// If Unicode, remove byte order mark from count
nByteCount = (unsigned long)GetLength();
if (m_bIsUnicodeText)
{
nByteCount = nByteCount - sizeof(wchar_t);
}
// Calc chars
nCharCount = (nByteCount / nCharSize);
}
return nCharCount;
}
CStdioFile的Writestring无法写入中文的问题的更多相关文章
- 使用cstdiofile在vs2010中无法写入中文的问题
在VC2010环境下, 以下代码无法实现使用CStdioFile向文本文件中写入中文(用notepad.exe查看不到写入的中文) CStdioFile file; file.Open(…); fil ...
- PHP往mysql数据库中写入中文失败
该类问题解决办法就是 在建立数据库连接之后,将该连接的编码方式改为中文. 代码如下: $linkID=@mysql_connect("localhost","root&q ...
- 分享一个解决MySQL写入中文乱码的方法
分享一个解决MySQL写入中文乱码的方法 之前有发帖请教过如何解决MySQL写入中文乱码的问题.但没人会,或者是会的人不想回答.搜索网上的答案并尝试很多次无效,所以当时就因为这个乱码问题搁浅了一个软件 ...
- python写入中文到文件乱码的问题
file = open(filename,'a',encoding='utf8')#指定写入编码为utf8,否则写入中文会乱码
- jsp页面写入中文到mysql时出现了乱码(转)
今天自己在用jsp把中文写入mysql的时候出现乱码,从数据库中读取出来的时候也显示为“??”,感觉应该出现了编码转换过程中的字符信息丢失.然后在mysql中直接执行该命令,发现中文是正常的,所有认为 ...
- Django的admin管理系统写入中文出错的解决方法/1267 Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (utf8_general_ci,COERCIBLE) for operation ‘locate’
Django的admin管理系统写入中文出错的解决方法 解决错误: 1267 Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and ( ...
- MySQL写入中文乱码
这点确实很迷,我的数据库属性确实设置了utf-8字符集,但写入中文还是乱码,后来是直接修改了全局配置才修改过来. 1.进入MySQL的本地安装路径,我的安装路径是"C:\Program Fi ...
- mysql 写入中文乱码
今天从另一个系统往mysql数据库写入数据,发现中文变成了????? 检查数据库的设置 ,server对应字符集是latinl 调整mysql参数配置,配置文件目录/etc/mysql/mysql.c ...
- CStdioFile.WriteString无法向文件写入中文
CStdioFile.WriteString向文件中写入字符串,但字符串中带有中文的,无法写入. 解决方案: 将带有中文的字符串进行转换后再写入文件. char* pBuffer = NULL; lo ...
随机推荐
- 由浅入深了解Retrofit(一)
Retrofit Retrofit与okhttp共同出自于Square公司,Retrofit是一个高质量和高效率的http库,Retrofit是对okhttp的网络框架做了一层封装,Retrofit内 ...
- [Eclipse]Eclipse快捷键
查看一个方法被谁调用:选中方法名字,Search-->Reference-->Workspace
- Java 进阶6 异常处理的陷阱
Java 进阶6 异常处理的陷阱 20131113 异常处理机制是 Java语言的特色之一,尤其是 Java的Checked 异常,更是体现了 Java语言的严谨性:没有完善的错误的代码根本就不会被执 ...
- 快速求排列组合 lucas定理
对于C(n, m) mod p.这里的n,m,p(p为素数)都很大的情况. 就不能再用C(n, m) = C(n - 1,m) + C(n - 1, m - 1)的公式递推了. 一般lucas定理的p ...
- MySQL Batched Key Access
Batched Key Access是MySQL 5.6 版本中的新特性,是一种用户提高表join性能的算法.[Batched Key Access] 对于多表join语句,当MySQL使 ...
- js的事件循环机制和任务队列
上篇讲异步的时候,提到了同步队列和异步队列的说法,其实只是一种形象的称呼,分别代表主线程中的任务和任务队列中的任务,那么此篇我们就来详细探讨这两者. 一.来张图感受一下 如果看完觉得一脸懵逼,请继续往 ...
- flowable EngineConfiguration的实现分析(2)
EngineConfiguration的实现类是一个抽象类:AbstractEngineConfiguration 一.引擎配置的分类 继承 AbsractEngineConfiguration的子类 ...
- 深度学习(六十九)darknet 实现实验 Compressing Deep Neural Networks with Pruning, Trained Quantization and Huffma
本文主要实验文献文献<Deep Compression: Compressing Deep Neural Networks with Pruning, Trained Quantization ...
- async eachSeries如何按序列执行下去
async callback要执行完才会进到一下个序列 async.mapSeries(files, function(file, outerCB) { var all = fs.readdirsyn ...
- jQuery AJAX 与 jQuery 事件
jQuery 本身即是为事件处理而特别设计的,jQuery 事件处理方法是 jQuery 中的核心函数. $(function() { ... }); 是如下格式的缩写: $(document).re ...