Jump to content
  • Advertisement
Sign in to follow this  
Afr0m@n

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

This topic is 4172 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!");
                MessageBox.Show(m_Header);
                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
            //typelists.
            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.
                    NumFiles++;
                }
            }

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

            foreach (TypeList TmpList in m_TypeLists)
            {
                foreach (ListEntry TmpEntry in TmpList.Entries)
                {
                    NumTotalEntries++;

                    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;
                }
            }

            Stream.Close();
            Reader.Close();

            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);
            #endregion

            Directory.CreateDirectory(Filename);

            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. :)
                Writer.Write(TmpFile.Data);
                //Lastly, nullify the databuffer to save memory.
                TmpFile.Data = null;

                Writer.Close();
                Stream.Close();
            }

            Reader.Close();
            ArchiveStream.Close();
        }
        
        /// <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
Advertisement
            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);
break;
}
}

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
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!