gpt4 book ai didi

c# - 为什么 resourceReader.GetResourceData 返回偏移 4 的类型 "ResourceTypeCode.Stream"的数据

转载 作者:太空狗 更新时间:2023-10-30 01:17:07 25 4
gpt4 key购买 nike

在我的函数 GetAssemblyResourceStream(下面的代码)中,我使用“assembly.GetManifestResourceStream”和“resourceReader.GetResourceData”从 Dll 中读取资源。

当我从资源的字节数组设置内存流时,我必须包含 4 个字节的偏移量:

const int OFFSET = 4;
resStream = new MemoryStream(data, OFFSET, data.Length - OFFSET);

偏移的原因是什么?它从哪里来?

引用:MSDN ResourceReader Class 末尾的示例

此外:我制作了一个测试应用程序以更好地了解资源。该应用程序显示了我遇到的偏移问题。我的小测试应用程序位于 Github (VS 2015)

更新 2015-10-05 10h28 由于答案非常少,我怀疑存在错误和/或未记录的行为。我在 Connect.Microsoft.com 报告了一个错误并会看到结果。

更新 2015-10-07 我删除了这个错误。我仍然认为它没有很好的记录和/或可以被视为一个错误,但我高度怀疑他们会在不做任何事情的情况下关闭我的请求。我希望没有人会遇到我遇到的同样问题。

代码:

   // ******************************************************************
/// <summary>
/// The path separator is '/'. The path should not start with '/'.
/// </summary>
/// <param name="asm"></param>
/// <param name="path"></param>
/// <returns></returns>
public static Stream GetAssemblyResourceStream(Assembly asm, string path)
{
// Just to be sure
if (path[0] == '/')
{
path = path.Substring(1);
}

// Just to be sure
if (path.IndexOf('\\') == -1)
{
path = path.Replace('\\', '/');
}

Stream resStream = null;

string resName = asm.GetName().Name + ".g.resources"; // Ref: Thomas Levesque Answer at:
// http://stackoverflow.com/questions/2517407/enumerating-net-assembly-resources-at-runtime

using (var stream = asm.GetManifestResourceStream(resName))
{
using (var resReader = new System.Resources.ResourceReader(stream))
{
string dataType = null;
byte[] data = null;
try
{
resReader.GetResourceData(path.ToLower(), out dataType, out data);
}
catch (Exception ex)
{
DebugPrintResources(resReader);
}

if (data != null)
{
switch (dataType) // COde from
{
// Handle internally serialized string data (ResourceTypeCode members).
case "ResourceTypeCode.String":
BinaryReader reader = new BinaryReader(new MemoryStream(data));
string binData = reader.ReadString();
Console.WriteLine(" Recreated Value: {0}", binData);
break;
case "ResourceTypeCode.Int32":
Console.WriteLine(" Recreated Value: {0}", BitConverter.ToInt32(data, 0));
break;
case "ResourceTypeCode.Boolean":
Console.WriteLine(" Recreated Value: {0}", BitConverter.ToBoolean(data, 0));
break;
// .jpeg image stored as a stream.
case "ResourceTypeCode.Stream":
////const int OFFSET = 4;
////int size = BitConverter.ToInt32(data, 0);
////Bitmap value1 = new Bitmap(new MemoryStream(data, OFFSET, size));
////Console.WriteLine(" Recreated Value: {0}", value1);

const int OFFSET = 4;
resStream = new MemoryStream(data, OFFSET, data.Length - OFFSET);

break;
// Our only other type is DateTimeTZI.
default:
////// No point in deserializing data if the type is unavailable.
////if (dataType.Contains("DateTimeTZI") && loaded)
////{
//// BinaryFormatter binFmt = new BinaryFormatter();
//// object value2 = binFmt.Deserialize(new MemoryStream(data));
//// Console.WriteLine(" Recreated Value: {0}", value2);
////}
////break;
break;
}

// resStream = new MemoryStream(resData);
}
}
}

return resStream;
}

最佳答案

byte[]开头的4个字节是size后面的数据的大小。但它完全没用,因为它是 byte[] 的一部分,并且 byte[] 的大小是已知的。此外,流的内容只是一个项目,其中 4 个字节的偏移量无法用于指示第一个项目相对于后续项目的大小,因为不可能有任何项目。

看完ResourceReader.GetResourceData Method documentation : 我尝试了 BinaryReader 和 BinaryFormatter 都没有成功。我将继续以与之前相同的方式读取资源的内容(绕过大小并使用 BitConverter 直接转换为流)。

感谢“嘿你”给了我朝那个方向看的想法。

