I am trying to serialize an enum object within a class. Currently I am going to be using a binary reader and writer to serialize/de-serialize.
My enum is called SelectionType and has a few possible values.
In my serialize method I write the toString value of the enum object I want to save.
I then dont know what to do with the string to turn this back into an enum when I read the string. I dont really want to have a hard coded case for each possible value.
I basically want to say; SelectionType newenumobject = SelectionType.String // where string is the value read from the file.
ANy help would be greatly appreciated:
here is what I have:
public override void Serialize(Stream stream)
{
System.Diagnostics.Debug.WriteLine("in level select serialize");
using (BinaryWriter writer = new BinaryWriter(stream))
{
//Debug.WriteLine("the type is" + SelectionType.ToString());
writer.Write(SelectionType.ToString());
// Write out the full name of all the types in our stack so we can
// recreate them if needed.
//byte[] bytes = new byte[SelectionType.ToString().Length * sizeof(char)];
//System.BitConverter.GetBytes(mSlectionType);
//writer.Write(bytes, 0, bytes.Length);
}
}
public override void Deserialize(Stream stream)
{
using (BinaryReader reader = new BinaryReader(stream))
{
while (reader.BaseStream.Position < reader.BaseStream.Length)
{
// read a line from our file
string line = reader.ReadString();
// if it isn't blank, we can create a screen from it
if (!string.IsNullOrEmpty(line))
{
Debug.WriteLine("line is" + line);
Type screenType = Type.GetType(line);
//SelectionType selection = Enum.Parse(screenType, line, false);
}
}
// char[] chars = new char[bytes.Length / sizeof(char)];
//System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
//new string(chars);
}
If you care about file size and read/write speed, you should save the underlying value of the enumeration rather than converting it to a string.
// be sure to use the correct backing type for your enum (default is 32-bit int)
writer.Write((int)SelectionType);
//...
selection = (SelectionType)reader.ReadInt32()
You can just use Enum.Parse.
Here is an example: http://dotnetfiddle.net/0e1Ika
var myValue = MyEnum.Value3;
var stringRepresentation = myValue.ToString();
var intRepresentation = (int)myValue;
Console.WriteLine("String-Value: \"{0}\"", stringRepresentation);
Console.WriteLine("Int-Value: {0}", intRepresentation);
var parsedFromString = (MyEnum)Enum.Parse(typeof(MyEnum), stringRepresentation);
var parsedFromInt = (MyEnum)Enum.Parse(typeof(MyEnum), intRepresentation.ToString());
Console.WriteLine("Parsed from string: {0}", parsedFromString);
Console.WriteLine("Parsed from int: {0}", parsedFromInt);
Hope that helps.
Best regards,
Chris
ps: uh, seems #dave-bish was faster :)
if you know the type of the enum, you can use Enum.Parse
var myValue = (EnumType)Enum.Parse(typeof(EnumType), "StringValue");
[Edit]
I see you have it commented out in your example - Why didn't this work for you?
Related
I am working o a project that turns message into ascii decimal values... this side is not important, the problem is it needs to read it back so the translation is basically like this:
if (textBox1.Text.Contains("a"))
{
textBox3.Text = textBox3.Text.Replace("a", "97");
}
if (textBox1.Text.Contains("b"))
{
textBox3.Text = textBox3.Text.Replace("b", "98");
}
.
.
.
if (textBox1.Text.Contains("Ğ"))
{
textBox3.Text = textBox3.Text.Replace("Ğ", "286");
}
if (textBox1.Text.Contains("ş"))
{
textBox3.Text = textBox3.Text.Replace("ş", "351");
}
this translation works perfect.
but translating back the output is the problem.
my translating back method in a nutshell:
if (sonmesajBinary.Text.Contains("97"))
{
okunanMesaj.Text = okunanMesaj.Text.Replace("97", "a");
}
if (sonmesajBinary.Text.Contains("98"))
{
okunanMesaj.Text = okunanMesaj.Text.Replace("98", "b");
}
if (sonmesajBinary.Text.Contains("99"))
{
okunanMesaj.Text = okunanMesaj.Text.Replace("99", "c");
}
and the problem is lets say the output is 140
but it also includes "40"
so pc gets it wrong. That's my problem, and i require your kind help:).
i am kinda noob so sorry for my mistakes and i am 17 also english is not my native language.
note: ascii values might not be the real ones, these are just for example.
There are many problems with your code there. Checking Contains will return true for any number of occurrences of a character at any location. You're checking in textBox1 and replacing in textBox3. You're checking each character known to you but it is possible there are more! There are easier ways of getting the byte/int/number equivalent of your character based on the encoding of your input.
Here's a rudimentary solution based on comments following the question. You however need to read more about code pages and then encodings. This is only part of the Encrypt operation. I'm sure you can figure out how to replace the contents and later also Decrypt to usable format. Cheers! Happy coding.
static void Main(string[] args)
{
string fileContents = "";
int encryptKey = 3; // Consider getting this from args[0], etc.
using (FileStream fs = File.OpenRead(#"C:\Users\My\Desktop\testfile.txt"))
using (TextReader tr = new StreamReader(fs))
{
fileContents = tr.ReadToEnd();
}
byte[] asciiBytesOfFile = Encoding.ASCII.GetBytes(fileContents);
int[] encryptedContents = Encrypt(encryptKey, asciiBytesOfFile);
}
private static int[] Encrypt(int encryptKey, byte[] asciiBytesOfFile)
{
int[] encryptedChars = new int[asciiBytesOfFile.Length];
for (int i = 0; i < asciiBytesOfFile.Length; i++)
{
encryptedChars[i] = encryptKey ^ asciiBytesOfFile[i];
}
return encryptedChars;
}
It was fixed thanks to Tom Blodget, all I needed to do was delimit. So I added 0 to beginning of every 2 digit values:D
if (textBox1.Text.Contains("a"))
{
textBox3.Text = textBox3.Text.Replace("a", "097");
}
Getting the error that's provided in the title with the following code:
var TopScores = await osuApi.GetScoresAsync(857477);
On GetScoresAsync:
public async Task<ReadOnlyCollection<Scores>> GetScoresAsync(long b, object u = null, Mods m = 0, int limit = 50)
{
var request = CreateRequestGetScores(ApiKey, b, u, m, limit);
var response = await request.GetResponseAsync();
using (var stream = new StreamReader(response.GetResponseStream()))
{
return ParseGetScores(await new StreamReader(response.GetResponseStream()).ReadToEndAsync());
}
}
ParseGetScores:
private static ReadOnlyCollection<Scores> ParseGetScores(string jsonString)
{
IList<Scores> result = new List<Scores>();
using (var stringReader = new StringReader(jsonString))
using (var jsonReader = new JsonTextReader(stringReader))
{
while (jsonReader.Read())
{
if (jsonReader.TokenType == JsonToken.StartObject)
result.Add(new Scores(jsonReader));
}
}
return new ReadOnlyCollection<Scores>(result);
}
Somewhere here it throws this at me:
Osu.Utils.JsonReaderException: 'Could not convert string to integer: 2174837884.'
EDIT: The reason I can't pinpoint exactly where it errors is because this code is taken from a library(dll) which I can only view in it's own project form and not debug directly
Hard to say without seeing the Scores class, but Scores likely has a property, perhaps like this:
public int Score { get; set;}
and the json that you are trying to read likely has this
Scores: [{ Score: 2174837884 },{Score: 2 }, ...]
The JsonTextReader uses reflection or some other method to initialize the Scores class and when it sees that the value 2,174,837,884 is too big to fit into an int, rather than truncating the int, it is nice and throws an exception. The largest value that an int can hold in c# is 2,147,483,647.
Hopefully you can change the Scores class and make the int a long, otherwise you may have to catch this Exception and have some way to handle it.
I want to iterate through the values of a specific path and read them.
I tried this
Code updated
RegistryKey key = Registry.CurrentUser.OpenSubKey(#"Software\Microsoft\Internet Explorer\IntelliForms\Storage2", true);
var names = key.GetValueNames();
for (int i = 0; i < names.Length; i++)
{
Console.WriteLine(names[i]);
byte[] test = ObjectToByteArray(key.GetValue(names[i]));
var value = Convert.ToBase64String(test);
Console.WriteLine(value);
};
Normally the string value should be an encrypted binary.
Update: So as #Peter Lillevold suggested I had to convert the array of bytes into a string.
To do so, I created this small function to convert the object key.GetValue into an array of bytes
public static byte[] ObjectToByteArray(Object obj)
{
if (obj == null)
return null;
BinaryFormatter Binaryform = new BinaryFormatter();
MemoryStream MemStream = new MemoryStream();
Binaryform.Serialize(MemStream, obj);
return MemStream.ToArray();
}
and then converted to a string as #Peter suggested.
So after the convertion of the array of bytes it is supposed to return me a string of binary.
What I get is some weird combination of letters and digits but it is not binary.
Any help on this?
You get "System.Byte[]" because you take an instance of byte[] and calls ToString() on it. This will not convert the content of the byte array into text, for that you would use something like Convert.ToBase64String or Encoding.UTF8.GetString. More discussion on the topic in this SO question.
I'm trying to convert an object which I have in a byte[] to an object.
I've tried using this code I found online:
object byteArrayToObject(byte[] bytes)
{
try
{
MemoryStream ms = new MemoryStream(bytes);
BinaryFormatter bf = new BinaryFormatter();
//ms.Position = 0;
return bf.Deserialize(ms,null);
}
catch
{
return null;
}
}
SerializationException: "End of Stream encountered before parsing was
completed.".
I've tried it with the ms.Position = 0 line uncommented of course too...
bytes[] is only 8 bytes long, each byte isn't null.
Suggestions?
[edit]
The byte[] was written to a binary file from a c++ program using something along the lines of
void WriteToFile (std::ostream& file,T* value)
{
file.write(reinterpret_cast<char*>(value), sizeof(*T))
}
Where value may be a number of different types.
I can cast to some objects okay from the file using BitConverter, but anything BitConverter doesn't cover I can't do..
As was stated by cdhowie, you will need to manually deserialize the encoded data. Based on the limited information available, you may either want an array of objects or an object containing an array. It looks like you have a single long but there is no way to know from your code. You will need to recreate your object in its true form so take the below myLong as a simple example for a single long array. Since it was unspecified I'll assume you want a struct containing an array like:
public struct myLong {
public long[] value;
}
You could do the same thing with an array of structs, or classes with minor changes to the code posted below.
Your method will be something like this: (written in the editor)
private myLong byteArrayToObject(byte[] bytes) {
try
{
int len = sizeof(long);
myLong data = new myLong();
data.value = new long[bytes.Length / len];
int byteindex = 0;
for (int i = 0; i < data.value.Length; i++) {
data.value[i] = BitConverter.ToInt64(bytes,byteindex);
byteindex += len;
}
return data;
}
catch
{
return null;
}
}
I am converting integer number to binary and put it in a header of a data message.
For instance the first meesage that arrived, I would convert the counter to binary that take 4 bytes and had the data message, which is a reguler message containning a, b, c etc'.
Here is how I convert the counter :
//This is preparing the counter as binaryint
nCtrIn = ...;
int nCtrInNetwork = System.Net.IPAddress.HostToNetworkOrder(nCtrIn);
byte[] ArraybyteFormat = BitConverter.GetBytes(nCtrInNetwork);
Now the problem is that now in to take a nother string copy the byteFormat to the beginning of a string and in addition to add the string data.
I do that because I want only in the end to write to the file using binary writer
m_brWriter.Write(ArraybyteFormat);
m_brWriter.Flush();
You can simplify by letting the BinaryWriter directly write the int - no need to conver to byte[] first.
The other problem is writing the message, it can be done like:
m_brWriter.Write(nCounterIn);
string msg = ....; // get it as 1 big string
byte[] textData = Encoding.UTF8.GetBytes(msg);
m_brWriter.Write(textData);
Or, even easier and also easier to read back:
m_brWriter.Write(nCounterIn);
m_brWriter.Write(msg);
But note that the BinaryWriter will now put it's own lentgh-prefix in front of the string.
If it's important to write to the stream in single call you can concatenate the arrays:
var intArray = new byte[4]; // In real code assign
var stringArray = new byte[12]; // actual arrays
var concatenated = new byte[16];
intArray.CopyTo(concatenated, 0);
stringArray.CopyTo(concatenated, 4);
m_brWriter.Write(concatenated);
m_brWriter.Flush();
Did you consider writing the arrays in two calls to Write?