[Fork] [Fork] https://stackoverflow.com/questions/58780225/how-to-save-a-serialized-messagepack-binary-file-in-c

CSharp · Console

/Program.cs

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Formatters;
using System.IO;
using System.Data;
using System.Globalization;
using System.Reflection;
using System.Runtime.Serialization;

using MessagePack;

using NUnit.Framework; // Throws NUnit.Framework.AssertionException

//https://stackoverflow.com/questions/58780225/how-to-save-a-serialized-messagepack-binary-file-in-c
	
	[MessagePackObject]
	public struct struct_realTime
	{
		[Key(0)]
		public int indexNum { get; set; }
		[Key(1)]
		public string currentTime { get; set; }
		[Key(2)]
		public string currentType { get; set; }
	}

	public static class MessagePackExtensions
	{
		const byte Array32 = 0xdd;
		const int Array32HeaderLength = 5;
		
		public static void AppendToFile<T>(Stream stream, T item)
		{
			if (stream == null)
				throw new ArgumentNullException(nameof(stream));
			if (!stream.CanSeek)
				throw new ArgumentException("!stream.CanSeek");
			
			stream.Position = 0;
			var buffer = new byte[Array32HeaderLength];
			var read = stream.Read(buffer, 0, Array32HeaderLength);
			stream.Position = 0;
			if (read == 0)
			{
				FormatArray32Header(buffer, 1);
				stream.Write(buffer, 0, Array32HeaderLength);
			}
			else
			{
				var count = ParseArray32Header(buffer, read);
				FormatArray32Header(buffer, count + 1);
				stream.Write(buffer, 0, Array32HeaderLength);
			}
			
			stream.Position = stream.Length;
			MessagePackSerializer.Serialize(stream, item);
		}
		
		static void FormatArray32Header(byte [] buffer, uint value)
		{
			buffer[0] = Array32;
			buffer[1] = unchecked((byte)(value >> 24));
			buffer[2] = unchecked((byte)(value >> 16));
			buffer[3] = unchecked((byte)(value >> 8));
			buffer[4] = unchecked((byte)value);
		}
		
		static uint ParseArray32Header(byte [] buffer, int readCount)
		{
			if (readCount < 5 || buffer[0] != Array32)
				throw new ArgumentException("Stream was not positioned on an Array32 header.");
			int i = 1;
			//https://stackoverflow.com/questions/8241060/how-to-get-little-endian-data-from-big-endian-in-c-sharp-using-bitconverter-toin
			//https://stackoverflow.com/a/8241127 by https://stackoverflow.com/users/23354/marc-gravell
			var value = unchecked((uint)((buffer[i++] << 24) | (buffer[i++] << 16) | (buffer[i++] << 8) | buffer[i++]));
			return value;
		}
	}

    class TestClass
    {
        public static void Test()
        {
			var path = "Question58780225.bin";
			foreach (var count in new [] { 1, 2, 14, 15, 16, 17, ushort.MaxValue - 4, ushort.MaxValue + 4 })
			{
				try
				{
					File.Delete(path);
					Test(path, count);
				}
				finally
				{
					File.Delete(path);
				}
			}
		}	
	
        static void Test(string filename, int expectedNumberOfRootItemsInFile)
        {
			int innerCount = 3;

			List<struct_realTime> list_temp = new List<struct_realTime>(innerCount);

			for (int num=0; num < innerCount; num++)
			{
				list_temp.Add(new struct_realTime
							  {
								  indexNum = 1,
								  currentTime = "time",
								  currentType = "type",
							  });
			}

			Console.WriteLine("Testing: {0} repetitions of {1}", expectedNumberOfRootItemsInFile, MessagePackSerializer.ToJson(list_temp));
							  
			for (int i = 0; i < expectedNumberOfRootItemsInFile; i++)
			{
				// Append each list_temp sequentially
				using (var fileStream = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite))
				{
					MessagePackExtensions.AppendToFile(fileStream, list_temp);
				}
			}

			List<List<struct_realTime>> allItemsInFile;
			using (var fileStream = File.OpenRead(filename))
			{
				allItemsInFile = MessagePackSerializer.Deserialize<List<List<struct_realTime>>>(fileStream);
			}
			Assert.IsTrue(allItemsInFile.Count == expectedNumberOfRootItemsInFile);
			Assert.IsTrue(allItemsInFile.All(i => i.SequenceEqual(list_temp)));
			
			Console.WriteLine("   Tests passed.");
		}	
	}

	public class Program
	{
		public static void Main()
		{
			Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , GetNetCoreVersion());
			Console.WriteLine("MessagePack version: " + typeof(MessagePackSerializer).Assembly.FullName);
			Console.WriteLine();

			try
			{
				TestClass.Test();
			}
			catch (Exception ex)
			{
				Console.WriteLine("Failed with unhandled exception: ");
				Console.WriteLine(ex);
				throw;
			}
		}
		
		public static string GetNetCoreVersion()
		{
			//https://techblog.dorogin.com/how-to-detect-net-core-version-in-runtime-ecd65ad695be
			//
			var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly;
			var assemblyPath = assembly.CodeBase.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
			int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
			if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
				return assemblyPath[netCoreAppIndex + 1];
			return null;
		}
	}
;