bir yapı içine ikili dosyasını oku

oy
42

C # kullanarak ikili veri okumaya çalışıyorum. Ben okumak istiyorum dosyalardaki verilerin düzeni hakkında tüm bilgilere sahip. Ben, yığın tarafından yığın verileri okuyabilecek olduğum bir dizeye dönüştürme verilerin ilk 40 bayt alma, yani önümüzdeki 40 bayt olsun.

Verilerin en az üç biraz farklı bir sürümü olduğundan, doğrudan bir yapı içine veri okumak istiyorum. Sadece çok çok daha doğru satır satır olarak okuyarak daha hissediyor.

Ben boşuna aşağıdaki yaklaşımı ancak denedi:

StructType aStruct;
int count = Marshal.SizeOf(typeof(StructType));
byte[] readBuffer = new byte[count];
BinaryReader reader = new BinaryReader(stream);
readBuffer = reader.ReadBytes(count);
GCHandle handle = GCHandle.Alloc(readBuffer, GCHandleType.Pinned);
aStruct = (StructType) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(StructType));
handle.Free();

Dere ı dan okumaya başladı oldukları bir açılmış FileStream olduğunu. Bir olsun AccessViolationExceptiokullanırken n Marshal.PtrToStructure.

dere ben dosyanın sonuna verilerde ilgilenmiyorum çünkü okumaya çalışıyorum daha fazla bilgi içerir.

yapı aşağıdaki gibi tanımlanır:

[StructLayout(LayoutKind.Explicit)]
struct StructType
{
    [FieldOffset(0)]
    public string FileDate;
    [FieldOffset(8)]
    public string FileTime;
    [FieldOffset(16)]
    public int Id1;
    [FieldOffset(20)]
    public string Id2;
}

örnekler kod, bu soru kısaltmak için orijinal değiştirilir.

Nasıl bir yapı içine bir dosyadan ikili veri okumak ki?

Oluştur 05/08/2008 saat 15:28
kaynak kullanıcı
Diğer dillerde...                            


7 cevaplar

oy
19

Sorundur dize senin yapı içinde s. Ben bayt / kısa / int gibi türleri sıralama bir sorun olmadığını tespit; Eğer böyle bir dize olarak karmaşık bir türü içine sıralamakta gerektiğinde ancak, açıkça yönetilmeyen bir tür taklit etmek için yapı gerekir. Sen MarshalAs attrib ile yapabilirsiniz.

senin Örneğin, aşağıdaki çalışması gerekir:

[StructLayout(LayoutKind.Explicit)]
struct StructType
{
    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
    public string FileDate;

    [FieldOffset(8)]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
    public string FileTime;

    [FieldOffset(16)]
    public int Id1;

    [FieldOffset(20)]
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 66)] //Or however long Id2 is.
    public string Id2;
}
Cevap 21/08/2008 saat 20:02
kaynak kullanıcı

oy
8

İşte kullanıyorum budur.
Bu taşınabilir yürütülebilir Format okumak için benim için başarıyla çalıştı.
O kadar, genel bir fonksiyonu var Tsenin olduğunu structtürü.

public static T ByteToType<T>(BinaryReader reader)
{
    byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));

    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
    handle.Free();

    return theStructure;
}
Cevap 02/11/2010 saat 03:40
kaynak kullanıcı

oy
5

Ronnie dediği gibi, ben BinaryReader kullanmak ve tek tek her alanını okumuştu. Bu bilgi ile makaleye link bulamazsa, ancak yapı az 30-40 kadar alanları içeriyorsa her alanını okumak için BinaryReader kullanarak, Marshal.PtrToStruct daha hızlı olabileceği gözlenmiştir ediyor. Onu bulduğumda makaleye link göndeririz.

: Makalenin linki yer almaktadır http://www.codeproject.com/Articles/10750/Fast-Binary-File-Reading-with-C

yapılar bir dizi dizme zaman alanlar * dizi uzunluğu gibi saha sayısı düşünebiliriz çünkü PtrToStruct, daha çabuk Üst yandan kazanır.

Cevap 06/05/2010 saat 02:04
kaynak kullanıcı

oy
3

Ben BinaryFormatter kullanarak hiç şans vardı, ben tam dosyasının içeriğini maçları tam bir yapı olması gerekiyor sanırım. Bir bytebuffer içine akımının bir kısmının okuma ve daha sonra kullanarak dönüştürme çözümü ile gitti bu yüzden sonunda yine dosya içeriğinin çok ilgilenen olmadığını anladı

Encoding.ASCII.GetString()

dizeleri ve

BitConverter.ToInt32()

tamsayılar için.

Daha sonra dosyanın daha ayrıştırmak mümkün olması gerekir ancak bu sürümü için ben satır kod sadece bir çift ile kaçtı.

Cevap 06/08/2008 saat 10:03
kaynak kullanıcı

oy
1

Ben senin koduyla herhangi bir sorun görmüyorum.

Sadece kafamdan, bunu elle ne denerseniz? çalışıyor mu?

BinaryReader reader = new BinaryReader(stream);
StructType o = new StructType();
o.FileDate = Encoding.ASCII.GetString(reader.ReadBytes(8));
o.FileTime = Encoding.ASCII.GetString(reader.ReadBytes(8));
...
...
...

Ayrıca denemek

StructType o = new StructType();
byte[] buffer = new byte[Marshal.SizeOf(typeof(StructType))];
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
Marshal.StructureToPtr(o, handle.AddrOfPinnedObject(), false);
handle.Free();

Daha sonra kullanmak [] tampon hala AccessViolation istisna almak olmadığını görmek yerine FileStream veri okuyabilir, sizin BinaryReader içinde.

Ben BinaryFormatter kullanarak hiç şans vardı, ben tam dosyasının içeriğini maçları tam bir yapı olması gerekiyor sanırım.

Yani BinaryFormatter kendi veri formatını, sizinkiyle tamamen uyumsuz vardır, mantıklı.

Cevap 05/08/2008 saat 16:31
kaynak kullanıcı

oy
0

yapılar doğruca Okuma kötüdür - Birçok C programı nedeniyle farklı bayt sıralamaların, alanların farklı derleyici uygulamaları, paketleme, kelime büyüklüğünün üzerinde düştü .......

Sen byte serialising ve deserialising bayt en iyisidir. İstediğiniz ya da sadece BinaryReader alışması eğer şeyler yapı kullanın.

Cevap 23/09/2008 saat 22:43
kaynak kullanıcı

oy
0

Bunu dene:

using (FileStream stream = new FileStream(fileName, FileMode.Open))
{
    BinaryFormatter formatter = new BinaryFormatter();
    StructType aStruct = (StructType)formatter.Deserialize(filestream);
}
Cevap 05/08/2008 saat 15:56
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more