仅供引用。这是我的代码,但它可能不如它应该的那样准确......它适用于我但没有经过深入测试。只是一个开始。

// ******************************************************************
/// <summary>
/// Will load resource from any assembly that is part of the application.
/// It does not rely on Application which is specific to a (UI) frameowrk.
/// </summary>
/// <param name="uri"></param>
/// <param name="asm"></param>
/// <returns></returns>
public static Stream LoadResourceFromUri(Uri uri, Assembly asm = null)
{
Stream stream = null;

if (uri.Authority.StartsWith("application") && uri.Scheme == "pack")
{
string localPath = uri.GetComponents(UriComponents.Path, UriFormat.UriEscaped);

int indexLocalPathWithoutAssembly = localPath.IndexOf(";component/");
if (indexLocalPathWithoutAssembly == -1)
{
indexLocalPathWithoutAssembly = 0;
}
else
{
indexLocalPathWithoutAssembly += 11;
}

if (asm != null) // Take the provided assembly, do not check for the asm in the uri.
{
stream = GetAssemblyResourceStream(asm, localPath.Substring(indexLocalPathWithoutAssembly));
}
else
{
if (uri.Segments.Length > 1)
{
if (uri.Segments[0] == "/" && uri.Segments[1].EndsWith(";component/"))
{
int index = uri.Segments[1].IndexOf(";");
if (index > 0)
{
string assemblyName = uri.Segments[1].Substring(0, index);

foreach (Assembly asmIter in AppDomain.CurrentDomain.GetAssemblies())
{
if (asmIter.GetName().Name == assemblyName)
{
stream = GetAssemblyResourceStream(asmIter, localPath.Substring(indexLocalPathWithoutAssembly));
break;
}
}
}
}
}

if (stream == null)
{
asm = Assembly.GetCallingAssembly();
stream = GetAssemblyResourceStream(asm, localPath.Substring(indexLocalPathWithoutAssembly));
}
}
}
return stream;
}

// ******************************************************************
/// <summary>
/// The path separator is '/'. The path should not start with '/'.
/// </summary>
/// <param name="asm"></param>
/// <param name="path"></param>
/// <returns></returns>
public static Stream GetAssemblyResourceStream(Assembly asm, string path)
{
// Just to be sure
if (path[0] == '/')
{
path = path.Substring(1);
}

// Just to be sure
if (path.IndexOf('\\') == -1)
{
path = path.Replace('\\', '/');
}

Stream resStream = null;

string resName = asm.GetName().Name + ".g.resources"; // Ref: Thomas Levesque Answer at:
// http://stackoverflow.com/questions/2517407/enumerating-net-assembly-resources-at-runtime

using (var stream = asm.GetManifestResourceStream(resName))
{
using (var resReader = new System.Resources.ResourceReader(stream))
{
string dataType = null;
byte[] data = null;
try
{
resReader.GetResourceData(path.ToLower(), out dataType, out data);
}
catch (Exception)
{
DebugPrintResources(resReader);
}

if (data != null)
{
switch (dataType) // COde from
{
// Handle internally serialized string data (ResourceTypeCode members).
case "ResourceTypeCode.String":
BinaryReader reader = new BinaryReader(new MemoryStream(data));
string binData = reader.ReadString();
Console.WriteLine(" Recreated Value: {0}", binData);
break;
case "ResourceTypeCode.Int32":
Console.WriteLine(" Recreated Value: {0}", BitConverter.ToInt32(data, 0));
break;
case "ResourceTypeCode.Boolean":
Console.WriteLine(" Recreated Value: {0}", BitConverter.ToBoolean(data, 0));
break;
// .jpeg image stored as a stream.
case "ResourceTypeCode.Stream":
////const int OFFSET = 4;
////int size = BitConverter.ToInt32(data, 0);
////Bitmap value1 = new Bitmap(new MemoryStream(data, OFFSET, size));
////Console.WriteLine(" Recreated Value: {0}", value1);

const int OFFSET = 4;
resStream = new MemoryStream(data, OFFSET, data.Length - OFFSET);

break;
// Our only other type is DateTimeTZI.
default:
////// No point in deserializing data if the type is unavailable.
////if (dataType.Contains("DateTimeTZI") && loaded)
////{
//// BinaryFormatter binFmt = new BinaryFormatter();
//// object value2 = binFmt.Deserialize(new MemoryStream(data));
//// Console.WriteLine(" Recreated Value: {0}", value2);
////}
////break;
break;
}

// resStream = new MemoryStream(resData);
}
}
}

return resStream;
}

关于c# - 为什么 resourceReader.GetResourceData 返回偏移 4 的类型 "ResourceTypeCode.Stream"的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32891004/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com