I have a problem with deserialization Protobuf-net. I serialize a List<> but when I deserialize the List<> returned is not identical to the first. There is missing data.
I do not understand why.
I initialize my List<> in ctr
public ctr()
{
DateTime date = new DateTime(2012 , 12, 03); ;
LkVisiteurIdDTO visitid= new LkVisiteurIdDTO(10, 11, 12);
PurgeDateTimeDTO datetime= new PurgeDateTimeDTO(date, true);
ContractProtoBuf proto = new ContractProtoBuf();
for (int i = 0; i < 5; i++)
{
proto.m_Index = i + 1;
proto.m_TechnicalKey = "m_TechnicalKey" + i;
proto.m_LogicalKey = visitid;
proto.m_PurgeTime = datetime;
protoContractList.Add(proto);
}
}
public byte[] serialization()
{
MemoryStream ms = new MemoryStream();
try
{
Serializer.Serialize(ms, protoContractList);
arr = ms.ToArray();
return arr;
}
catch
{
Console.WriteLine("La sérialisation protobuf a échoué");
return null;
}
finally
{
ms.Close();
}
}
public List<ContractProtoBuf> deserialization()
{
MemoryStream ms = new MemoryStream(arr,false);
try
{
listeRetour = Serializer.Deserialize<List<ContractProtoBuf>>(ms);
return (listeRetour);
}
catch (Exception e)
{
Console.WriteLine("La désérialisation protobuf a échoué");
return null;
}
finally
{
ms.Close();
}
}
So my question is how to have same result ?
Here is my structure
[ProtoContract]
public struct ContractProtoBuf
{
[ProtoMember(1)]
public int m_Index;
[ProtoMember(2)]
public string m_TechnicalKey;
[ProtoMember(3)]
public LkVisiteurIdDTO m_LogicalKey;
[ProtoMember(4)]
public PurgeDateTimeDTO m_PurgeTime;
}
I create a list of ContractProtoBuf and I add data with values "that do not have consequence."
public ctr()
{
DateTime date = new DateTime(2012 , 12, 03); ;
for (int i = 0; i < 5; i++)
{
LkVisiteurIdDTO visitid= new LkVisiteurIdDTO(10, 11, 12);
PurgeDateTimeDTO datetime= new PurgeDateTimeDTO(date, true);
ContractProtoBuf proto = new ContractProtoBuf();
proto.m_Index = i + 1;
proto.m_TechnicalKey = "m_TechnicalKey" + i;
proto.m_LogicalKey = visitid;
proto.m_PurgeTime = datetime;
protoContractList.Add(proto);
}
}
I serialize my list that gets a Byte [] and when I deserialize the Byte [], the return list does not contain the same values in the type PurgeDateTimeDTO and LkVisiteurIdDTO .
In the return list I find the dateTime {01/01/0001 0:00:00} and visitid {0,0,0}
However m.Index and m_Technicalkey have good value
You don't show the DTOs, but if I assume that ContractProtoBuf is a class, then you are adding the same instance each time. Equally, you are adding the same visit each time. Normally, I would expect these to be different, for example:
public ctr()
{
DateTime date = new DateTime(2012 , 12, 03); ;
for (int i = 0; i < 5; i++)
{
LkVisiteurIdDTO visitid= new LkVisiteurIdDTO(10, 11, 12);
PurgeDateTimeDTO datetime= new PurgeDateTimeDTO(date, true);
ContractProtoBuf proto = new ContractProtoBuf();
proto.m_Index = i + 1;
proto.m_TechnicalKey = "m_TechnicalKey" + i;
proto.m_LogicalKey = visitid;
proto.m_PurgeTime = datetime;
protoContractList.Add(proto);
}
}
But as I say - it is impossible to say for sure without more information. If you can provide a complete (i.e. runnable) example, I'll be happy to look further.
Related
I have a 2D integer array to store x,y coordinates. I checked out a few functions to write 2D array into a file but cannot find anything that is able to read that binary file on load and push it into a new 2 dimensional integer array.
This is my world generator function which saves it to the file:
public WorldGenerator()
{
int worldSizeX = 100;
int worldSizeY = 100;
int[,] world = new int[worldSizeX*worldSizeY, 2];
Logger.log("Generating world...");
for(int x = 0; x < worldSizeX; x++)
{
for(int y = 0; y < 2; y++)
{
System.Random random = new System.Random();
int itemID = random.Next(0, 1);
world[x, y] = itemID;
}
}
FileStream fs = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/ConsoleGame/world/default.wd", FileMode.OpenOrCreate, FileAccess.Write);
BinaryWriter bw = new BinaryWriter(fs);
for (int x = 0; x < worldSizeX; x++)
{
for (int y = 0; y < 2; y++)
{
bw.Write(world[x, y]);
}
}
bw.Close();
fs.Close();
Logger.log("World generated.");
}
Any good idea that could work for reading this file in? I should get back a 2D integer array and world[0,0] should get me the itemid. I am new to c# and this would be just a basic console application.
I have also seen others answering similar questions but none of them are worked for me yet. Maybe because this save function is wrong or something else.
EDIT:
Here is how I load the file:
using (var filestream = File.Open(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/ConsoleGame/world/default.wd", FileMode.Open))
using (var binaryStream = new BinaryReader(filestream))
{
while (binaryStream.PeekChar() != -1)
{
Console.WriteLine(binaryStream.ReadInt32());
}
}
need Newtonsoft.Json
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace ConsoleApp18
{
class Program
{
static void Main(string[] args)
{
int worldSizeX = 100;
int worldSizeY = 100;
int[,] world = new int[worldSizeX * worldSizeY, 2];
System.Random random = new System.Random();
for (int x = 0; x < worldSizeX; x++)
{
for (int y = 0; y < 2; y++)
{
int itemID = random.Next(0, 2);
world[x, y] = itemID;
}
}
string json = JsonConvert.SerializeObject(world, Formatting.Indented);
System.IO.File.WriteAllText("WriteText.txt", json);
string text = System.IO.File.ReadAllText("WriteText.txt");
int[,] deserialized = JsonConvert.DeserializeObject<int[,]>(text);
//use "deserialized"
}
}
}
What you need is called "Serialization".
Start with the simple builtin binary serializer.
Serializable attribute does the magic here.
By the moment you'll realize it is not the best option, you'll be able to use something more suiting your needs, like proto-buf.
I've also changed ints to shorts in your example. I doubt you need 32 bits for each world cell, so we can save a bit of hard drive space.
[Serializable]
public class WorldState
{
public short[,] Items { get; set; }
public void Save(string filename)
{
if (filename == null) throw new ArgumentNullException(nameof(filename));
using (var file = File.Create(filename))
{
var serializer = new BinaryFormatter();
serializer.Serialize(file, this);
}
}
public static WorldState Load(string filename)
{
if (filename == null) throw new ArgumentNullException(nameof(filename));
if (!File.Exists(filename)) throw new FileNotFoundException("File not found", filename);
using (var file = File.OpenRead(filename))
{
var serializer = new BinaryFormatter();
return serializer.Deserialize(file) as WorldState;
}
}
}
public class WorldStateTests
{
[Fact]
public void CanSaveAndLoad()
{
var ws = new WorldState
{
Items = new short[,]
{
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 },
{ 1, 2, 3, 4 }
}
};
// save the world state to file. Find it and see what's inside
ws.Save("./ws.bin");
// load the world back
var loaded = WorldState.Load("./ws.bin");
// check a new world state got loaded
Assert.NotNull(loaded);
// and it still has items
Assert.NotEmpty(loaded.Items);
// and the items are the same as we saved
Assert.Equal(ws.Items, loaded.Items);
}
}
I use this function to train my DTrees object from Emgu.CV library.
public void Learn_Internal(double[][] aadMlInpFv, int[] anMlOutGt)
{
if (aadMlInpFv == null || aadMlInpFv.Length == 0) return;
try
{
//Use the first 80% of data as training sample
int trainingSampleCount = (int)(aadMlInpFv.Length * 0.8);
Matrix<Byte> varType = new Matrix<byte>(aadMlInpFv[0].Length + 1, 1);
varType.SetValue((byte)VarType.Categorical); //the data is categorical
Matrix<byte> sampleIdx = new Matrix<byte>(aadMlInpFv.Length, 1);
using (Matrix<byte> sampleRows = sampleIdx.GetRows(0, trainingSampleCount, 1))
sampleRows.SetValue(255);
//Matrix<double> trainData = new Matrix<double>(aadMlInpFv.Length, aadMlInpFv[0].Length);
Matrix<float> trainData = new Matrix<float>(aadMlInpFv.Length, aadMlInpFv[0].Length);
for (int i = 0; i < aadMlInpFv.Length; i++)
{
for (int j = 0; j < aadMlInpFv[i].Length; j++)
{
trainData[i, j] = (float)aadMlInpFv[i][j];
}
}
Matrix<int> trainClasses = new Matrix<int>(anMlOutGt);
using (TrainData td = new TrainData(trainData, DataLayoutType.RowSample, trainClasses))
{
m_oModelDTree.Train(td);
}
}
catch (Exception ex)
{
}
}
It cause an exception: System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
m_oModelDTree is an object from DTrees initialized like this:
m_oModelDTree = new DTrees()
{
MaxDepth = 8,
MinSampleCount = 10,
RegressionAccuracy = 0,
UseSurrogates = true,
MaxCategories = 15,
CVFolds = 10,
Use1SERule = true,
TruncatePrunedTree = true
};
I have implemented other classifier models like KNN, AdaBoost, etc from Emgu.CV befor like this method and all of them works except DTrees.
What was wrong with this?
EDIT:
Exception thrown in line: m_oModelDTree.Train(td);
Using OpenTK to attempt to create shaders in C#, repeatedly getting memory access violation errors. Any help would be appreciated. Here is the class I am having errors with, full code will be able to be found at https://github.com/Autodesk/synthesis/engine-research/OpenTKBuild
Error at Line 53 :
An unhandled exception of type 'System.AccessViolationException'
occurred in OpenTK.dll
Additional information: Attempted to read or write protected memory.
This is often an indication that other memory is corrupt.
Source code:
using OpenTK.Graphics.OpenGL;
namespace OpenTKbuild
{
class Shader
{
public int Program;
public Shader(string vertexPath, string fragmentPath)
{
string vertexCode, fragmentCode;
int vertex, fragment;
try
{
System.IO.FileStream vShaderFile = new System.IO.FileStream(vertexPath, System.IO.FileMode.Open);
System.IO.FileStream fShaderFile = new System.IO.FileStream(fragmentPath, System.IO.FileMode.Open);
System.IO.StreamReader vShaderRead = new System.IO.StreamReader(vShaderFile);
System.IO.StreamReader fShaderRead = new System.IO.StreamReader(fShaderFile);
vShaderFile.Close();
fShaderFile.Close();
vertexCode = vShaderRead.ToString();
fragmentCode = fShaderRead.ToString();
char[] vShaderCodeChar = vertexCode.ToCharArray();
char[] fShaderCodeChar = fragmentCode.ToCharArray();
string[] vShaderCode = new string[vShaderCodeChar.Length];
string[] fShaderCode = new string[fShaderCodeChar.Length];
for (int i = 0; i < vShaderCodeChar.Length; i++)
{
vShaderCode[i] = vShaderCodeChar[i].ToString();
}
for (int i = 0; i < vShaderCodeChar.Length; i++)
{
vShaderCode[i] = vShaderCodeChar[i].ToString();
}
int vcount = vShaderCode.Length;
int fcount = fShaderCode.Length;
vertex = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertex, 1, vShaderCode, ref vcount);
GL.CompileShader(vertex);
fragment = GL.CreateShader(ShaderType.FragmentShader);
// --------> error occurs onthe next line. when commented out, error does not persist.
GL.ShaderSource(fragment, 1, fShaderCode, ref fcount);
GL.CompileShader(fragment);
Program = GL.CreateProgram();
GL.AttachShader(Program, vertex);
GL.AttachShader(Program, fragment);
GL.LinkProgram(Program);
GL.DeleteShader(vertex);
GL.DeleteShader(fragment);
}
catch
{
throw new System.Exception("wut");
}
}
public void Use()
{
GL.UseProgram(Program);
}
}
}
I'm not sure why you convert the shader source string into a character array and then into a string array with just one character per string. But even if you do so, the length and the count parameter of GL.ShaderSource have to fit your data. At the moment, you tell OpenGL that there is one element in the array and that this element has fcount characters, which is not the case. This is then the reason why OpenGL tries to read outside of your allocated memory.
To solve your problem, I would suggest the following code:
GL.ShaderSource(vertex, 1, new string[] { vertexCode }, vertexCode.Length);
solved using the following code:
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace MeshImport
{
class Shader
{
public int ShaderProgram = 0;
public static int vertex, fragment, geometry;
public Shader() : base()
{
}
public Shader(string vertexPath, string fragmentPath, string geometryPath)
{
#region OLD
//string vertexCode = null, fragmentCode = null;
//System.IO.FileStream vShaderFile = new System.IO.FileStream(vertexPath, System.IO.FileMode.Open);
//System.IO.FileStream fShaderFile = new System.IO.FileStream(fragmentPath, System.IO.FileMode.Open);
#endregion
string vCode = null, fCode = null, gCode = null;
try
{
#region OLD
//System.IO.StreamReader vShaderRead = new System.IO.StreamReader(vShaderFile);
//System.IO.StreamReader fShaderRead = new System.IO.StreamReader(fShaderFile);
//vShaderFile.Close();
//fShaderFile.Close();
//vertexCode = vShaderRead.ToString();
//fragmentCode = fShaderRead.ToString();
#endregion
vCode = System.IO.File.ReadAllText(vertexPath);
fCode = System.IO.File.ReadAllText(fragmentPath);
gCode = System.IO.File.ReadAllText(geometryPath);
}
catch
{
System.Console.WriteLine("FILE NOT READ SUCCESSFULLY\n");
}
#region OLD
//char[] vShaderCodeChar = vertexCode.ToCharArray();
//char[] fShaderCodeChar = fragmentCode.ToCharArray();
//string[] vShaderCode = new string[vShaderCodeChar.Length];
//string[] fShaderCode = new string[fShaderCodeChar.Length];
//for (int i = 0; i < vShaderCodeChar.Length; i++)
//{
// vShaderCode[i] = vShaderCodeChar[i].ToString();
//}
//for (int i = 0; i < vShaderCodeChar.Length; i++)
//{
// vShaderCode[i] = vShaderCodeChar[i].ToString();
//}
#endregion
vertex = GL.CreateShader(ShaderType.VertexShader);
GL.CompileShader(vertex);
fragment = GL.CreateShader(ShaderType.FragmentShader);
GL.CompileShader(fragment);
geometry = GL.CreateShader(ShaderType.GeometryShaderExt);
GL.CompileShader(geometry);
compileShader(vertex, vCode);
compileShader(fragment, fCode);
compileShader(geometry, gCode);
ShaderProgram = GL.CreateProgram();
GL.AttachShader(ShaderProgram, vertex);
GL.AttachShader(ShaderProgram, fragment);
GL.LinkProgram(ShaderProgram);
string info;
GL.GetProgramInfoLog(ShaderProgram, out info);
System.Console.WriteLine(info);
GL.ProgramParameter(ShaderProgram, Version32.GeometryInputType, (int)All.Lines);
GL.ProgramParameter(ShaderProgram, Version32.GeometryOutputType, (int)All.LineStrip);
int tmp;
GL.GetInteger((GetPName)ExtGeometryShader4.MaxGeometryOutputVerticesExt, out tmp);
#region OLD
//int success;
//char[] infolog = new char[512];
//int[] vcount = null;
//int[] fcount = null;
//int nullint = 0;
//System.Text.StringBuilder sb = new System.Text.StringBuilder();
//sb.Append(infolog);
//vertex = GL.CreateShader(ShaderType.VertexShader);
//GL.CompileShader(vertex);
//GL.GetShader(vertex, ShaderParameter.CompileStatus, out success);
//if (success == 0)
//{
// GL.GetShaderInfoLog(vertex, 512, out nullint, sb);
// System.Console.WriteLine("Error: Shader : Vertex : Compilation Failed\n" + infolog);
//}
//fragment = GL.CreateShader(ShaderType.FragmentShader);
//GL.CompileShader(fragment);
//GL.GetShader(fragment, ShaderParameter.CompileStatus, out success);
//if (success == 0)
//{
// GL.GetShaderInfoLog(fragment, 512, out nullint, sb);
// System.Console.WriteLine("Error: Shader : Fragment : Compilation Failed\n" + infolog);
//}
//Program = GL.CreateProgram();
//GL.AttachShader(Program, vertex);
//GL.AttachShader(Program, fragment);
//GL.LinkProgram(Program);
//GL.DeleteShader(vertex);
//GL.DeleteShader(fragment);
#endregion
}
public void Use()
{
GL.UseProgram(ShaderProgram);
}
private void compileShader(int shader, string source)
{
GL.ShaderSource(shader, source);
GL.CompileShader(shader);
string info;
GL.GetShaderInfoLog(shader, out info);
System.Console.WriteLine(info);
int compileResult;
GL.GetShader(shader, ShaderParameter.CompileStatus, out compileResult);
if (compileResult != 1)
{
System.Console.WriteLine("CompileError : " + source);
}
}
public void cleanUp()
{
if (fragment != 0)
GL.DeleteShader(fragment);
if (vertex != 0)
GL.DeleteShader(vertex);
if (geometry != 0)
GL.DeleteShader(geometry);
}
}
}
Heres a fun problem I have.
I have a function that returns a var of items;
var Items = new { sumList = SumList, ratesList = List, sum = List.Sum() };
return Items;
From a function that is dynamic:
public override dynamic GetRates()
and I return it to a function I else where and try to apply it to my code:
dynamic res = cl.mainC.GetRates();
List<double> MashkantaSumList = res.sumList;
Now when I try to apply it, it says the object doesnt exist. But if I look in the debugger the items are happily there as a generic list or what not.
How do I resolve this?
EDIT:
as per request I'll post the full code:
//virtual
public virtual dynamic TotalMashkanta(int i, double sum, double ribit, string[] discount)
{
return 0;
}
//override
public override dynamic TotalMashkanta(int i, double sum, double ribit, string[] discount)
{
double SumTemp = sum;
double monthlyRibit = ribit / 12;
Double permPayPerMont = Financial.Pmt(monthlyRibit, i, sum, 0, DueDate.EndOfPeriod);
List<double> MashkantaList = new List<double>();
List<double> MashkantaSumList = new List<double>();
for (int j = 1; j <= i; j++)
{
MashkantaList.Add(Mashkanta(j, sum, ribit, permPayPerMont) * (1 - CalcDiscount((j / 12) + 1, discount)));
SumTemp = getSum(j, sum, ribit, permPayPerMont * -1); ;
MashkantaSumList.Add(SumTemp);
}
var K_Mashkanta = new { sumList = MashkantaSumList, ratesList = MashkantaList, sum = MashkantaList.Sum() };
return K_Mashkanta;
}
//Function that calls the results
public void GetSilukinTable(string Path, string ClientID, DAL.Client client, string partner_checked, string insurance_Amount, string Premiya_Structure_Mashkanta, string Premiya_Life_Mashkanta, string Discount_Life_Mashkanta, string Loan_Period,string Loan_EndDate, string Bank, string Loan_Interest, string Loan_Amount, string Discount_Loan, string AgentNotes, string ManID)
{
BL.CalculateLogic.Companies t = BL.CalculateLogic.Companies.כלל;
if(ManID == "211") t = BL.CalculateLogic.Companies.הפניקס;
if(ManID == "207") t = BL.CalculateLogic.Companies.הראל;
if(ManID == "206") t = BL.CalculateLogic.Companies.מנורה;
if(ManID == "208") t = BL.CalculateLogic.Companies.הכשרה;
BL.CalculateLogic cl = new BL.CalculateLogic(client, t);
DateTime LoanEnd = DateTime.Now;
int months = 0;
if (DateTime.TryParse(Loan_EndDate, out LoanEnd))
months = BL.Calculating_Companies.Company.GetMonthsBetween(DateTime.Now, LoanEnd);
else
months = Int32.Parse(Loan_Period) * 12;
string[] Discount = Discount_Loan.Split('-');
dynamic res = cl.mainC.TotalMashkanta(months, Double.Parse(Loan_Amount), Double.Parse(Loan_Interest.Trim('%')), Discount);
var MashkantaSumList = res.sumList;
List<double> MashkantaList = res.ratesList;
List<double> MashkantaSumListPartner = new List<double>();
List<double> MashkantaListPartner = new List<double>();
List<double> MashkantaListSum = res.ratesList;
}
The compiler is happy about it because dynamic is compiled and checked at run time. Whatever the problem is, the types don't match. It evaluates this at run time, so you won't see issues at compile time. (Advice: use dynamic only when you really must! Else you will have this kind of problems all the time!)
I tried your code using this and it works fine:
static dynamic GetRates()
{
List<double> SumList = new List<double>();
List<double> List = new List<double>();
var Items = new { sumList = SumList, ratesList = List, sum = List.Sum() };
return Items;
}
static void Main(string[] args)
{
dynamic res = GetRates();
List<double> MashkantaSumList = res.sumList;
}
I am trying to use Npgsql and Npgsql.EntityFramework with a geography data type. I can write data to the database, but I'm unable to retrieve it. I am not sure if this is even possible, so I would appreciate any help.
The class that represents the table looks like this:
internal class Geo
{
[Key, Column("geo_test_id")]
public int GeoId { get; set; }
[Column("geography")]
public byte[] Geography { get; set; }
}
Data insertion is done like this:
var geog1 = System.Data.Spatial.DbGeography.FromText("POINT(-118.4079 33.9434)");
var geog2 = System.Data.Spatial.DbGeography.FromText("POINT(2.5559 49.0083)");
using (var db = new Database.MyDbContext())
{
db.Geos.Add(new Database.Geo() { Geography = geog1.AsBinary() });
db.Geos.Add(new Database.Geo() { Geography = geog2.AsBinary() });
db.SaveChanges();
}
Data retrieval is done like this:
using (var db = new Database.MyDbContext())
{
var geos = from g in db.Geos
select g.Geography;
}
The problem is that I get the following error: Invalid cast from 'System.String' to 'System.Byte[]'.
I also tried saving the geography data as a string. In this case I am able to retrieve it, but I can't create a DbGeography object from text.
Any ideas?
Thanks!
UPDATE:
The changes I made to ExpectedTypeConverter class:
else if (expectedType == typeof(byte[]))
{
if (currentType == typeof(Guid))
{
return ((Guid)value).ToByteArray();
}
else if (value is Array)
{
Array valueArray = (Array)value;
int byteLength = Buffer.ByteLength(valueArray);
byte[] bytes = new byte[byteLength];
Buffer.BlockCopy(valueArray, 0, bytes, 0, byteLength);
return bytes;
}
else if (currentType == typeof(System.String)) // this part was added
{
string hex = value.ToString();
int numChars = hex.Length / 2;
byte[] bytes = new byte[numChars];
using (var sr = new StringReader(hex))
{
for (int i = 0; i < numChars; i++)
{
bytes[i] = Convert.ToByte(new string(new char[2] { (char)sr.Read(), (char)sr.Read() }), 16);
}
}
return bytes;
}
else
{
// expect InvalidCastException from this call
return Convert.ChangeType(value, expectedType);
}