由於遊戲使用的DBC文件包含關於遊戲中可用法術的記錄和信息。 :) (如ID,名稱,損壞等等等)Marshaling.PtrToStructure丟棄異常 - 將字節讀取到結構中
更復雜的是,字符串數據存儲在記錄之後的一個塊中。在記錄字符串數據包含偏移到字符串,(所以它不是一個真正的字符串)
我有DBC文件結構,看起來像這樣:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct SpellEntry
{
private const int MAX_EFFECT_INDEX = 3;
public uint ID;
public uint Category;
public uint Dispel;
public uint Mechanic;
public uint Attributes;
public uint AttributesEx;
public uint AttributesEx2;
public uint AttributesEx3;
public uint AttributesEx4;
public uint AttributesEx5;
public uint AttributesEx6;
public uint AttributesEx7;
public uint Stances;
public uint unk_320_2;
public uint StancesNot;
public uint unk_320_3;
public uint Targets;
public uint TargetCreatureType;
public uint RequiresSpellFocus;
public uint FacingCasterFlags;
public uint CasterAuraState;
public uint TargetAuraState;
public uint CasterAuraStateNot;
public uint TargetAuraStateNot;
public uint casterAuraSpell;
public uint targetAuraSpell;
public uint excludeCasterAuraSpell;
public uint excludeTargetAuraSpell;
public uint CastingTimeIndex;
public uint RecoveryTime;
public uint CategoryRecoveryTime;
public uint InterruptFlags;
public uint AuraInterruptFlags;
public uint ChannelInterruptFlags;
public uint procFlags;
public uint procChance;
public uint procCharges;
public uint maxLevel;
public uint baseLevel;
public uint spellLevel;
public uint DurationIndex;
public uint powerType;
public uint manaCost;
public uint manaCostPerlevel;
public uint manaPerSecond;
public uint manaPerSecondPerLevel;
public uint rangeIndex;
public float speed;
public uint modalNextSpell;
public uint StackAmount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
public uint[] Totem;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.I4)]
public int[] Reagent;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.U4)]
public uint[] ReagentCount;
public int EquippedItemClass;
public int EquippedItemSubClassMask;
public int EquippedItemInventoryTypeMask;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] Effect;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
public int[] EffectDieSides;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
public int[] EffectBaseDice;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
public float[] EffectDicePerLevel;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
public float[] EffectRealPointsPerLevel;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
public int[] EffectBasePoints;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectMechanic;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectImplicitTargetA;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectImplicitTargetB;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectRadiusIndex;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectApplyAuraName;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectAmplitude;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
public float[] EffectMultipleValue;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectChainTarget;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectItemType;
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
//public int[] EffectMiscValue;
//[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.I4)]
//public int[] EffectMiscValueB;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.U4)]
public uint[] EffectTriggerSpell;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
public float[] EffectPointsPerComboPoint;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX)]
public Flag96[] EffectSpellClassMask;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
public uint[] SpellVisual;
public uint SpellIconID;
public uint activeIconID;
public uint spellPriority;
[MarshalAs(UnmanagedType.LPStr)]
public string SpellName;
[MarshalAs(UnmanagedType.LPStr)]
public string Rank;
[MarshalAs(UnmanagedType.LPStr)]
public string Description;
[MarshalAs(UnmanagedType.LPStr)]
public string ToolTip;
public uint ManaCostPercentage;
public uint StartRecoveryCategory;
public uint StartRecoveryTime;
public uint MaxTargetLevel;
public uint SpellFamilyName;
public Flag96 SpellFamilyFlags;
public uint MaxAffectedTargets;
public uint DmgClass;
public uint PreventionType;
public uint StanceBarOrder;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_EFFECT_INDEX, ArraySubType = UnmanagedType.R4)]
public float[] DmgMultiplier;
public uint MinFactionId;
public uint MinReputation;
public uint RequiredAuraVision;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)]
public uint[] TotemCategory;
public int AreaGroupId;
public int SchoolMask;
public uint runeCostID;
public uint spellMissileID;
public uint PowerDisplayId;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.R4)]
public float[] unk_320_4;
public uint spellDescriptionVariableID;
public uint SpellDifficultyId;
}
[StructLayout(LayoutKind.Sequential)]
public struct Flag96
{
public uint DwA;
public uint DwB;
public uint DwC;
public override string ToString()
{
return string.Format("DwA: {0} - DwB: {1} - DwC: {2}", DwA, DwB, DwC);
}
}
所以,我嘗試做的是編組字節這個結構用下面的代碼:
byte[] buff = new byte[Marshal.SizeOf(typeof(Spell.SpellEntry))];
binReader.BaseStream.Seek(DBCFile.HEADER_SIZE + (index * 4 * 234), SeekOrigin.Begin);
var bytes = binReader.ReadBytes(buff.Length);
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var obj = (Spell.SpellEntry)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),typeof(Spell.SpellEntry));
handle.Free();
這使我對Marshal.PtrToStructure線的AccessViolationException。 我懷疑我的結構是無效的,不知何故,你能糾正我,還是給一個提示? 有趣的是,當我在IDE中調試時,它看起來像它正確地讀取結構,但給這個例外......怪異。
我也tryed讀入結構一個接一個,像
spell[index].ID = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
spell[index].Category = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
spell[index].Dispel = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
spell[index].Mechanic = BitConverter.ToUInt32(binReader.ReadBytes(4), 0);
這是工作的100%爲我好,但它的外觀跛腳,其很長的代碼。編組看起來更親:)所以,你的意見是什麼,編組速度比一個一個閱讀更快,如果是的話,我應該如何解決它? 感謝
編組是用於在託管代碼和非託管代碼之間編組數據,而不是提供將數據讀入結構的便捷方式。一個[BinaryReader](http://msdn.microsoft.com/en-us/library/system.io.binaryreader.aspx)在這裏是適當的。 – dtb 2010-11-22 19:53:19
是的,那是我做的另一種方式,但是在這樣的大結構上,它是正確的方法嗎? – 2010-11-22 19:59:31