- 浏览: 624934 次
最新评论
-
csc08801:
兔子的问题,是第二个月再生一对兔子,不是第三个月;问题是有多少 ...
Java基础算法集50题 -
Caelebs:
Java基础算法集50题 -
maincoolbo:
不错,希望能做个老码农,,
Java基础算法集50题 -
warrior701:
vcok 写道人其实是很渺小的,包括那些所谓超过你的人。你是小 ...
首先你得承认世界上有全面超过你的人 -
jackie_yk:
引用这个方法很简单,但是我实在不明白框架的设计者为什么要先判断 ...
Spring 源码阅读 之 Spring框架加载
VC 编程ANSI环境下读写Unicode文件和将CStdioFile类扩展,读取UNICODE文本文件
VC 编程ANSI环境下读写Unicode文件
没有注意到文件编码的不同会产生这么多的问题,在动手以前查询了很多资料,在本博客中收藏了不少先辈的成果,在这里一并表示致敬!
关于ANSI和Unicode编码的原理在这里也不说了,主要讲下如何读写!
首先确定你的工程是采用的是什么编码环境,默认是ANSI,不同的字符集读写文件的差别也比较大,我这里只在ANSI环境下做的,下一步在探索在Unicode环境下如何读写!(原先这个没搞懂,读了不少代码发现自己试验都是有误的)。
在ANSI的字符集下,CString等都是单字节版本的,所以一定要注意。而多要读取的Unicode文件却是双字节的,这里就要转换了,当然在ANSI字符集下,还是用二进制的方式打开Unicode文件,自己判断是否是换行,在转化成ANSI编码。而在写Unicode的时候,先将所字符转化成Unicode编码再写入,而且在写文件之前一定要加上Unicode文件的标识。
下面是读
CFile mFile(UnicodefilePath,CFile::modeRead);
byte head[2];
mFile.Read(head,2);
if((head[0]==0xff&&head[1]==0xfe)||(head[0]==0xfe&&head[1]==0xff) )
{
//AfxMessageBox(_T("File is Unicode!"));
isUnicode = true;
}
if(isUnicode) mFile.Seek(2,CFile::begin); //0xfffe
wchar_t wch;
wchar_t wstr[300];
CString strvalue ;
hile(mFile.Read((char *)&wch,2)>0)
{
if(wch==0x000D) //by line
{
//chang to ansi
int nLen = i;
char *buf = new char[2*nLen];
WideCharToMultiByte(CP_ACP, 0, wstr, nLen, buf, 2*nLen, NULL, NULL);
buf[2*nLen-1] = 0; //some assertion failed,这个比较重要,小问题可以折腾人啊
strvalue = buf;
mFile.Seek(2,CFile::current); //跳过行开头符号
i=0;
}
else
{
wstr[i++] = wch;
}
}
//下面是写
CStdioFile transFile;
transFile.Open(strUnicodeSavepath,CFile::modeCreate|CFile::modeWrite|CFile::typeBinary);
WORD wSignature = 0xFEFF;
transFile.Write(&wSignature, 2); //Unicode的文件符号
CHAR *pszAnsi = new TCHAR[strvalue.GetLength()+1];
_tcscpy(pszAnsi, strvalue);
WCHAR * szwBuffer = new WCHAR[strvalue.GetLength()+1];
MultiByteToWideChar(CP_ACP, 0, pszAnsi, -1, szwBuffer, strvalue.GetLength()+1);
//write to files
transFile.Write(szwBuffer, lstrlenW(szwBuffer) * sizeof(WCHAR));
当然你可以把你的工程设置成Unicode的字符集,这个时候在Unicode的工程下读取ANSI文件又是一个烦人的事情,讲文件读到CString中的时候,每个单字节的ANSI被转成了双字节,需要自己来处理,后面我再探索探索再来记录。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Augusdi/archive/2009/10/15/4677528.aspx
============================================================================
将CStdioFile类扩展,读取UNICODE文本文件
最近因为要读取SQL脚本文件,用CStdioFile来读取脚本文件,却在程序调试时读取不了文件。
后来看了一下文本文件格式,竟然是UNICODE格式的,原来在导出SQL脚本的时候,选项默认的是UNICODE格式。为了同时支持ANSI和UNICODE两种格式,在Codeproject站点上找到了CStdioFileEx类的代码,但在调试运行过程中发现,在生成UNICODE版本的执行文件时,运行没有错误,但在非UNICODE版本中却出现错误,原来在代码中此部分没有考虑文件读到末尾的情况,经修改,CStdioFileEx类就可以正常使用了,在读取文本文件时,自动识别ANSI和UNICODE两种格式。
实现头文件如下:
#define nUNICODE_BOM 0xFEFF // Unicode "byte order mark" which goes at start of file
#define sNEWLINE _T("/r/n") // New line characters
#define sDEFAULT_UNICODE_FILLER_CHAR "#" // Filler char used when no conversion from Unicode to local code page is possible
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);
virtual void WriteString( LPCTSTR lpsz );
bool IsFileUnicodeText() { return m_bIsUnicodeText; }
unsigned long GetCharCount();
// Additional flag to allow Unicode text writing
static const UINT modeWriteUnicode;
// static utility functions
// --------------------------------------------------------------------------------------------
//
// CStdioFileEx::GetUnicodeStringFromMultiByteString()
//
// --------------------------------------------------------------------------------------------
// Returns: bool
// Parameters: char * szMultiByteString (IN) Multi-byte input string
// wchar_t* szUnicodeString (OUT) Unicode output string
// short nUnicodeBufferSize (IN) Size of Unicode output buffer
// UINT nCodePage (IN) Code page used to perform conversion
// Default = -1 (Get local code page).
//
// Purpose: Gets a Unicode string from a MultiByte string.
// Notes: None.
// Exceptions: None.
//
static bool GetUnicodeStringFromMultiByteString(char * szMultiByteString,wchar_t* szUnicodeString,
short nUnicodeBufferSize,UINT nCodePage=-1);
// --------------------------------------------------------------------------------------------
//
// CStdioFileEx::GetMultiByteStringFromUnicodeString()
//
// --------------------------------------------------------------------------------------------
// Returns: BOOL
// Parameters: wchar_t * szUnicodeString (IN) Unicode input string
// char* szMultiByteString (OUT) Multibyte output string
// short nMultiByteBufferSize (IN) Multibyte buffer size
// UINT nCodePage (IN) Code page used to perform conversion
// Default = -1 (Get local code page).
//
// Purpose: Gets a MultiByte string from a Unicode string.
// Notes: .
// Exceptions: None.
//
static BOOL GetMultiByteStringFromUnicodeString(wchar_t * szUnicodeString,char* szMultiByteString,
short nMultiByteBufferSize,UINT nCodePage=-1);
// --------------------------------------------------------------------------------------------
//
// CStdioFileEx::IsFileUnicode()
//
// --------------------------------------------------------------------------------------------
// Returns: bool
// Parameters: const CString& sFilePath
//
// Purpose: Determines whether a file is Unicode by reading the first character and detecting
// whether it's the Unicode byte marker.
// Notes: None.
// Exceptions: None.
//
static bool IsFileUnicode(const CString& sFilePath);
protected:
UINT ProcessFlags(const CString& sFilePath, UINT& nOpenFlags);
bool m_bIsUnicodeText;
UINT m_nFlags;
};
实现文件如下:
/*static*/ const UINT CStdioFileEx::modeWriteUnicode = 0x20000; // Add this flag to write in Unicode
CStdioFileEx::CStdioFileEx(): CStdioFile()
{
m_bIsUnicodeText = false;
}
CStdioFileEx::CStdioFileEx(LPCTSTR lpszFileName,UINT nOpenFlags)
:CStdioFile(lpszFileName, ProcessFlags(lpszFileName, nOpenFlags))
{
}
BOOL CStdioFileEx::Open(LPCTSTR lpszFileName,UINT nOpenFlags,CFileException* pError /*=NULL*/)
{
// Process any Unicode stuff
ProcessFlags(lpszFileName, nOpenFlags);
return CStdioFile::Open(lpszFileName, nOpenFlags, pError);
}
BOOL CStdioFileEx::ReadString(CString& rString)
{
const int nMAX_LINE_CHARS = 4096;
BOOL bReadData;
LPTSTR lpsz;
int nLen = 0; //, nMultiByteBufferLength = 0, nChars = 0;
CString sTemp;
wchar_t* pszUnicodeString = NULL;
char * pszMultiByteString= NULL;
// If at position 0, discard byte-order mark before reading
if (!m_pStream || (GetPosition() == 0 && m_bIsUnicodeText))
{
wchar_t cDummy;
// Read(&cDummy, sizeof(_TCHAR));
Read(&cDummy, sizeof(wchar_t));
}
// If compiled for Unicode
#ifdef _UNICODE
// Do standard stuff -- both ANSI and Unicode cases seem to work OK
bReadData = CStdioFile::ReadString(rString);
#else
if (!m_bIsUnicodeText)
{
// Do standard stuff -- read ANSI in ANSI
bReadData = CStdioFile::ReadString(rString);
}
else
{
pszUnicodeString = new wchar_t[nMAX_LINE_CHARS];
pszMultiByteString= new char[nMAX_LINE_CHARS];
// Read as Unicode, convert to ANSI
if(fgetws(pszUnicodeString, nMAX_LINE_CHARS, m_pStream)==NULL)
{
bReadData=FALSE;
}
else
{
bReadData=TRUE;
if (GetMultiByteStringFromUnicodeString(pszUnicodeString, pszMultiByteString, nMAX_LINE_CHARS))
{
rString = (CString)pszMultiByteString;
}
if (pszUnicodeString)
{
delete pszUnicodeString;
}
if (pszMultiByteString)
{
delete pszMultiByteString;
}
}
}
#endif
// Then remove end-of-line character if in Unicode text mode
if (bReadData)
{
// Copied from FileTxt.cpp but adapted to Unicode and then adapted for end-of-line being just '/r'.
nLen = rString.GetLength();
if (nLen > 1 && rString.Mid(nLen-2) == sNEWLINE)
{
rString.GetBufferSetLength(nLen-2);
}
else
{
lpsz = rString.GetBuffer(0);
if (nLen != 0 && (lpsz[nLen-1] == _T('/r') || lpsz[nLen-1] == _T('/n')))
{
rString.GetBufferSetLength(nLen-1);
}
}
}
return bReadData;
}
// --------------------------------------------------------------------------------------------
//
// CStdioFileEx::WriteString()
//
// --------------------------------------------------------------------------------------------
// Returns: void
// Parameters: LPCTSTR lpsz
//
// 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.
// Notes: If writing in Unicode we need to:
// a) Write the Byte-order-mark at the beginning of the file
// b) Write all strings in byte-mode
// - If we were compiled in Unicode, we need to convert Unicode to multibyte if
// we want to write in multibyte
// - If we were compiled in multi-byte, we need to convert multibyte to Unicode if
// we want to write in Unicode.
// Exceptions: None.
//
void CStdioFileEx::WriteString(LPCTSTR lpsz)
{
// If writing Unicode and at the start of the file, need to write byte mark
if (m_nFlags & CStdioFileEx::modeWriteUnicode)
{
// If at position 0, write byte-order mark before writing anything else
if (!m_pStream || GetPosition() == 0)
{
wchar_t cBOM = (wchar_t)nUNICODE_BOM;
CFile::Write(&cBOM, sizeof(wchar_t));
}
}
// If compiled in Unicode...
#ifdef _UNICODE
// If writing Unicode, no conversion needed
if (m_nFlags & CStdioFileEx::modeWriteUnicode)
{
// Write in byte mode
CFile::Write(lpsz, lstrlen(lpsz) * sizeof(wchar_t));
}
// Else if we don't want to write Unicode, need to convert
else
{
int nChars = lstrlen(lpsz) + 1; // Why plus 1? Because yes
int nBufferSize = nChars * sizeof(char);
wchar_t* pszUnicodeString = new wchar_t[nChars];
char * pszMultiByteString= new char[nChars];
// Copy string to Unicode buffer
lstrcpy(pszUnicodeString, lpsz);
// Get multibyte string
if (GetMultiByteStringFromUnicodeString(pszUnicodeString, pszMultiByteString, nBufferSize, GetACP()))
{
// Do standard write
CFile::Write((const void*)pszMultiByteString, lstrlen(lpsz));
}
if (pszUnicodeString && pszMultiByteString)
{
delete [] pszUnicodeString;
delete [] pszMultiByteString;
}
}
// Else if *not* compiled in Unicode
#else
// If writing Unicode, need to convert
if (m_nFlags & CStdioFileEx::modeWriteUnicode)
{
int nChars = lstrlen(lpsz) + 1; // Why plus 1? Because yes
int nBufferSize = nChars * sizeof(wchar_t);
wchar_t* pszUnicodeString = new wchar_t[nChars];
char * pszMultiByteString= new char[nChars];
// Copy string to multibyte buffer
lstrcpy(pszMultiByteString, lpsz);
if (GetUnicodeStringFromMultiByteString(pszMultiByteString, pszUnicodeString, nBufferSize, GetACP()))
{
// Write in byte mode
CFile::Write(pszUnicodeString, lstrlen(lpsz) * sizeof(wchar_t));
}
else
{
ASSERT(false);
}
if (pszUnicodeString && pszMultiByteString)
{
delete [] pszUnicodeString;
delete [] pszMultiByteString;
}
}
// Else if we don't want to write Unicode, no conversion needed
else
{
// Do standard stuff
CStdioFile::WriteString(lpsz);
}
#endif
}
UINT CStdioFileEx::ProcessFlags(const CString& sFilePath, UINT& nOpenFlags)
{
m_bIsUnicodeText = false;
// If we have writeUnicode we must have write or writeRead as well
#ifdef _DEBUG
if (nOpenFlags & CStdioFileEx::modeWriteUnicode)
{
ASSERT(nOpenFlags & CFile::modeWrite || nOpenFlags & CFile::modeReadWrite);
}
#endif
// If reading in text mode and not creating...
if (nOpenFlags & CFile::typeText && !(m_nFlags & CFile::modeCreate) && !(m_nFlags & CFile::modeWrite ))
{
m_bIsUnicodeText = IsFileUnicode(sFilePath);
// If it's Unicode, switch to binary mode
if (m_bIsUnicodeText)
{
nOpenFlags ^= CFile::typeText;
nOpenFlags |= CFile::typeBinary;
}
}
m_nFlags = nOpenFlags;
return nOpenFlags;
}
// --------------------------------------------------------------------------------------------
//
// CStdioFileEx::IsFileUnicode()
//
// --------------------------------------------------------------------------------------------
// Returns: bool
// Parameters: const CString& sFilePath
//
// Purpose: Determines whether a file is Unicode by reading the first character and detecting
// whether it's the Unicode byte marker.
// Notes: None.
// Exceptions: None.
//
/*static*/ bool CStdioFileEx::IsFileUnicode(const CString& sFilePath)
{
CFile file;
bool bIsUnicode = false;
wchar_t cFirstChar;
CFileException exFile;
// 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)nUNICODE_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;
}
// --------------------------------------------------------------------------------------------
//
// CStdioFileEx::GetUnicodeStringFromMultiByteString()
//
// --------------------------------------------------------------------------------------------
// Returns: bool
// Parameters: char * szMultiByteString (IN) Multi-byte input string
// wchar_t* szUnicodeString (OUT) Unicode outputstring
// short nUnicodeBufferSize (IN) Size of Unicode output buffer
// UINT nCodePage (IN) Code page used to perform conversion
// Default = -1 (Get local code page).
//
// Purpose: Gets a Unicode string from a MultiByte string.
// Notes: None.
// Exceptions: None.
//
bool CStdioFileEx::GetUnicodeStringFromMultiByteString(char * szMultiByteString, wchar_t* szUnicodeString, short nUnicodeBufferSize, UINT nCodePage)
{
bool bOK = true;
int nReturn = 0;
CString sErrorMsg;
if (szUnicodeString && szMultiByteString)
{
// If no code page specified, take default for system
if (nCodePage == -1)
{
nCodePage = GetACP();
}
try
{
nReturn = MultiByteToWideChar(nCodePage,MB_PRECOMPOSED,szMultiByteString,-1,szUnicodeString,nUnicodeBufferSize);
if (nReturn == 0)
{
bOK = false;
}
}
catch(...)
{
bOK = false;
}
}
else
{
bOK = false;
}
ASSERT(bOK);
return bOK;
}
// --------------------------------------------------------------------------------------------
//
// CStdioFileEx::GetMultiByteStringFromUnicodeString()
//
// --------------------------------------------------------------------------------------------
// Returns: BOOL
// Parameters: wchar_t * szUnicodeString (IN) Unicode input string
// char* szMultiByteString (OUT) Multibyte output string
// short nMultiByteBufferSize (IN) Multibyte buffer size
// UINT nCodePage (IN) Code page used to perform conversion
// Default = -1 (Get local code page).
//
// Purpose: Gets a MultiByte string from a Unicode string
// Notes: None.
// Exceptions: None.
//
BOOL CStdioFileEx::GetMultiByteStringFromUnicodeString(wchar_t * szUnicodeString, char* szMultiByteString,
short nMultiByteBufferSize, UINT nCodePage)
{
BOOL bUsedDefChar = FALSE;
BOOL bGotIt = FALSE;
if (szUnicodeString && szMultiByteString)
{
// If no code page specified, take default for system
if (nCodePage == -1)
{
nCodePage = GetACP();
}
try
{
bGotIt = WideCharToMultiByte(nCodePage, WC_COMPOSITECHECK | WC_SEPCHARS,
szUnicodeString,-1, szMultiByteString, nMultiByteBufferSize, sDEFAULT_UNICODE_FILLER_CHAR, &bUsedDefChar);
}
catch(...)
{
TRACE(_T("Controlled exception in WideCharToMultiByte!/n"));
}
}
return bGotIt;
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Augusdi/archive/2009/10/15/4677520.aspx
相关推荐
值得注意的是,上述代码和描述中引用了Visual C++(VC)的相关类和函数,如CFile、CStdioFile、WideCharToMultiByte和MultiByteToWideChar等,这些类和函数是Microsoft Visual C++提供的,用于处理文件读写以及字符...
本资源摘要信息介绍了如何在VC ANSI环境下按行读取四种不同编码格式的文本文件,包括ANSI、UNICODE、UNICODE big endian和UTF-8。通过研究这四种编码方式的特点,设计了一个继承自CStdioFile类的扩展类CStdioFileEx...
在VC6环境下,CStdioFile是MFC(Microsoft Foundation Classes)库中提供的一种用于文本文件操作的类,它基于标准C语言的stdio.h库,提供了简单易用的接口进行文件的读写操作。本教程将详细介绍如何使用CStdioFile...
VisualC 实效编程 81 用CStdioFile读写文件VisualC 实效编程 81 用CStdioFile读写文件VisualC 实效编程 81 用CStdioFile读写文件VisualC 实效编程 81 用CStdioFile读写文件VisualC 实效编程 81 用CStdioFile读写文件...
(包括ANSI、UNICODE、UNICODE big endian、UTF-8)格式的文本文件 */ //核心算法:CStdioFileEx继承自CStdioFile, 覆盖CStdioFile的 BOOL ReadString(CString& rString)方法, // 根据不同文件编码特征,寻找文件...
该技术基于 CStdioFile 类,提供了对文本文件和二进制文件的读写操作。 文件的概念 在计算机中,一切数据都是以文件的形式存储在磁盘上的,每个文件都有一个文件名,文件名由主文件名和扩展名两部分组成,中间用...
`CStdioFileEx`类是`CStdioFile`的一个增强版本,它添加了对UNICODE读写功能的内置支持。这意味着当读取文件时,`CStdioFileEx`能够自动检测文件的字符集,无论是ASCII、UTF-8还是其他UNICODE编码,都能正确处理。这...
在Microsoft Visual Studio中进行C++开发时,我们经常会遇到与文件操作相关的任务。...在实际编程中,根据项目需求和团队习惯,选择合适的文件操作类是非常重要的,而`CStdioFile`无疑为开发者提供了更多的可能性。
在VC++编程环境中,我们经常会遇到需要处理文件输入输出的需求,这时可以利用MFC(Microsoft Foundation Classes)库中的CStdioFile类。CStdioFile是CFile的一个派生类,它提供了对标准C库中的stdio.h接口的支持,...
在VC++编程环境中,逐行读取文本文件是一项常见的任务,尤其在处理大量数据或进行文本分析时。这里我们将深入探讨如何使用C++标准库和MFC(Microsoft Foundation Classes)来实现这一功能。 首先,我们可以使用C++...
在VC++编程环境中,`CStdioFile`是MFC(Microsoft Foundation Classes)库中一个非常重要的类,它提供了一种方便的方式来处理标准输入/输出流,如打开、读取和写入文本文件。这个类是基于Cstdio库(也称为cstdio或...
在这个例子中,我们关注的是一个扩展的MFC类——`CStdioFileEx`,这个类是`CStdioFile`的增强版,增加了对UNICODE字符集的支持,使得文件读写更加灵活和兼容。 通常,`CStdioFile`是MFC提供的一种简单方式来处理...
在这个场景中,我们关注的是如何“逐行读取文本文件”,特别是在C++环境下使用CStdioFile类处理TXT文件。CStdioFile是MFC(Microsoft Foundation Classes)库提供的一种文件处理类,它封装了标准C语言的stdio.h库,...
本文将深入探讨如何使用MFC来实现对TXT文件的读写操作,这对于任何需要处理文本数据的Windows应用都是基础且重要的。 首先,我们需要了解MFC中的CFile类,它是所有文件操作的基础。CFile类提供了标准的文件操作接口...
总之,MFC中的CStdioFile类为文本文件的读写提供了强大的支持,特别是`ReadString`和`WriteString`函数,它们使得按行读取和写入文件变得简单而高效。对于从事C++与MFC应用开发的程序员来说,熟练掌握这些功能是非常...
在计算机编程中,尤其是在使用MFC(Microsoft Foundation Classes)框架的环境下,CStdioFile类是处理文本文件操作的重要工具。CStdioFile类是在afx.h头文件中声明的,它是CFile类的派生类,主要用于处理使用C运行时...
这个“位图BMP格式图像文件处理类源码VC版.rar”包含了一个C++类,它提供了读取和写入BMP文件的功能,对于开发者来说,了解和使用这样的类可以帮助他们更好地处理图像数据。 首先,我们来看BMP文件的结构。一个BMP...
在VC++环境中,读取和写入TXT文件是常见的任务,可以使用MFC(Microsoft Foundation Classes)中的CStdioFile类来实现。本教程将详细解释如何使用VC++的CStdioFile类来读取和保存TXT文件。 首先,我们需要在工程中...