Пример #1
0
/////////////////////////////////////////////////////////////////////////////
// GetUnicodeString
/////////////////////////////////////////////////////////////////////////////
wchar_t*
	GetUnicodeString(
	LPCSTR	MultiByteString)
{
	wchar_t*	UnicodeString	= NULL;

	if (NULL != MultiByteString)
	{
		size_t	StringLength = strlen(MultiByteString) + 1;
		UnicodeString = new wchar_t[StringLength];
		GetUnicodeStringFromMultiByteString(MultiByteString, UnicodeString, (int)StringLength, -1);
	}

	return UnicodeString;
}
Пример #2
0
BOOL CStdioFile_i::ReadString(CString& rString)
{
  const int	nMAX_LINE_CHARS = 4096;
  BOOL			bReadData = FALSE;
  LPTSTR		lpsz;
  int			nLen = 0;
  wchar_t*		pszUnicodeString = NULL;
  char	*		pszMultiByteString= NULL;
  int			nChars = 0;
  
  try
  {
    // 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
    if (m_bIsUnicodeText)
    {
      // Do standard stuff - Unicode to Unicode. Seems to work OK.
      bReadData = CStdioFile::ReadString(rString);
    }
    else
    {
      pszUnicodeString	= new wchar_t[nMAX_LINE_CHARS]; 
      pszMultiByteString= new char[nMAX_LINE_CHARS]; 
      
      // Initialise to something safe
      memset(pszUnicodeString, 0, sizeof(wchar_t) * nMAX_LINE_CHARS);
      memset(pszMultiByteString, 0, sizeof(char) * nMAX_LINE_CHARS);
      
      // Read the string
      bReadData = (NULL != fgets(pszMultiByteString, nMAX_LINE_CHARS, m_pStream));
      
      if (bReadData)
      {
        // Convert multibyte to Unicode, using the specified code page
        nChars = GetUnicodeStringFromMultiByteString(pszMultiByteString, pszUnicodeString, nMAX_LINE_CHARS, m_nFileCodePage);
        
        if (nChars > 0)
        {
          rString = (CString)pszUnicodeString;
        }
      }
    }
#else
    
    if (!m_bIsUnicodeText)
    {
      // Do standard stuff -- read ANSI in ANSI
      bReadData = CStdioFile::ReadString(rString);
      
      // Get the current code page
      UINT nLocaleCodePage = GetCurrentLocaleCodePage();
      
      // If we got it OK...
      if (nLocaleCodePage > 0)
      {
        // if file code page does not match the system code page, we need to do a double conversion!
        if (nLocaleCodePage != (UINT)m_nFileCodePage)
        {
          int nStringBufferChars = rString.GetLength() + 1;
          
          pszUnicodeString	= new wchar_t[nStringBufferChars]; 
          
          // Initialise to something safe
          memset(pszUnicodeString, 0, sizeof(wchar_t) * nStringBufferChars);
          
          // Convert to Unicode using the file code page
          nChars = GetUnicodeStringFromMultiByteString(rString, pszUnicodeString, nStringBufferChars, m_nFileCodePage);
          
          // Convert back to multibyte using the system code page
          // (This doesn't really confer huge advantages except to avoid "mangling" of non-convertible special
          // characters. So, if a file in the E.European code page is displayed on a system using the 
          // western European code page, special accented characters which the system cannot display will be
          // replaced by the default character (a hash or something), rather than being incorrectly mapped to
          // other, western European accented characters).
          if (nChars > 0)
          {
            // Calculate how much we need for the MB buffer (it might be larger)
            nStringBufferChars = GetRequiredMultiByteLengthForUnicodeString(pszUnicodeString,nLocaleCodePage);
            pszMultiByteString= new char[nStringBufferChars];  
            
            nChars = GetMultiByteStringFromUnicodeString(pszUnicodeString, pszMultiByteString, nStringBufferChars, nLocaleCodePage);
            rString = (CString)pszMultiByteString;
          }
        }
      }
    }
    else
    {
      pszUnicodeString	= new wchar_t[nMAX_LINE_CHARS]; 
      
      // Initialise to something safe
      memset(pszUnicodeString, 0, sizeof(wchar_t) * nMAX_LINE_CHARS);
      
      // Read as Unicode, convert to ANSI
      
      // Bug fix by Dennis Jeryd 06/07/2003: initialise bReadData
      bReadData = (NULL != fgetws(pszUnicodeString, nMAX_LINE_CHARS, m_pStream));
      
      if (bReadData)
      {
        // Calculate how much we need for the multibyte string
        int nRequiredMBBuffer = GetRequiredMultiByteLengthForUnicodeString(pszUnicodeString,m_nFileCodePage);
        pszMultiByteString= new char[nRequiredMBBuffer];  
        
        nChars = GetMultiByteStringFromUnicodeString(pszUnicodeString, pszMultiByteString, nRequiredMBBuffer, m_nFileCodePage);
        
        if (nChars > 0)
        {
          rString = (CString)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);
        }
      }
    }
  }
  // Ensure we always delete in case of exception
  catch(...)
  {
    if (pszUnicodeString)	delete [] pszUnicodeString;
    
    if (pszMultiByteString) delete [] pszMultiByteString;
    
    throw;
  }
  
  if (pszUnicodeString)		delete [] pszUnicodeString;
  
  if (pszMultiByteString)		delete [] pszMultiByteString;
  
  return bReadData;
}
Пример #3
0
// --------------------------------------------------------------------------------------------
//
//	CStdioFile_i::WriteString()
//
// --------------------------------------------------------------------------------------------
// Returns:    void
// Parameters: LPCTSTR lpsz
//
// Purpose:		Writes string to file either in Unicode or multibyte, depending on whether the caller specified the
//					CStdioFile_i::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 CStdioFile_i::WriteString(LPCTSTR lpsz)
{
  wchar_t*	pszUnicodeString	= NULL; 
  char	*	pszMultiByteString= NULL;
  
  try
  {
    // If writing Unicode and at the start of the file, need to write byte mark
    if (m_nFlags & CStdioFile_i::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 & CStdioFile_i::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);	// leave space for multi-byte chars
      int		nCharsWritten = 0;
      int		nBufferSize = 0;
      
      pszUnicodeString	= new wchar_t[nChars]; 
      
      // Copy string to Unicode buffer
      lstrcpy(pszUnicodeString, lpsz);
      
      // Work out how much space we need for the multibyte conversion
      nBufferSize = GetRequiredMultiByteLengthForUnicodeString(pszUnicodeString, m_nFileCodePage);
      pszMultiByteString= new char[nBufferSize];  
      
      // Get multibyte string
      nCharsWritten = GetMultiByteStringFromUnicodeString(pszUnicodeString, pszMultiByteString, nBufferSize, m_nFileCodePage);
      
      if (nCharsWritten > 0)
      {
        // Do byte-mode write using actual chars written (fix by Howard J Oh)
        //			CFile::Write((const void*)pszMultiByteString, lstrlen(lpsz));
        CFile::Write((const void*)pszMultiByteString,
          nCharsWritten*sizeof(char));
      }
    }
    // Else if *not* compiled in Unicode
#else
    // If writing Unicode, need to convert
    if (m_nFlags & CStdioFile_i::modeWriteUnicode)
    {
      int		nChars = lstrlen(lpsz) + 1;	 // Why plus 1? Because yes
      int		nBufferSize = nChars * sizeof(wchar_t);
      int		nCharsWritten = 0;
      
      pszUnicodeString	= new wchar_t[nChars];
      pszMultiByteString= new char[nChars]; 
      
      // Copy string to multibyte buffer
      lstrcpy(pszMultiByteString, lpsz);
      
      nCharsWritten = GetUnicodeStringFromMultiByteString(pszMultiByteString, pszUnicodeString, nChars, m_nFileCodePage);
      
      if (nCharsWritten > 0)
      {
        // Do byte-mode write using actual chars written (fix by Howard J Oh)
        //			CFile::Write(pszUnicodeString, lstrlen(lpsz) * sizeof(wchar_t));
        CFile::Write(pszUnicodeString, nCharsWritten*sizeof(wchar_t));
      }
      else
      {
        ASSERT(false);
      }
      
    }
    // Else if we don't want to write Unicode, no conversion needed, unless the code page differs
    else
    {
      //		// Do standard stuff
      //		CStdioFile::WriteString(lpsz);
      
      // Get the current code page
      UINT nLocaleCodePage = GetCurrentLocaleCodePage();
      
      // If we got it OK, and if file code page does not match the system code page, we need to do a double conversion!
      if (nLocaleCodePage > 0 && nLocaleCodePage != (UINT)m_nFileCodePage)
      {
        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;
}
Пример #4
0
// --------------------------------------------------------------------------------------------
//
//	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];  
		int		nCharsWritten = 0;

		// Copy string to Unicode buffer
		lstrcpy(pszUnicodeString, lpsz);

		// Get multibyte string
		nCharsWritten = 
			GetMultiByteStringFromUnicodeString(pszUnicodeString, pszMultiByteString, ( short ) nBufferSize, GetACP());
		
		if (nCharsWritten > 0)
		{
			//   CFile::Write((const void*)pszMultiByteString, lstrlen(lpsz));

			// Do byte-mode write using actual chars written (fix by Howard J Oh)
			CFile::Write((const void*)pszMultiByteString,
				nCharsWritten*sizeof(char));
		}

		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
		wchar_t*	pszUnicodeString	= new wchar_t[nChars];
		char	*	pszMultiByteString= new char[nChars]; 
		int		nCharsWritten = 0;
		
		// Copy string to multibyte buffer
		lstrcpy(pszMultiByteString, lpsz);

		nCharsWritten =
			GetUnicodeStringFromMultiByteString(pszMultiByteString,
			pszUnicodeString, nChars, GetACP());
		
		if (nCharsWritten > 0)
		{
			//   CFile::Write(pszUnicodeString, lstrlen(lpsz) * sizeof(wchar_t));

			// Write in byte mode. Write actual number of chars written * bytes (fix by Howard J Oh)
			CFile::Write(pszUnicodeString, nCharsWritten*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);
		
		// Do byte-mode write. This avoids annoying "interpretation" of \n's as	\r\n
		CFile::Write((const void*)lpsz, lstrlen(lpsz)*sizeof(char));
	}

#endif
}