[C#] Special Chars

09/21/2012 04:38 urgabel#1
I'm working with simplified chinese texts, slowly translating all I can for the game Heroes of Might and Magic online (from TQ).
My program reads text data from 2 files, 1 chinese and 1 english; replace strings if english available and saves to a new file.
With a few strings I got a problem: the game uses a special string to avoid empty Names, and the Encoding does not well with that, but all other texts are fine, either english or chinese.
Here is part of my code:
Code:
Encoding enc = Encoding.GetEncoding(54936);      //"GB18030" = Page Code 54936: Simplified Chinese
using (StreamWriter sw = new StreamWriter(filename, false, enc))
{
	foreach (KeyValuePair<UInt32, NpcX> NPC in this.NPCs)
	{
		sw.WriteLine("[" + NPC.Key.ToString() + "]");
		//Check if Name is empty, and replace to ASCII(165)
		sw.WriteLine("Name=" + NPC.Value.Name);
		sw.WriteLine("RaceId=" + NPC.Value.RaceId.ToString());
		sw.WriteLine("AddSize=" + NPC.Value.AddSize.ToString());
		sw.WriteLine("Scale=" + NPC.Value.Scale.ToString());
		sw.WriteLine("FixDir=" + NPC.Value.FixDir.ToString());
		sw.WriteLine("Dir=" + NPC.Value.Dir.ToString());
		sw.WriteLine("Look=" + NPC.Value.Look.ToString());
		sw.WriteLine("Head=" + NPC.Value.Head.ToString());
		sw.WriteLine("Hair=" + NPC.Value.Hair.ToString());
		sw.WriteLine("Armet=" + NPC.Value.Armet.ToString());
		sw.WriteLine("Armor=" + NPC.Value.Armor.ToString());
		sw.WriteLine("RWeapon=" + NPC.Value.RWeapon.ToString());
		sw.WriteLine("LWeapon=" + NPC.Value.LWeapon.ToString());
		sw.WriteLine("Misc=" + NPC.Value.Misc.ToString());
		sw.WriteLine("Mount=" + NPC.Value.Mount.ToString());
		sw.WriteLine("Effect=" + NPC.Value.Effect);
		sw.WriteLine("Note=" + NPC.Value.Note);
		sw.WriteLine("");
	}
}
I need to write 2 bytes with same value = 165 decimal (or 0xA1).
Any suggestion?
09/21/2012 07:51 ernilos#2
Try Text.Encoding.UTF8
09/21/2012 16:34 urgabel#3
Quote:
Originally Posted by ernilos View Post
Try Text.Encoding.UTF8
There are lots of strings in chinese (still untranslated), and the game does not handle UTF, it reads strings with ANSI codepage "GB18030".
The problem is there are lots of decorative NPCs with special name displayed in game as empty name, but the string in file cannot be empty or the game does not play.
I could assign somtehing like "Unnamed", but it is so ugly...
What I need to write is exactly these 2 bytes with value 161, but I don't know how to do while using "GB18030" codepage.
If I don't use "GB18030" for the StreamWriter, the text in the file becomes corrupted when read by the game.

I've found a solution:

Code:
                Encoding enc = Encoding.GetEncoding(54936);      //"GB18030" = Page Code 54936: Simplified Chinese
                if (File.Exists(filename))                       // Delete the file if it exists.
                {
                    File.Delete(filename);
                }
                using (FileStream fs = File.Create(filename))    //Create the file.
                using (StreamWriter sw = new StreamWriter(fs, enc))
                {
                    foreach (KeyValuePair<UInt32, NpcX> NPC in this.NPCs)
                    {
                        sw.WriteLine("[" + NPC.Key.ToString() + "]");
                        if (NPC.Value.Name == "")   //Default empty name
                        {
                            sw.Write("Name=");
                            sw.Flush();
                            fs.Flush();
                            fs.WriteByte(161);
                            fs.WriteByte(161);
                            fs.Flush();
                            sw.Flush();
                            sw.WriteLine();         //End the line
                        }
                        else
                        {
                            sw.WriteLine("Name=" + NPC.Value.Name);
                        }
                        sw.WriteLine("RaceId=" + NPC.Value.RaceId.ToString());
                        sw.WriteLine("AddSize=" + NPC.Value.AddSize.ToString());
Using streamwriter to write text (with encoding) and filestream to write raw bytes.

Gracias por intentarlo ;)
09/24/2012 18:59 x]vIrus[x#4
what you do there is write 0xa1a1 have you tried writing (char)(short)0xa1a1?
just for the lulz
09/26/2012 01:42 urgabel#5
Quote:
Originally Posted by x]vIrus[x View Post
what you do there is write 0xa1a1 have you tried writing (char)(short)0xa1a1?
just for the lulz
Thanks for trying, even if already solved.
You cannot cast just 2 bytes to short (short is 32 bits) but also does not work if cast to Uint16.

I have tried several ways, including
Code:
sw.WriteLine((char) 0xa1a1);
and get in file 0x82 0x35 0xC2 0x30
I guess due to bad Encoding...

Anyway, the solution to write bytes with no encoding at all is to use a filestream.