?? stdiofileex.cpp
字號:
{
int nChars = lstrlen(lpsz) + 1; // Why plus 1? Because yes
pszUnicodeString = new wchar_t[nChars];
// Initialise to something safe
memset(pszUnicodeString, 0, sizeof(wchar_t) * nChars);
// Convert to Unicode using the locale code page (the code page we are using in memory)
nChars = GetUnicodeStringFromMultiByteString((LPCSTR)(const char*)lpsz, pszUnicodeString, nChars, nLocaleCodePage);
// Convert back to multibyte using the file code page
// (Note that you can't reliably read a non-Unicode file written in code page A on a system using a code page B,
// modify the file and write it back using code page A, unless you disable all this double-conversion code.
// In effect, you have to choose between a mangled character display and mangled file writing).
if (nChars > 0)
{
// Calculate how much we need for the MB buffer (it might be larger)
nChars = GetRequiredMultiByteLengthForUnicodeString(pszUnicodeString, m_nFileCodePage);
pszMultiByteString= new char[nChars];
memset(pszMultiByteString, 0, sizeof(char) * nChars);
nChars = GetMultiByteStringFromUnicodeString(pszUnicodeString, pszMultiByteString, nChars, m_nFileCodePage);
// Do byte-mode write. This avoids annoying "interpretation" of \n's as \r\n
CFile::Write((const void*)pszMultiByteString, nChars * sizeof(char));
}
}
else
{
// Do byte-mode write. This avoids annoying "interpretation" of \n's as \r\n
CFile::Write((const void*)lpsz, lstrlen(lpsz)*sizeof(char));
}
}
#endif
}
// Ensure we always clean up
catch(...)
{
if (pszUnicodeString) delete [] pszUnicodeString;
if (pszMultiByteString) delete [] pszMultiByteString;
throw;
}
if (pszUnicodeString) delete [] pszUnicodeString;
if (pszMultiByteString) delete [] pszMultiByteString;
}
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... ; fixed by Dennis Jeryd 6/8/03
if (nOpenFlags & CFile::typeText && !(nOpenFlags & CFile::modeCreate) && !(nOpenFlags & 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 = GetLength();
if (m_bIsUnicodeText)
{
nByteCount = nByteCount - sizeof(wchar_t);
}
// Calc chars
nCharCount = (nByteCount / nCharSize);
}
return nCharCount;
}
// Get the current user磗 code page
UINT CStdioFileEx::GetCurrentLocaleCodePage()
{
_TCHAR szLocalCodePage[10];
UINT nLocaleCodePage = 0;
int nLocaleChars = ::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE, szLocalCodePage, 10);
// If OK
if (nLocaleChars > 0)
{
nLocaleCodePage = (UINT)_ttoi(szLocalCodePage);
ASSERT(nLocaleCodePage > 0);
}
else
{
ASSERT(false);
}
// O means either: no ANSI code page (Unicode-only locale?) or failed to get locale
// In the case of Unicode-only locales, what do multibyte apps do? Answers on a postcard.
return nLocaleCodePage;
}
// --------------------------------------------------------------------------------------------
//
// CStdioFileEx::GetUnicodeStringFromMultiByteString()
//
// --------------------------------------------------------------------------------------------
// Returns: int - num. of chars written (0 means error)
// Parameters: char * szMultiByteString (IN) Multi-byte input string
// wchar_t* szUnicodeString (OUT) Unicode outputstring
// int nUnicodeBufferSize (IN) Size of Unicode output buffer in chars(IN)
// 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.
//
int CStdioFileEx::GetUnicodeStringFromMultiByteString(IN LPCSTR szMultiByteString, OUT wchar_t* szUnicodeString, IN int nUnicodeBufferSize, IN int nCodePage)
{
bool bOK = true;
int nCharsWritten = 0;
if (szUnicodeString && szMultiByteString)
{
// If no code page specified, take default for system
if (nCodePage == -1)
{
nCodePage = GetACP();
}
try
{
// Zero out buffer first. NB: nUnicodeBufferSize is NUMBER OF CHARS, NOT BYTES!
memset((void*)szUnicodeString, '\0', sizeof(wchar_t) *
nUnicodeBufferSize);
// When converting to UTF8, don't set any flags (see Q175392).
nCharsWritten = MultiByteToWideChar((UINT)nCodePage,
(nCodePage==CP_UTF8 ? 0:MB_PRECOMPOSED), // Flags
szMultiByteString,-1,szUnicodeString,nUnicodeBufferSize);
}
catch(...)
{
TRACE(_T("Controlled exception in MultiByteToWideChar!\n"));
}
}
// Now fix nCharsWritten
if (nCharsWritten > 0)
{
nCharsWritten--;
}
ASSERT(nCharsWritten > 0);
return nCharsWritten;
}
// --------------------------------------------------------------------------------------------
//
// CStdioFileEx::GetMultiByteStringFromUnicodeString()
//
// --------------------------------------------------------------------------------------------
// Returns: int - number of characters written. 0 means error
// Parameters: wchar_t * szUnicodeString (IN) Unicode input string
// char* szMultiByteString (OUT) Multibyte output string
// int nMultiByteBufferSize (IN) Multibyte buffer size (chars)
// 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: Added fix by Andy Goodwin: make buffer into int.
// Exceptions: None.
//
int CStdioFileEx::GetMultiByteStringFromUnicodeString(wchar_t * szUnicodeString, char* szMultiByteString,
int nMultiByteBufferSize, int nCodePage)
{
BOOL bUsedDefChar = FALSE;
int nCharsWritten = 0;
// Fix by Andy Goodwin: don't do anything if buffer is 0
if ( nMultiByteBufferSize > 0 )
{
if (szUnicodeString && szMultiByteString)
{
// Zero out buffer first
memset((void*)szMultiByteString, '\0', nMultiByteBufferSize);
// If no code page specified, take default for system
if (nCodePage == -1)
{
nCodePage = GetACP();
}
try
{
// If writing to UTF8, flags, default char and boolean flag must be NULL
nCharsWritten = WideCharToMultiByte((UINT)nCodePage,
(nCodePage==CP_UTF8 ? 0 : WC_COMPOSITECHECK | WC_SEPCHARS), // Flags
szUnicodeString,-1,
szMultiByteString,
nMultiByteBufferSize,
(nCodePage==CP_UTF8 ? NULL:sDEFAULT_UNICODE_FILLER_CHAR), // Filler char
(nCodePage==CP_UTF8 ? NULL: &bUsedDefChar)); // Did we use filler char?
// If no chars were written and the buffer is not 0, error!
if (nCharsWritten == 0 && nMultiByteBufferSize > 0)
{
TRACE1("Error in WideCharToMultiByte: %d\n", ::GetLastError());
}
}
catch(...)
{
TRACE(_T("Controlled exception in WideCharToMultiByte!\n"));
}
}
}
// Now fix nCharsWritten
if (nCharsWritten > 0)
{
nCharsWritten--;
}
return nCharsWritten;
}
//---------------------------------------------------------------------------------------------------
//
// CStdioFileEx::GetRequiredMultiByteLengthForUnicodeString()
//
//---------------------------------------------------------------------------------------------------
// Returns: int
// Parameters: wchar_t * szUnicodeString,int nCodePage=-1
//
// Purpose: Obtains the multi-byte buffer size needed to accommodate a converted Unicode string.
// Notes: We can't assume that the buffer length is simply equal to the number of characters
// because that wouldn't accommodate multibyte characters!
//
/*static*/ int CStdioFileEx::GetRequiredMultiByteLengthForUnicodeString(wchar_t * szUnicodeString,int nCodePage /*=-1*/)
{
int nCharsNeeded = 0;
try
{
// If no code page specified, take default for system
if (nCodePage == -1)
{
nCodePage = GetACP();
}
// If writing to UTF8, flags, default char and boolean flag must be NULL
nCharsNeeded = WideCharToMultiByte((UINT)nCodePage,
(nCodePage==CP_UTF8 ? 0 : WC_COMPOSITECHECK | WC_SEPCHARS), // Flags
szUnicodeString,-1,
NULL,
0, // Calculate required buffer, please!
(nCodePage==CP_UTF8 ? NULL:sDEFAULT_UNICODE_FILLER_CHAR), // Filler char
NULL);
}
catch(...)
{
TRACE(_T("Controlled exception in WideCharToMultiByte!\n"));
}
return nCharsNeeded;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -