Converting ImageSource to Object Throws Binary stream error - c#

I'm trying to convert/cast an image source to an object. I tried to convert to a byte prior to object.
ImageSource oImageSelectedByUser = (from ii in mySource where ii.PhotoImgStream != null select ii.PhotoImgStream).FirstOrDefault();
var oImageAsByte = await ConvertStreamtoByteAsync(oImageSelectedByUser);
var oImageAsObject = FromByteArray<object>(oImageAsByte);
private static async Task<byte[]> ConvertStreamtoByteAsync(ImageSource imageSource)
{
byte[] buffer = new byte[16 * 1024];
try
{
if (imageSource is FileImageSource)
{
FileImageSource objFileImageSource = (FileImageSource)imageSource;
string strFileName = objFileImageSource.File;
var webClient = new WebClient();
buffer = await webClient.DownloadDataTaskAsync(new Uri(strFileName));
return buffer;
}
}
catch (Exception ex)
{
buffer = null;
}
return buffer;
}
public T FromByteArray<T>(byte[] data)
{
if (data == null)
return default(T);
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream(data))
{
object obj = bf.Deserialize(ms);
return (T)obj;
}
}
When trying to convert to object, the error I get is:
Binary stream '0' does not contain a valid BinaryHeader. Possible
causes are invalid stream or object version change between
serialization and deserialization.
I wanted to ask is there a better way to do this?
Any direction/pointers appreciated.

You could modify the code like following
public T FromByteArray<T>(byte[] data)
{
if (data == null)
return default(T);
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream(data))
{
ms.Seek(0, SeekOrigin.Begin); // /rewinded the stream to the begining.
object obj = bf.Deserialize(ms);
return (T)obj;
}
}

Related

End of Stream encountered before parsing was completed session

I'm trying to serialize/deserialize a string array in c# but getting this error -
System.Runtime.Serialization.SerializationException : End of Stream
encountered before parsing was completed.
Here is my code:
void SerializeFunc(ISession session, string key, object toSerialize)
{
var binaryFormatter = new BinaryFormatter();
var memoryStream = new MemoryStream();
binaryFormatter.Serialize(memoryStream, toSerialize);
session.Set(key, memoryStream.ToArray());
memoryStream.Flush();
memoryStream.Close();
memoryStream.Dispose();
}
object DeSerializeFunc(ISession session, string key)
{
var memoryStream = new MemoryStream();
var binaryFormatter = new BinaryFormatter();
var objectBytes = session.Get(key) as byte[];
memoryStream.Write(objectBytes, 0, objectBytes.Length);
memoryStream.Seek(0, SeekOrigin.Begin);
memoryStream.Position = 0;
var valueObject = binaryFormatter.Deserialize(memoryStream); //ERROR
memoryStream.Close();
memoryStream.Dispose();
return valueObject;
}
public class CustomSession : Microsoft.AspNetCore.Http.ISession
{
Dictionary<string, object> sessionStorage = new Dictionary<string, object>();
void ISession.Set(string key, byte[] value)
{
sessionStorage[key] = value;
}
bool ISession.TryGetValue(string key, out byte[] value)
{
if (sessionStorage[key] != null)
{
value = Encoding.ASCII.GetBytes(sessionStorage[key].ToString());
return true;
}
else
{
value = null;
return false;
}
}
// remove other Interface members for simplicity..
}
var session = new CustomSession();
SerializeFunc(session, "key1", new string[] { "one", "two", "three" });
var obj = DeSerializeFunc(session, "key1"); //ERROR
What am I doing wrong here?

Error: Cannot access a closed file when converting imagefile into bytes

Whenever converting the imagefile into bytes we got an error like
cannot access a closed file
Please help me in order to overcome this
private byte[] ConvertToBytes(HttpPostedFileBase file)
{
byte[] imageBytes = null;
BinaryReader reader = new BinaryReader(file.InputStream);
imageBytes = reader.ReadBytes((int)file.ContentLength);
return imageBytes;
}
Use a BinaryReader object to return a byte array from the stream like:
byte[] fileData = null;
var binaryReader = new BinaryReader(Request.Files[0].InputStream);
fileData = binaryReader.ReadBytes(Request.Files[0].ContentLength);
In case it can help:
try
{
using (var bitmap = new System.Drawing.Bitmap(file.InputStream))
{
using (var memoryStream = new MemoryStream())
{
bitmap.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Jpeg);
return memoryStream.ToArray();
}
}
}
catch (Exception)
{
return null;
}
finally
{
postedFile.InputStream.Position = 0;
}

