Blob列SQlite Adob??e AIR中的第一个字节是什么? Blob Sizeinfo
我已经确定了在通过Adobe AIR操作数据库时插入到任何blob字段中的随机字节序列. (从我的结果来看,它似乎始终以字节[12,…]开头,但我不确定)
我认为这是字节的sizeinfo,让我解释一下我是如何得出这个结论的. 首先我的上下文:我通过Adobe AIR(客户端)和System.data.sqlite(C#服务器端)操作sqlite数据库 使用System.data.sqlite,如果我通过Adobe AIR读取一个填充了BLOB的Sqlite数据库,我必须得到AIR开头附加的那些字节,然后我的二进制数据都很好.完善! 使用Adobe AIR,如果我尝试读取一个由System.data.Sqlite填充BLOB的sqlite数据库,数据已损坏我收到错误!显然是因为我没有AIR研究过的缺少的字节. 当然,我试图通过复制我在第一种情况下删除的一系列3个字节来添加这些字节,但之后它部分返回数据,而在图像的情况下,最后一行像素全部变为灰色,在某些图像中我有或多或少的灰色线条.因为数据对应于相同~4k大小的一系列图像,并且我从其中一个添加了3个字节,我得到了这个结果. 而Air也有时会抛出这个错误:
显然这些字节给出了大小的信息,但我真的不知道它是怎么做的!?! 我尝试添加一个长度为4k的bytearray,它往往会增加3个字节,但我尝试添加4M,最多可达5个字节. 我发现这个问题How do you convert 3 bytes into a 24 bit number in C#?,我认为这可能是如何存储大小信息. 但我仍然没有得到它…… 感谢 FluorineFX(AMF for .NET)开源项目,这里就是答案.因为在我的Adobe AIR项目中,我必须将我的air.ByteArray对象作为参数传递给sqlite Blob字段中的所有内容; AIR会将所有内容序列化为AMF,这是一种紧凑的二进制动作消息格式. Page 11 Secion 3.14 ByteArray类型 http://opensource.adobe.com/wiki/download/attachments/1114283/amf3_spec_05_05_08.pdf 该文件规定:
但不是全部,我搜索了一个AMF .NET开源项目,并创建了FluorineFX.查看代码,我发现每个AMF二进制文件都以字节TypeCode为前缀,ByteArray为12: /// <summary> /// AMF ByteArray data type. /// </summary> public const byte ByteArray = 12; 进一步搜索并再次在FluorineFX源中找到AMFReader.ReadAMF3ByteArray()和AMFWriter.WriteByteArray() 这有助于我快速构建我需要的东西: private static byte[] RemoveAMF3ByteArrayPrefixBytes(byte[] ar) { var ms = new MemoryStream(ar); var br = new BinaryReader(ms); // if first byte is AMF TypeCode for ByteArray if (br.Read() != 12) return ar; int handle = ReadAMF3IntegerData(br); bool inline = ((handle & 1) != 0); handle = handle >> 1; if (inline) { int length = handle; byte[] buffer = br.ReadBytes(length); return buffer; } return ar; } private static byte[] AddAMF3ByteArrayPrefixBytes(byte[] ar) { var ms = new MemoryStream(); var bw = new BinaryWriter(ms); bw.Write((byte)12); // AMF TypeCode for ByteArray var handle = (int)ar.Length; handle = handle << 1; handle = handle | 1; WriteAMF3IntegerData(bw,handle); bw.Write(ar); return ms.ToArray(); } /// <summary> /// Handle decoding of the variable-length representation which gives seven bits of value per serialized byte by using the high-order bit /// of each byte as a continuation flag. /// </summary> /// <returns></returns> private static int ReadAMF3IntegerData(BinaryReader br) { int acc = br.ReadByte(); if(acc < 128) return acc; else { acc = (acc & 0x7f) << 7; int tmp = br.ReadByte(); if(tmp < 128) acc = acc | tmp; else { acc = (acc | tmp & 0x7f) << 7; tmp = br.ReadByte(); if(tmp < 128) acc = acc | tmp; else { acc = (acc | tmp & 0x7f) << 8; tmp = br.ReadByte(); acc = acc | tmp; } } } //To sign extend a value from some number of bits to a greater number of bits just copy the sign bit into all the additional bits in the new format. //convert/sign extend the 29bit two's complement number to 32 bit int mask = 1 << 28; // mask int r = -(acc & mask) | acc; return r; //The following variation is not portable,but on architectures that employ an //arithmetic right-shift,maintaining the sign,it should be fast. //s = 32 - 29; //r = (x << s) >> s; } private static void WriteAMF3IntegerData(BinaryWriter bw,int value) { //Sign contraction - the high order bit of the resulting value must match every bit removed from the number //Clear 3 bits value &= 0x1fffffff; if (value < 0x80) bw.Write((byte)value); else if (value < 0x4000) { bw.Write((byte)(value >> 7 & 0x7f | 0x80)); bw.Write((byte)(value & 0x7f)); } else if (value < 0x200000) { bw.Write((byte)(value >> 14 & 0x7f | 0x80)); bw.Write((byte)(value >> 7 & 0x7f | 0x80)); bw.Write((byte)(value & 0x7f)); } else { bw.Write((byte)(value >> 22 & 0x7f | 0x80)); bw.Write((byte)(value >> 15 & 0x7f | 0x80)); bw.Write((byte)(value >> 8 & 0x7f | 0x80)); bw.Write((byte)(value & 0xff)); } } 我希望这会有助于其他人. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |