I am still learning C#. I come from a Delphi and C past.

I am used to being to create flat data files of of records. Example:

// Sample Delphi code...

type
  SectorRecord = Record
  iIdx    : integer;
  iCoordX : integer;
  iCoordY : integer;
  sName   : String[60];
end;

  .....

myFile : File of SectorRecord;
sr     : SectorRecord;

AssignFile(myFile,'someFileName.DAT');
Reset(myFile);
Read(myFile,sr);
CloseFile(myFile);

Is there just nothing like this in C#?

Everything I look up concerning file access in C# points me back to text files I have to parse through, or creating a database (and all the support coding that goes along with that).

Am I just not understanding the terminology and not looking up the right word for this type of file?

Thanks in advance.

Dani AI

Generated

Short answer: yes — C#/.NET can do the same "file of record" pattern Delphi gives (fixed-size records with random access). The common approaches are: BinaryReader/BinaryWriter for manual reads/writes; marshalling a fixed-layout struct to bytes (StructLayout + Marshal or Span/MemoryMarshal) for true fixed-size records that you can Seek to by index; memory-mapped files for very large datasets; or a compact binary serializer (protobuf/MessagePack) when portability/versioning matter. is right that XML is an option but is often too verbose; is right that object serialization also works. The snippet below shows a straightforward struct->bytes approach that reproduces fixed-size records and supports random access.

using System;
using System.IO;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct SectorRecord
{
    public int iIdx;
    public int iCoordX;
    public int iCoordY;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 60)]
    public string sName; // fixed 60 bytes (Ansi)
}

static class RecordIO
{
    public static byte[] ToBytes<T>(T item) where T : struct
    {
        int size = Marshal.SizeOf(typeof(T));
        byte[] arr = new byte[size];
        IntPtr ptr = Marshal.AllocHGlobal(size);
        try { Marshal.StructureToPtr(item, ptr, false); Marshal.Copy(ptr, arr, 0, size); }
        finally { Marshal.FreeHGlobal(ptr); }
        return arr;
    }

    public static T FromBytes<T>(byte[] arr) where T : struct
    {
        IntPtr ptr = Marshal.AllocHGlobal(arr.Length);
        try { Marshal.Copy(arr, 0, ptr, arr.Length); return (T)Marshal.PtrToStructure(ptr, typeof(T)); }
        finally { Marshal.FreeHGlobal(ptr); }
    }
}

// write/read example (random-access by record index)
int recSize = Marshal.SizeOf(typeof(SectorRecord));
var rec = new SectorRecord { iIdx = 1, iCoordX = 10, iCoordY = 20, sName = "SectorA" };

using (var fs = new FileStream("data.dat", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
    long index = 0;
    fs.Seek(index * recSize, SeekOrigin.Begin);
    fs.Write(RecordIO.ToBytes(rec), 0, recSize);

    fs.Seek(index * recSize, SeekOrigin.Begin);
    byte[] buf = new byte[recSize];
    fs.Read(buf, 0, recSize);
    var readRec = RecordIO.FromBytes<SectorRecord>(buf);
}

Notes and cautions: specify Pack and CharSet (or use explicit byte arrays) to avoid unexpected padding or multibyte chars; marshalling uses the host endianness — if byte-for-byte compatibility with other platforms/languages (or with Delphi short-strings) is required, define the exact byte layout (Delphi String[60] is a short-string with a leading length byte, so emulate that format explicitly). For huge files, MemoryMappedFile or Span<T>/MemoryMarshal give better throughput and fewer allocations. Avoid legacy BinaryFormatter for new code; for version-tolerant, cross-language formats consider protobuf-net or MessagePack.

This preserves Delphi-style fixed records and random access without leaving managed C#. It also makes the on-disk layout explicit so compatibility with existing DAT files can be achieved.

Recommended Answers

All 5 Replies

Perhaps you should take a look at XML files.
You can both import and export them into a datatable for manipulation.

Zinderin, take a look at the binary reader and binary writer. That's the closest you'll get to being able to achieve what you want.

Zinderin, take a look at the binary reader and binary writer. That's the closest you'll get to being able to achieve what you want.

Thanks guys ... both of you. :)

XML just doesn't do it if you have 100,000s on 100,000s records. Especially with small records (the XML overhead becomes bigger than the actual data). And I don't even want to get into the "deer in the headlights" look you get from a small business when you start talking about changing their data formats. They've already been through the pain ... they don't want to change anything.

And the binaryReader/Writer just seems insanely clumsy to me (I did continue to search after posting my question here and found the binaryReader/Writer). Granted its likely just my inexperience with the language.

I guess its back to C for this stuff. Or waiting til I understand C# well enough to build an API in C and link it in to my C# code. :(

It is just crazy to me that they don't support this. Especially given how static C# is, and considering its ancestry.

Thanks again.

You can actually serialise objects into Binary. Then write them to your binary file.

It's pretty straight forward and with a little helper/base class is actually quite quick and easy to understand. (About 4 lines of code each way)

You can actually serialise objects into Binary. Then write them to your binary file.

It's pretty straight forward and with a little helper/base class is actually quite quick and easy to understand. (About 4 lines of code each way)

Thanks Ketsuekiame ... clearly it is my inexperience then. I have more to learn. :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.