Re: Get ASCII value for character when higher than 127
On 29 May 2007 07:01:32 -0700, ssetz@wxs.nl wrote:
Hi Sandra,
But, again, this works fine for normal characters, but not for the
special ones. This whole encoding stuff is starting to driving me
nuts!!!
In this message you can find a function I wrote in C++ to convert
"Windows Unicode" strings (i.e. UTF-16 Unicode) to the UTF-8 Unicode.
The function prototype is:
std::string StringUnicodeToUTF8( const wchar_t * unicodeString )
it gets a Unicode (UTF-16) string as input, and returns a UTF-8
encoded string as output.
<Notes>
- The function may throw exceptions on errors.
- The "core" of this function is the ::WideCharToMultiByte Win32 API
</Notes>
You could use this function to convert your (Unicode) strings into
UTF-8, and write them into XML files.
e.g.:
<CODE language="C++">
// Your Unicode strings
// (e.g. read from edit controls or whatever...)
const wchar_t * UserName = L"MisterJohn_?";
const wchar_t * Password = L"???";
// I put some typical Italian characters (vowels with stress)
// inside the strings.
// I don't know if the newsgroup will show them correctly;
// you may try with your own characters and also Chinese
// characters, etc.
// The XML file header with UTF-8 encoding
const std::string xmlHeader =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
//
// Build the XML text into an output string stream
//
std::ostringstream xmlString;
xmlString << xmlHeader << std::endl;
xmlString << "<userdata>";
xmlString << "<username>" << StringUnicodeToUTF8( UserName )
<< "</username>" << std::endl;
xmlString << "<password>" << StringUnicodeToUTF8( Password )
<< "</password>" << std::endl;
xmlString << "</userdata>" << std::endl;
//
// Write content to "user.xml" file
//
std::ofstream xmlFile( "user.xml" );
xmlFile << xmlString.str();
</CODE>
You can read the XML file from C# using code like the following (it
reads username and password from the XML file):
<CODE language="C#">
// Clear user name and password
// (txtUserName and txtPassword are TextBox'es)
txtUserName.Text = "";
txtPassword.Text = "";
// Read data from XML file
XmlTextReader reader = new XmlTextReader( @"user.xml" );
while (reader.Read())
{
if ( (reader.NodeType == XmlNodeType.Element))
{
if (reader.LocalName.Equals("username"))
{
txtUserName.Text = reader.ReadString();
}
else if (reader.LocalName.Equals("password"))
{
txtPassword.Text = reader.ReadString();
}
}
}
</CODE>
If you want to "scramble" the input XML file on the C++ side using
XOR, you could do as follows:
<CODE language="C++">
//
// Crypt file using XOR
//
// xmlString is an std::ostringstream,
// containing the text of the XML file.
std::string originalFile = xmlString.str();
// Destination file
std::ofstream scrambledFile( "user.xml.crypt" );
// Key for XOR crypt
const char scrambleKey = 0x77;
// Scrambling loop
for ( std::string::const_iterator it = originalFile.begin();
it != originalFile.end(); ++it )
{
scrambledFile.put( (*it) ^ scrambleKey );
}
</CODE>
And to read it back and un-sramble from C#, you could use code like
this (consider that I'm not a C# expert, so maybe there could exist a
better C# code than what I developed here):
<CODE language="C#">
//
// Decrypt file
//
// Input file to un-scramble
FileStream inputFile = new FileStream(@"user.xml.crypt",
FileMode.Open);
BinaryReader inputReader = new BinaryReader(inputFile);
// Output file
FileStream outputFile = new FileStream(@"user.xml",
FileMode.Create);
BinaryWriter outputWriter = new BinaryWriter(outputFile);
// XOR key
const byte scrambleKey = 0x77;
// Un-scrambling loop
for (long i = 0; i < inputReader.BaseStream.Length; i++)
{
byte dataByte = inputReader.ReadByte();
dataByte ^= scrambleKey;
outputWriter.Write(dataByte);
}
// Close files
outputWriter.Close();
outputFile.Close();
inputReader.Close();
inputFile.Close();
</CODE>
And there is the main StringUnicodeToUTF8 function:
<CODE language="C++">
//
// Convert (encode) a Unicode UTF-16 string to Unicode UTF-8.
//
// by MrAsm
//
std::string StringUnicodeToUTF8( const wchar_t * unicodeString )
{
// Check input string pointer
if ( unicodeString == NULL )
throw std::invalid_argument(
"StringUnicodeToUTF8: Bad pointer" );
// Special case of empty string
if ( *unicodeString == L'\0' )
return "";
// One Unicode UTF-16 character may be converted
// up to four (4) UTF-8 characters.
const int lengthW = ::lstrlenW( unicodeString ) + 1;
const int lengthUtf8 = lengthW * 4;
// Buffer for UTF-8 string
std::vector< char > utf8Buffer;
utf8Buffer.resize( lengthUtf8 );
// Try converting from Unicode UTF-16 to UTF-8
if ( ::WideCharToMultiByte(
CP_UTF8, // Convert to UTF-8
0, // Default flags [not used]
unicodeString, // Pointer to Unicode string to be
// converted
lengthW, // Number of wide-chars in input string
// (including NUL terminator)
&utf8Buffer[0], // Pointer to buffer to receive the
// destination string
lengthUtf8, // Size, in bytes, of the destination
// buffer
NULL, // [default - not used]
NULL ) // [default - not used]
== 0 )
{
throw std::runtime_error(
"StringUnicodeToUTF8: Conversion failed." );
}
// Return the UTF-8 string
return std::string( &utf8Buffer[0] );
}
</CODE>
HTH,
MrAsm