Patcher.IO.CustomBinaryReader.ReadStringZeroTerminated C# (CSharp) Method

ReadStringZeroTerminated() public method

public ReadStringZeroTerminated ( ) : string
return string
        public string ReadStringZeroTerminated()
        {
            StringBuilder sb = null;
            int i = 0;
            byte b;
            while ((b = ReadByte()) != '\0')
            {
                internalBuffer[i++] = b;
                if (i >= internalBufferSize)
                {
                    // Create string builder
                    // The final string length will be at least internalBufferSize, so lets double it
                    if (sb == null)
                        sb = new StringBuilder(internalBufferSize * 2);

                    // Append part of the string
                    sb.Append(InternalBufferToString(i));
                    i = 0;
                }
            }
            if (sb != null)
            {
                // Append the rest if anything in the buffer
                if (i > 0)
                    sb.Append(InternalBufferToString(i));
                // Return string builder
                return sb.ToString();
            }
            else
            {
                // Return string from internal buffer
                return InternalBufferToString(i);
            }
        }

Usage Example

        protected override void DoOpen()
        {
            using (CustomBinaryReader reader = new CustomBinaryReader(new FileStream(ArchivePath, FileMode.Open, FileAccess.Read)))
            {
                uint signature = reader.ReadUInt32();
                if (signature != 0x415342)
                {
                    throw new InvalidDataException("File is not BSA");
                }

                uint version = reader.ReadUInt32();
                uint folderOffset = reader.ReadUInt32();
                flags = (ArchiveFlags)reader.ReadUInt32();
                uint folderCount = reader.ReadUInt32();
                uint fileCount = reader.ReadUInt32();
                uint totalFolderNameLength = reader.ReadUInt32();
                uint totalFileNameLength = reader.ReadUInt32();
                uint fileExtensions = reader.ReadUInt32();

                FolderInfo[] folders = new FolderInfo[(int)folderCount];

                // Read folders
                reader.BaseStream.Position = folderOffset;
                for (int i = 0; i < folderCount; i++)
                {
                    ulong hash = reader.ReadUInt64();
                    uint count = reader.ReadUInt32();
                    uint offset = reader.ReadUInt32() - totalFileNameLength;
                    folders[i] = new FolderInfo()
                    {
                        FileCount = count,
                        ContentOffset = offset
                    };
                }

                // Read folder content (name and files)
                foreach (var folder in folders)
                {
                    byte folderNameLength = reader.ReadByte();
                    folder.Path = Encoding.UTF8.GetString(reader.ReadBytes(folderNameLength - 1));
                    byte zero = reader.ReadByte();

                    folder.Files = new FileInfo[folder.FileCount];
                    for (int i = 0; i < folder.FileCount; i++)
                    {
                        ulong hash = reader.ReadUInt64();
                        uint size = reader.ReadUInt32();

                        bool compressed = flags.HasFlag(ArchiveFlags.DefaultCompressed);
                        if ((size & 0xf0000000) != 0)
                        {
                            size &= 0xfffffff;
                            compressed = !compressed;
                        }

                        uint offset = reader.ReadUInt32();
                        folder.Files[i] = new FileInfo()
                        {
                            Size = size,
                            DataOffset = offset,
                            IsCompressed = compressed
                        };
                    }
                }

                long total = fileCount;
                long loaded = 0;
                string filename = Path.GetFileName(ArchivePath);

                // Read file names
                foreach (var folder in folders)
                {
                    foreach (var file in folder.Files)
                    {
                        file.Filename = reader.ReadStringZeroTerminated();
                        loaded++;
                    }
                }

                // Convert to nested sorted dictionary for fast search
                for (int i = 0; i < folderCount; i++)
                {
                    var files = new SortedDictionary<string, FileInfo>();
                    for (int j = 0; j < folders[i].FileCount; j++)
                    {
                        files.Add(folders[i].Files[j].Filename, folders[i].Files[j]);
                    }
                    sorted.Add(folders[i].Path, files);
                }

                return;
            }
        }