• Advertisement
Sign in to follow this  

[.net] C#: Reading non-terminated strings?

This topic is 3989 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

How on earth would I go about reading a string from a binarystream that, according to this resource looks like this; 'The IFF header is 64 bytes long. The first 60 bytes are the signature, which consists of two strings: "IFF FILE 2.5:TYPE FOLLOWED BY SIZE" " JAMIE DOORNBOS & MAXIS 1" (without the quote marks). The first string is terminated by a null byte; the second string is not. The game checks all sixty bytes to determine if it's a valid IFF file.' This seems to be nearly impossible to do in C#! 0_o Here's my current code:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Windows.Forms;

namespace DBPF.Iff
    public class IffLoader
        private string m_Header;
        private long m_RSMPOffset;
        private IffFile[] m_Files;
        private string m_ArchivePath;
        private RSMPResource m_RSMPResource;
        private TypeList[] m_TypeLists;

        public bool LoadIffFile(string FilePath)
            FileStream Stream = File.OpenRead(FilePath);
            BinaryReader Reader = new BinaryReader(Stream);
            ASCIIEncoding ASCIIEncoding = new ASCIIEncoding();
            m_ArchivePath = FilePath;

            m_Header = Encoding.Default.GetString(Reader.ReadBytes(60));

            if (!m_Header.Equals("IFF FILE 2.5:TYPE FOLLOWED BY SIZE  "))
                MessageBox.Show("Archive was not an *.iff archive!");
                return false;

            m_RSMPOffset = (long)Reader.ReadUInt32();

            Stream.Seek(m_RSMPOffset, SeekOrigin.Begin);

            m_RSMPResource = new RSMPResource();
            m_RSMPResource.Unknown = Reader.ReadUInt32();
            m_RSMPResource.Version = Reader.ReadUInt32();
            m_RSMPResource.ID = ASCIIEncoding.GetString(Reader.ReadBytes(4));
            m_RSMPResource.Size = Reader.ReadUInt32();
            m_RSMPResource.NumTypeLists = Reader.ReadUInt32();

            m_TypeLists = new TypeList[m_RSMPResource.NumTypeLists];

            int NumFiles = 0;

            //Read the information pertaining to all the typelists in the RSMP resource,
            //and then read the information pertaining to all entries in each of the
            for (int x = 0; x < m_TypeLists.Length; x++)
                m_TypeLists[x] = new TypeList();
                m_TypeLists[x].TypeCode = ASCIIEncoding.GetString(Reader.ReadBytes(4));
                m_TypeLists[x].NumEntries = Reader.ReadUInt32();
                m_TypeLists[x].Entries = new ListEntry[m_TypeLists[x].NumEntries];

                for (int y = 0; y < m_TypeLists[x].NumEntries; y++)
                    m_TypeLists[x].Entries[y] = new ListEntry();
                    m_TypeLists[x].Entries[y].Offset = BitConverter.ToInt32(Reader.ReadBytes(4), 0);
                    m_TypeLists[x].Entries[y].ID = Reader.ReadUInt16();
                    m_TypeLists[x].Entries[y].Unknown = Reader.ReadUInt16();
                    m_TypeLists[x].Entries[y].Flags = Reader.ReadUInt16();
                    m_TypeLists[x].Entries[y].NameString = Reader.ReadString();

                    //Increase the number of files for each entry, so that
                    //m_Files can be initialized to a proper length.

            m_Files = new IffFile[NumFiles];
            int NumTotalEntries = 0;

            foreach (TypeList TmpList in m_TypeLists)
                foreach (ListEntry TmpEntry in TmpList.Entries)

                    Stream.Seek(TmpEntry.Offset, SeekOrigin.Begin);

                    m_Files[NumTotalEntries] = new IffFile();
                    m_Files[NumTotalEntries].TypeCode = ASCIIEncoding.GetString(Reader.ReadBytes(4));
                    m_Files[NumTotalEntries].Size = Reader.ReadUInt32();
                    m_Files[NumTotalEntries].ID = Reader.ReadUInt16();
                    m_Files[NumTotalEntries].Flags = Reader.ReadUInt16();
                    m_Files[NumTotalEntries].Name = ASCIIEncoding.GetString(Reader.ReadBytes(64));
                    m_Files[NumTotalEntries].Offset = Stream.Position;


            return true;

        /// <summary>
        /// Extracts all the files in the currently opened archive.
        /// </summary>
        /// <param name="Filename">The name of the directory to extract to.
        ///                        Will be created if it doesn't exist.</param>
        public void UnpackArchive(string Filename)
            #region Assignments
            //Filetype extension for the current file.
            string CurrentExtension = "";

            //Filestream and reader for the archive file.
            FileStream ArchiveStream = File.OpenRead(m_ArchivePath);
            BinaryReader Reader = new BinaryReader(ArchiveStream);


            foreach (IffFile TmpFile in m_Files)
                FileStream Stream = File.Create(Filename + "\\" + TmpFile.Name + CurrentExtension);
                BinaryWriter Writer = new BinaryWriter(Stream);

                //Seek to the offset in the archive for the current file.
                ArchiveStream.Seek(TmpFile.Offset, SeekOrigin.Begin);
                //Initialize the databuffer to the size of the current file,
                //minus the size of the resourceheader.
                TmpFile.Data = new byte[TmpFile.Size - 76];
                //Read the file into the databuffer.
                TmpFile.Data = Reader.ReadBytes((int)TmpFile.Size - 76);

                //And, finally, write the databuffer into the new file. :)
                //Lastly, nullify the databuffer to save memory.
                TmpFile.Data = null;


        /// <summary>
        /// Returns all the *.iff files loaded by this loader in an array.
        /// </summary>
        public IffFile[] FileList
            get { return m_Files; }

Here's some of the things I have tried, in vain: m_Header = ASCIIEncoding.GetString(Reader.ReadBytes(60)); m_Header = Reader.ReadString() + Reader.ReadString(); m_Header = Reader.ReadString() + ASCIIEncoding.GetString(Reader.ReadBytes(24)); No matter what I do, and despite endless googling, I always seem to end up with this string (not exactly this one, but something close to it (I.E I cannot get the line termination down right or something, which makes it impossible to do an if() check on it)): "IFF FILE 2.5:TYPE FOLLOWED BY SIZE " Thanks in advance!

Share this post

Link to post
Share on other sites
            FileStream Stream = File.OpenRead("Sprites.iff");
BinaryReader reader = new BinaryReader(Stream);

byte[] header = reader.ReadBytes(60);
string header_line_1 = String.Empty, header_line_2 = String.Empty;

for (int i = 0; i < 60; i++)
if (header == 0x00)
header_line_1 = Encoding.ASCII.GetString(header, 0, i);
header_line_2 = Encoding.ASCII.GetString(header, i + 1, 59 - i);

if (!header_line_1.Equals("IFF FILE 2.5:TYPE FOLLOWED BY SIZE") || !header_line_2.Equals(" JAMIE DOORNBOS & MAXIS 1"))
throw new Exception("Not a valid IFF file!");

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement