Ce n'est pas comment vous déclariez en C. Si l'enregistrement dans le fichier contient une chaîne alors vous déclarez la structure similaire à:
struct Example {
int mumble; // Anything, not necessarily a string length
char text[42];
// etc...
};
La déclaration équivalente C# ressemblerait à ceci:
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
private struct Example {
public int mumble;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 42)]
public string text;
// etc...
}
Vous utiliseriez normalement BinaryReader pour lire les données. Mais il ne peut pas gérer les chaînes de cette manière directement, vous devez les lire comme un byte [] et faire la conversion de chaîne vous-même. Vous ne pouvez pas non plus profiter de la syntaxe déclarative, vous devez écrire un appel pour chaque membre de la structure.
Il existe une solution de contournement pour cela, la classe Marshal sait déjà comment convertir les structures non gérées en structures managées avec la méthode PtrToStructure(). Voici une implémentation générique, cela fonctionne pour n'importe quel type blittable. Deux versions, une version statique qui lit à partir d'un octet [] et une méthode d'instance qui a été optimisée pour lire plusieurs fois à partir d'un flux. Vous utiliseriez un FileStream ou MemoryStream avec celui-là.
using System;
using System.IO;
using System.Runtime.InteropServices;
class StructTranslator {
public static bool Read<T>(byte[] buffer, int index, ref T retval) {
if (index == buffer.Length) return false;
int size = Marshal.SizeOf(typeof(T));
if (index + size > buffer.Length) throw new IndexOutOfRangeException();
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try {
IntPtr addr = (IntPtr)((long)handle.AddrOfPinnedObject() + index);
retval = (T)Marshal.PtrToStructure(addr, typeof(T));
}
finally {
handle.Free();
}
return true;
}
public bool Read<T>(Stream stream, ref T retval) {
int size = Marshal.SizeOf(typeof(T));
if (buffer == null || size > buffer.Length) buffer = new byte[size];
int len = stream.Read(buffer, 0, size);
if (len == 0) return false;
if (len != size) throw new EndOfStreamException();
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try {
retval = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally {
handle.Free();
}
return true;
}
private byte[] buffer;
}
Non testé, espérons que cela fonctionne.
Votre code C proposé est défectueux, donc vos chances de le convertir en C# sont vouées à l'échec! –
Cela dépend. Combien d'enregistrements de données? À quel point sont-ils gros? –