How to Serialize Avro to a byte array using Avro c# library?

I am looking for a way to serialize Avro to a byte array in Avro C# library. There is a link to do for Avro Java library as described in following link from Avro documentation:
https://cwiki.apache.org/confluence/display/AVRO/FAQ#FAQ-Serializingtoabytearray
Code copied from above link:
ByteArrayOutputStream out = new ByteArrayOutputStream();
BinaryEncoder encoder = EncoderFactory.get().binaryEncoder(out, null);
DatumWriter<User> writer = new SpecificDatumWriter<User>(User.getClassSchema());
writer.write(user, encoder);
encoder.flush();
out.close();
byte[] serializedBytes = out.toByteArray();
But I have not found a way to do in Avro c# library. I am basically looking for c# equivalent of above code.
You can use these methods to convert to and from an object to a byte array or vice-versa. Code extracted from https://stackoverflow.com/a/18205093/6138713
// Convert an object to a byte array
private byte[] ObjectToByteArray(Object obj)
{
if(obj == null)
return null;
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, obj);
return ms.ToArray();
}
// Convert a byte array to an Object
private Object ByteArrayToObject(byte[] arrBytes)
{
MemoryStream memStream = new MemoryStream();
BinaryFormatter binForm = new BinaryFormatter();
memStream.Write(arrBytes, 0, arrBytes.Length);
memStream.Seek(0, SeekOrigin.Begin);
Object obj = (Object) binForm.Deserialize(memStream);
return obj;
}
Maybe something as follows, I used the following code to write to a Kineses Stream
public async Task RecordAsync(ISpecificRecord record, string partitionKey)
{
using (var ms = new MemoryStream())
{
var encoder = new BinaryEncoder(ms);
var writer = new SpecificDefaultWriter(record.Schema);
writer.Write(record, encoder);
// AWS Kineses
var putRecordRequest = new PutRecordRequest
{
StreamName = _streamName,
Data = ms,
PartitionKey = partitionKey
};
await _kinesis.PutRecordAsync(putRecordRequest);
}
}
or
public byte[] Serialize(ISpecificRecord record)
{
using (var ms = new MemoryStream())
{
var encoder = new BinaryEncoder(ms);
var writer = new SpecificDefaultWriter(record.Schema);
writer.Write(record, encoder);
return ms.ToArray();
}
}

Why StringWriter.ToString return `System.Byte[]` and not the data?

