using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace BinaryPacker
{
class Program
{
static void Main(string[] args)
{
//输出到xml
//创建xml文档
//实例化一个xmldocument类
XmlDocument xDoc = new XmlDocument();
//声明一个xml所需要的语法的变量,添加在末尾
XmlDeclaration xmlDeclaration = xDoc.CreateXmlDeclaration("1.0", "UTF-8", "yes");
//创建根节点
XmlElement ele = null;// xDoc.CreateElement("grades");
BinaryPacker.Element element = BinaryPacker.FromBinary(@"H:\Maps\Maps\0-Intro.bin");
//xDoc.AppendChild(ele);
string xmlname = "";
element.ToStringXML(xDoc, ele,ref xmlname);
xDoc.Save(xmlname+".xml");
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace BinaryPacker
{
class BinaryPacker
{
public static void ToBinary(string filename, string outdir = null)
{
string extension = Path.GetExtension(filename);
if (outdir != null)
{
Path.Combine(new string[]
{
outdir + Path.GetFileName(filename)
});
}
filename.Replace(extension, BinaryPacker.OutputFileExtension);
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(filename);
XmlElement rootElement = null;
foreach (object obj in xmlDocument.ChildNodes)
{
if (obj is XmlElement)
{
rootElement = (obj as XmlElement);
break;
}
}
BinaryPacker.ToBinary(rootElement, outdir);
}
public static void ToBinary(XmlElement rootElement, string outfilename)
{
BinaryPacker.stringValue.Clear();
BinaryPacker.stringCounter = 0;
BinaryPacker.CreateLookupTable(rootElement);
BinaryPacker.AddLookupValue(BinaryPacker.InnerTextAttributeName);
using (FileStream fileStream = new FileStream(outfilename, FileMode.Create))
{
BinaryWriter binaryWriter = new BinaryWriter(fileStream);
binaryWriter.Write("CELESTE MAP");
binaryWriter.Write(Path.GetFileNameWithoutExtension(outfilename));
binaryWriter.Write((short)BinaryPacker.stringValue.Count);
foreach (KeyValuePair<string, short> keyValuePair in BinaryPacker.stringValue)
{
binaryWriter.Write(keyValuePair.Key);
}
BinaryPacker.WriteElement(binaryWriter, rootElement);
binaryWriter.Flush();
}
}
private static void CreateLookupTable(XmlElement element)
{
BinaryPacker.AddLookupValue(element.Name);
foreach (object obj in element.Attributes)
{
XmlAttribute xmlAttribute = (XmlAttribute)obj;
if (!BinaryPacker.IgnoreAttributes.Contains(xmlAttribute.Name))
{
BinaryPacker.AddLookupValue(xmlAttribute.Name);
byte b;
object obj2;
if (BinaryPacker.ParseValue(xmlAttribute.Value, out b, out obj2) && b == 5)
{
BinaryPacker.AddLookupValue(xmlAttribute.Value);
}
}
}
foreach (object obj3 in element.ChildNodes)
{
if (obj3 is XmlElement)
{
BinaryPacker.CreateLookupTable(obj3 as XmlElement);
}
}
}
private static void AddLookupValue(string name)
{
if (!BinaryPacker.stringValue.ContainsKey(name))
{
BinaryPacker.stringValue.Add(name, BinaryPacker.stringCounter);
BinaryPacker.stringCounter += 1;
}
}
private static void WriteElement(BinaryWriter writer, XmlElement element)
{
int num = 0;
IEnumerator enumerator = element.ChildNodes.GetEnumerator();
while (enumerator.MoveNext())
{
if (enumerator.Current is XmlElement)
{
num++;//遍历有多少xml子结点结点
}
}
int num2 = 0;
foreach (object obj in element.Attributes)
{
XmlAttribute xmlAttribute = (XmlAttribute)obj;
if (!BinaryPacker.IgnoreAttributes.Contains(xmlAttribute.Name))
{
num2++;
}
}
if (element.InnerText.Length > 0 && num == 0)
{
num2++;
}
writer.Write(BinaryPacker.stringValue[element.Name]);
writer.Write((byte)num2);
foreach (object obj2 in element.Attributes)
{
XmlAttribute xmlAttribute2 = (XmlAttribute)obj2;
if (!BinaryPacker.IgnoreAttributes.Contains(xmlAttribute2.Name))
{
byte value;
object obj3;
BinaryPacker.ParseValue(xmlAttribute2.Value, out value, out obj3);
writer.Write(BinaryPacker.stringValue[xmlAttribute2.Name]);
writer.Write(value);
switch (value)
{
case 0:
writer.Write((bool)obj3);
break;
case 1:
writer.Write((byte)obj3);
break;
case 2:
writer.Write((short)obj3);
break;
case 3:
writer.Write((int)obj3);
break;
case 4:
writer.Write((float)obj3);
break;
case 5:
writer.Write(BinaryPacker.stringValue[(string)obj3]);
break;
}
}
}
if (element.InnerText.Length > 0 && num == 0)
{
writer.Write(BinaryPacker.stringValue[BinaryPacker.InnerTextAttributeName]);
if (element.Name == "solids" || element.Name == "bg")
{
byte[] array = RunLengthEncoding.Encode(element.InnerText);
writer.Write(7);
writer.Write((short)array.Length);
writer.Write(array);
}
else
{
writer.Write(6);
writer.Write(element.InnerText);
}
}
writer.Write((short)num);
foreach (object obj4 in element.ChildNodes)
{
if (obj4 is XmlElement)
{
BinaryPacker.WriteElement(writer, obj4 as XmlElement);
}
}
}
private static bool ParseValue(string value, out byte type, out object result)
{
bool flag;
byte b;
short num;
int num2;
float num3;
if (bool.TryParse(value, out flag))
{
type = 0;
result = flag;
}
else if (byte.TryParse(value, out b))
{
type = 1;
result = b;
}
else if (short.TryParse(value, out num))
{
type = 2;
result = num;
}
else if (int.TryParse(value, out num2))
{
type = 3;
result = num2;
}
else if (float.TryParse(value, NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite | NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out num3))
{
type = 4;
result = num3;
}
else
{
type = 5;
result = value;
}
return true;
}
public static BinaryPacker.Element FromBinary(string filename)
{
BinaryPacker.Element element;
using (FileStream fileStream = File.OpenRead(filename))
{
BinaryReader binaryReader = new BinaryReader(fileStream);
binaryReader.ReadString();
string package = binaryReader.ReadString();
short num = binaryReader.ReadInt16();
BinaryPacker.stringLookup = new string[(int)num];
for (int i = 0; i < (int)num; i++)
{
BinaryPacker.stringLookup[i] = binaryReader.ReadString();
}
element = BinaryPacker.ReadElement(binaryReader);
element.Package = package;
}
return element;
}
private static BinaryPacker.Element ReadElement(BinaryReader reader)
{
BinaryPacker.Element element = new BinaryPacker.Element();
element.Name = BinaryPacker.stringLookup[(int)reader.ReadInt16()];
byte b = reader.ReadByte();
if (b > 0)
{
element.Attributes = new Dictionary<string, object>();
}
for (int i = 0; i < (int)b; i++)
{
string key = BinaryPacker.stringLookup[(int)reader.ReadInt16()];
byte b2 = reader.ReadByte();
object value = null;
if (b2 == 0)
{
value = reader.ReadBoolean();
}
else if (b2 == 1)
{
value = Convert.ToInt32(reader.ReadByte());
}
else if (b2 == 2)
{
value = Convert.ToInt32(reader.ReadInt16());
}
else if (b2 == 3)
{
value = reader.ReadInt32();
}
else if (b2 == 4)
{
value = reader.ReadSingle();
}
else if (b2 == 5)
{
value = BinaryPacker.stringLookup[(int)reader.ReadInt16()];
}
else if (b2 == 6)
{
value = reader.ReadString();
}
else if (b2 == 7)
{
short count = reader.ReadInt16();
value = RunLengthEncoding.Decode(reader.ReadBytes((int)count));
}
element.Attributes.Add(key, value);
}
short num = reader.ReadInt16();
if (num > 0)
{
element.Children = new List<BinaryPacker.Element>();
}
for (int j = 0; j < (int)num; j++)
{
element.Children.Add(BinaryPacker.ReadElement(reader));
}
return element;
}
public static readonly HashSet<string> IgnoreAttributes = new HashSet<string>
{
"_eid"
};
public static string InnerTextAttributeName = "innerText";
public static string OutputFileExtension = ".bin";
private static Dictionary<string, short> stringValue = new Dictionary<string, short>();
private static string[] stringLookup;
private static short stringCounter;
public class Element
{
public bool HasAttr(string name)
{
return this.Attributes != null && this.Attributes.ContainsKey(name);
}
public string Attr(string name, string defaultValue = "")
{
object obj;
if (this.Attributes == null || !this.Attributes.TryGetValue(name, out obj))
{
obj = defaultValue;
}
return obj.ToString();
}
public bool AttrBool(string name, bool defaultValue = false)
{
object obj;
if (this.Attributes == null || !this.Attributes.TryGetValue(name, out obj))
{
obj = defaultValue;
}
if (obj is bool)
{
return (bool)obj;
}
return bool.Parse(obj.ToString());
}
public float AttrFloat(string name, float defaultValue = 0f)
{
object obj;
if (this.Attributes == null || !this.Attributes.TryGetValue(name, out obj))
{
obj = defaultValue;
}
if (obj is float)
{
return (float)obj;
}
return float.Parse(obj.ToString(), CultureInfo.InvariantCulture);
}
public string Package;
public string Name;
public Dictionary<string, object> Attributes;
public List<BinaryPacker.Element> Children;
public void ToStringXML(XmlDocument xDoc,XmlElement element,ref string name)
{
if (element != null) {
XmlElement elementc = xDoc.CreateElement(Name);
element.AppendChild(elementc);
element = elementc;
if (Package != null)
{
element.SetAttribute("Package", Package);
}
}
else {
element = xDoc.CreateElement(Name);
name = Package;
xDoc.AppendChild(element);
element.SetAttribute("Package", Package);
}
if (Attributes!=null) {
List<KeyValuePair<string, object>> lit = Attributes.ToList();
for (int j = 0; j < lit.Count; j++)
{
element.SetAttribute(lit[j].Key, lit[j].Value.ToString());
}
}
if (Children != null)
{
for (int i = 0; i < Children.Count; i++)
{
Children[i].ToStringXML(xDoc, element,ref name);
}
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BinaryPacker
{
public static class RunLengthEncoding
{
public static byte[] Encode(string str)
{
List<byte> list = new List<byte>();
for (int i = 0; i < str.Length; i++)
{
byte b = 1;
char c = str[i];
while (i + 1 < str.Length && str[i + 1] == c && b < 255)
{
b += 1;
i++;
}
list.Add(b);
list.Add((byte)c);
}
return list.ToArray();
}
public static string Decode(byte[] bytes)
{
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < bytes.Length; i += 2)
{
stringBuilder.Append((char)bytes[i + 1], (int)bytes[i]);
}
return stringBuilder.ToString();
}
}
}