/// <summary>
        /// 在指定的sheet中读取key对应条目
        /// </summary>
        /// <param name="sheetName">指定的sheet名称</param>
        /// <param name="key">要获取的条目的键</param>
        /// <returns>键对应的条目</returns>
        public byte[] GetSheetBytes(string sheetName, string key, out string sheetType)
        {
            sheetType = "";
            KeySheetData data;

            if (mKeySheets.TryGetValue(sheetName, out data))
            {
                mCachedOffsets.Clear();
                if (data.GetItemOffsets(key, mCachedOffsets))
                {
                    Stream s = data.stream;
                    if (mCachedOffsets.Count > 0)
                    {
                        s.Position = (long)mCachedOffsets[0];
                        ushort typeIndex = DatabaseStreamReader.ReadUShort(s);
                        sheetType = data.typeFinder.GetTypeName(typeIndex);
                        int    length = DatabaseStreamReader.ReadInt(s);
                        byte[] bytes  = new byte[length];
                        s.Read(bytes, 0, length);
                        return(bytes);
                    }
                }
            }
            return(null);
        }
        /// <summary>
        /// 根据xml名称从数据库中获取该xml定义的数据
        /// </summary>
        /// <param name="xmlName">xml名称</param>
        /// <returns>该xml中的二进制数据</returns>
        public byte[] GetXMLBytes(string xmlName, out string xmlType)
        {
            xmlType = "";
            if (string.IsNullOrEmpty(xmlName))
            {
                return(null);
            }
            DataInfo info;

            if (!mDataInfos.TryGetValue(xmlName, out info))
            {
                return(null);
            }
            info.usedTimes++;
            Stream s = info.stream;

            if (s == null)
            {
                return(null);
            }
            s.Position = (long)info.offset;
            ushort typeIndex = DatabaseStreamReader.ReadUShort(s);

            xmlType = info.typeFinder.GetTypeName(typeIndex);
            int length = DatabaseStreamReader.ReadInt(s);

            byte[] bytes = new byte[length];
            s.Read(bytes, 0, length);
            return(bytes);
        }
        /// <summary>
        /// 将一个组中所有的xml数据加到数据库中
        /// </summary>
        /// <param name="stream">该组的数据流</param>
        /// <param name="addedXmls">从组中加到数据库中的所有xml名称</param>
        /// <returns>组名称,若添加失败或该组已存在,则返回null</returns>
        public string AddToDatabase(Stream stream, IList <string> addedXmls)
        {
            stream.Position = 0L;
            byte[] buffer   = new byte[1024];
            ushort groupLen = DatabaseStreamReader.ReadUShort(stream);

            stream.Read(buffer, 0, groupLen);
            string groupKey = Encoding.UTF8.GetString(buffer, 0, groupLen);

            if (mGroupXmls.ContainsKey(groupKey))
            {
                return(null);
            }
            ushort count = DatabaseStreamReader.ReadUShort(stream);

            string[]        xmls       = new string[count];
            GroupTypeFinder typeFinder = new GroupTypeFinder("Assembly-CSharp", groupKey);

            for (ushort i = 0; i < count; i++)
            {
                ushort nameLen = DatabaseStreamReader.ReadUShort(stream);
                //Debug.LogWarning(nameLen);
                stream.Read(buffer, 0, nameLen);
                string xmlName = Encoding.UTF8.GetString(buffer, 0, nameLen);
                int    offset  = DatabaseStreamReader.ReadInt(stream);
                if (mDataInfos.ContainsKey(xmlName))
                {
                    Debug.LogError(string.Format("Xml '{0}' is already existed !", xmlName));
                    continue;
                }
                mDataInfos.Add(xmlName, new DataInfo(stream, typeFinder, offset));
                xmls[i] = xmlName;
                if (addedXmls != null)
                {
                    addedXmls.Add(xmlName);
                }
            }
            ushort typeCount = DatabaseStreamReader.ReadUShort(stream);

            string[] typeNames = new string[typeCount];
            for (uint i = 0; i < typeCount; i++)
            {
                int len = stream.ReadByte();
                stream.Read(buffer, 0, len);
                typeNames[i] = Encoding.UTF8.GetString(buffer, 0, len);
            }
            typeFinder.SetTypes(typeNames);
            mGroupXmls.Add(groupKey, xmls);
            return(groupKey);
        }
            // 根据string型id直接返回数据流,Lua层使用;
            public byte[] GetItemBytes(string key, out string sheetType)
            {
                sheetType = "";
                if (!mStrKey)
                {
                    return(null);
                }

                object          obj       = null;
                Type            type      = null;
                List <ItemData> itemDatas = null;

                if (mKeyDatas.TryGetValue(key, out itemDatas))
                {
                    for (int i = 0, imax = itemDatas.Count; i < imax; i++)
                    {
                        obj = itemDatas[i].obj;
                        if (obj != null)
                        {
                            type = itemDatas[i].type;
                            break;
                        }
                    }
                }

                while (obj == null && mActiveKeyReaders.Count > 0)
                {
                    for (int i = 0, imax = mActiveKeyReaders.Count; i < imax; i++)
                    {
                        XmlIdReader r       = mActiveKeyReaders[i];
                        bool        canRead = false;
                        while (canRead = r.MoveNext())
                        {
                            string   itemKey = r.CurrentKeyItem.Key;
                            ItemData itemData;
                            itemData.obj  = r.CurrentKeyItem.Value;
                            itemData.type = r.type;
                            if (mKeyDatas.TryGetValue(itemKey, out itemDatas))
                            {
                                itemDatas.Add(itemData);
                            }
                            else
                            {
                                itemDatas = new List <ItemData>();
                                itemDatas.Add(itemData);
                                mKeyDatas.Add(itemKey, itemDatas);
                            }
                            if (itemKey == key)
                            {
                                obj  = itemData.obj;
                                type = itemData.type;
                                break;
                            }
                            if (string.Compare(itemKey, key) > 0)
                            {
                                break;
                            }
                        }
                        if (!canRead)
                        {
                            mCachedInts.Add(i);
                        }
                        if (obj != null)
                        {
                            break;
                        }
                    }
                    for (int i = mCachedInts.Count - 1; i >= 0; i--)
                    {
                        mActiveKeyReaders.RemoveAt(mCachedInts[i]);
                    }
                    mCachedInts.Clear();
                }
                if (obj != null && type != null)
                {
                    sheetType = type.ToString();
                    MemoryStream dataStream = new MemoryStream();
                    RuntimeTypeModel.Default.SerializeWithLengthPrefix(dataStream, obj, type, ProtoBuf.PrefixStyle.Fixed32, 0);

                    dataStream.Position = 0;
                    int    length = DatabaseStreamReader.ReadInt(dataStream);
                    byte[] bytes  = new byte[length];
                    dataStream.Read(bytes, 0, length);
                    dataStream.Close();
                    return(bytes);
                }
                return(null);
            }
        /// <summary>
        /// 将一个组中所有的sheet加到数据库中
        /// </summary>
        /// <param name="stream">该组的数据流</param>
        /// <param name="addedSheets">从组中加到数据库中的所有sheet名称</param>
        /// <returns>组名称,若添加失败或该组已存在,则返回null</returns>
        public string AddToDatabase(Stream stream, IList <string> addedSheets)
        {
            stream.Position = 0L;
            byte[] buffer      = new byte[1024];
            ushort groupKeyLen = DatabaseStreamReader.ReadUShort(stream);

            stream.Read(buffer, 0, groupKeyLen);
            string groupKey = Encoding.UTF8.GetString(buffer, 0, groupKeyLen);

            if (mGroupSheets.ContainsKey(groupKey))
            {
                return(null);
            }

            ushort sheetCount = DatabaseStreamReader.ReadUShort(stream);

            int[] sheetOffsets = new int[sheetCount];
            for (ushort i = 0; i < sheetCount; i++)
            {
                sheetOffsets[i] = DatabaseStreamReader.ReadInt(stream);
            }
            string[]        sheets     = new string[sheetCount];
            GroupTypeFinder typeFinder = new GroupTypeFinder("Assembly-CSharp", groupKey);

            for (ushort i = 0; i < sheetCount; i++)
            {
                stream.Position = sheetOffsets[i];
                ushort nameLen = DatabaseStreamReader.ReadUShort(stream);
                stream.Read(buffer, 0, nameLen);
                string sheetName = Encoding.UTF8.GetString(buffer, 0, nameLen);

                uint sheetItemCount = DatabaseStreamReader.ReadUInt(stream);
                //UnityEngine.Debug.LogError("sheet name : " + sheetName + "   item count : " + sheetItemCount);
                bool strKey = (sheetItemCount & 0x80000000) != 0u;
                sheetItemCount = sheetItemCount & 0x7fffffff;

                //UnityEngine.Debug.LogError("sheet item count : " + sheetItemCount);
                //UnityEngine.Debug.LogError("str key ? " + strKey);

                bool existed = mKeySheets.ContainsKey(sheetName) || mIdSheets.ContainsKey(sheetName);
                if (strKey)
                {
                    string[] keys    = new string[sheetItemCount];
                    int[]    offsets = new int[sheetItemCount];
                    for (int j = 0; j < sheetItemCount; j++)
                    {
                        int keyLen = stream.ReadByte();
                        //UnityEngine.Debug.Log(keyLen);
                        stream.Read(buffer, 0, keyLen);
                        keys[j]    = Encoding.UTF8.GetString(buffer, 0, keyLen);
                        offsets[j] = DatabaseStreamReader.ReadInt(stream);
                        //UnityEngine.Debug.LogWarning(string.Format("key : {0}    offset : {1}", keys[j], offsets[j]));
                    }
                    if (!existed)
                    {
                        KeySheetData sheet = new KeySheetData(stream, typeFinder, (int)sheetItemCount, keys, offsets);
                        mKeySheets.Add(sheetName, sheet);
                    }
                }
                else
                {
                    uint[] ids     = new uint[sheetItemCount];
                    int[]  offsets = new int[sheetItemCount];
                    for (int j = 0; j < sheetItemCount; j++)
                    {
                        ids[j]     = (uint)DatabaseStreamReader.ReadInt(stream);
                        offsets[j] = DatabaseStreamReader.ReadInt(stream);
                        //UnityEngine.Debug.LogWarning(string.Format("id : {0}    offset : {1}", ids[j], offsets[j]));
                    }
                    if (!existed)
                    {
                        IdSheetData sheet = new IdSheetData(stream, typeFinder, (int)sheetItemCount, ids, offsets);
                        mIdSheets.Add(sheetName, sheet);
                    }
                }
                if (existed)
                {
                    Debug.LogError(string.Format("Sheet '{0}' is already existed !", sheetName));
                }
                else
                {
                    sheets[i] = sheetName;
                    if (addedSheets != null)
                    {
                        addedSheets.Add(sheetName);
                    }
                    //Debug.Log("sheet : " + sheetName);
                }
            }
            ushort typeCount = DatabaseStreamReader.ReadUShort(stream);

            string[] typeNames = new string[typeCount];
            for (uint i = 0; i < typeCount; i++)
            {
                int len = stream.ReadByte();
                stream.Read(buffer, 0, len);
                typeNames[i] = Encoding.UTF8.GetString(buffer, 0, len);
            }
            typeFinder.SetTypes(typeNames);
            mGroupSheets.Add(groupKey, sheets);
            return(groupKey);
        }
        /// <summary>
        /// 根据xml名称从数据库中获取该xml定义的数据
        /// </summary>
        /// <param name="xmlName">xml名称</param>
        /// <returns>该xml中的二进制数据</returns>
        public byte[] GetXMLBytes(string xmlName, out string xmlType)
        {
            xmlType = "";
            if (string.IsNullOrEmpty(xmlName))
            {
                return(null);
            }
            DataInfo info;

            if (!mDataInfos.TryGetValue(xmlName, out info))
            {
                return(null);
            }
            info.usedTimes++;

            byte[]       xmlBytes = null;
            StreamReader sr       = null;

            System.Xml.XmlReader xr         = null;
            MemoryStream         dataStream = new MemoryStream();
            string path = string.Format("{0}/../{1}", Application.dataPath, info.path);

            try
            {
                sr = File.OpenText(path);
                xr = System.Xml.XmlReader.Create(sr);
                Type type = info.typeFinder.GetType((ushort)info.typeIndex);
                if (type == null)
                {
                    return(null);
                }

                xmlType = info.typeFinder.GetTypeName((ushort)info.typeIndex);
                System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(type);
                object obj = serializer.Deserialize(xr);
                RuntimeTypeModel.Default.SerializeWithLengthPrefix(dataStream, obj, type, ProtoBuf.PrefixStyle.Fixed32, 0);

                dataStream.Position = 0;
                int xmlLength = DatabaseStreamReader.ReadInt(dataStream);
                xmlBytes = new byte[xmlLength];
                dataStream.Read(xmlBytes, 0, xmlLength);
            }
            catch (Exception e)
            {
                System.Xml.XmlTextReader xtr = xr as System.Xml.XmlTextReader;
                if (xtr != null)
                {
                    Debug.LogError(string.Format("Xml Parse Error At '{0}:{1},{2}'", path, xtr.LineNumber, xtr.LinePosition));
                }
                Debug.LogException(e);
            }
            if (dataStream != null)
            {
                dataStream.Close();
            }
            if (xr != null)
            {
                xr.Close();
            }
            if (sr != null)
            {
                sr.Close();
            }

            return(xmlBytes);
        }