UnZipFile method writes the data from inputStream to outputWriter.
Why sr.ToString() returns System.Byte[] and not the data?
using (var sr = new StringWriter())
{
UnZipFile(response.GetResponseStream(), sr);
var content = sr.ToString();
}
public static void UnZipFile(Stream inputStream, TextWriter outputWriter)
{
using (var zipStream = new ZipInputStream(inputStream))
{
ZipEntry currentEntry;
if ((currentEntry = zipStream.GetNextEntry()) != null)
{
var size = 2048;
var data = new byte[size];
while (true)
{
size = zipStream.Read(data, 0, size);
if (size > 0)
{
outputWriter.Write(data);
}
else
{
break;
}
}
}
}
}
The problem is on the line:
outputWriter.Write(data);
StringWriter.Write has no overload expecting a byte[]. Therefore, Write(Object) is called instead. And according to MSDN:
Writes the text representation of an object to the text string or stream by calling the ToString method on that object.
Calling ToString on a byte array returns System.byte[], explaining how you get that string in your StringWriter.
The reason is simple:
data is of type byte[]. There is no overload for byte[] on StringWriter so it uses the overload for object. And then calls ToString() on the boxed byte array which simply prints the type.
Your code is equivalent to this:
outputWriter.Write(data.ToString());
theateist,
Looking at the other answers here, I am going to have to agree that the reason for the "ToString()" returning System.Byte[] is because that is what you are putting into it, and everything put into the StringWriter calls it's own "ToString" method when doing so. (i.e. byte[].toString() = "System.byte[]"). In fact the whole idea is that the StringWriter is only ment for writing into a string "buffer" (StringBuilder), so in theory if your file was large enough(bigger than 2048), your output would be "System.Byte[]System.Byte[]" (etc.). Try this to deflate into a memory stream and then read from that stream, may be a better understanding of what you are looking at. (Code not tested, just example).
using (Stream ms = new MemoryStream())
{
UnZipFile(response.GetResponseStream(), ms);
string content;
ms.Position = 0;
using(StreamReader s = new StreamReader(ms))
{
content = s.ReadToEnd();
}
}
public static void UnZipFile(Stream inputStream, Stream outputWriter)
{
using (var zipStream = new ZipInputStream(inputStream))
{
ZipEntry currentEntry;
if ((currentEntry = zipStream.GetNextEntry()) != null)
{
int size = 2048;
byte[] data = new byte[size];
while (true)
{
size = zipStream.Read(data, 0, size);
if (size > 0)
{
outputWriter.Write(data);
}
else
{
break;
}
}
}
}
}
Another idea would actually be to using the endcoding to get the string
public string UnZipFile(Stream inputStream)
{
string tmp;
using(Stream zipStream = new ZipInputStream(inputStream))
{
ZipEntry currentEntry;
if(currentEntry = zipStream.GetNextEntry()) != null)
{
using(Stream ms = new MemoryStream())
{
int size = 2048;
byte[] data = new byte[size];
while(true)
{
if((size = zipStream.Read(data,0,size)) > 0)
ms.Write(data);
else
break;
}
tmp = Encoding.Default.GetString(ms.ToByteArray());
}
}
}
}
return tmp;
}
Or as one last idea, you could actually change your original code to have
outputWriter.Write(Encoding.Default.GetString(data));
Instead of
outputWriter.Write(data);
By the way, please avoid the var keyword in posts, maybe just my pet peev, but code is less readable when utilizing weak types.
StringWriter.Write:MSDN
StringWriter.ToString:MSDN

object to byte not working

I am trying to convert class to byte but not worked.
I receive a byte[] (b) with zero length . why ?
void start()
{
Item item = new Item();
item.files.Add(#"test");
byte[] b = ObjectToByteArray(item); // b will have zero length
}
[Serializable]
public class Item : ISerializable
{
public Item()
{
files = new List<string>();
Exclude = false;
CleanEmptyFolder = false;
}
public List<string> files;
public string MusicProfileName;
public bool Exclude;
#region ISerializable Members
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("files", files);
info.AddValue("MusicProfileName", MusicProfileName);
info.AddValue("Exclude", Exclude);
}
#endregion
}
public byte[] ObjectToByteArray(object _Object)
{
using (var stream = new MemoryStream())
{
// serialize object
var formatter = new BinaryFormatter();
formatter.Serialize(stream, _Object);
// get a byte array
var bytes = new byte[stream.Length];
using (BinaryReader br = new BinaryReader(stream))
{
bytes = br.ReadBytes(Convert.ToInt32(stream.Length));
}
return bytes;
}
}
You didn't reset the MemoryStream before you started to read from it. The position is at the end of the stream, so you get an empty array.
Use the ToArray method instead, it gets the entire content regardless of the current position:
public byte[] ObjectToByteArray(object _Object) {
using (var stream = new MemoryStream()) {
// serialize object
var formatter = new BinaryFormatter();
formatter.Serialize(stream, _Object);
// get a byte array
return stream.ToArray();
}
}
Try using MemoryStream.ToArray instead of trying to read from the MemoryStream with a BinaryReader:
return stream.ToArray();
The problem is that you aren't resetting the stream, so it's trying to read from the end instead of the beginning. You could also seek back to the beginning of the stream:
stream.Seek(0, SeekOrigin.Begin);

Categories