I'm developing an application using cefSharp, all is good now i need to maintain history for all browser tabs opened and closed by user and providing a option for opening closed tabs.
Is there a way to store Chromium Web Browser object into memory or database and retrieve it from there.
I've used below code to store objects into database
var objBrowserTest = (ChromiumWebBrowser)browserControl;
MemoryStream memStream = new MemoryStream();
StreamWriter sw = new StreamWriter(memStream);
sw.Write(objBrowserTest);
string sql = #"
INSERT INTO tblBrowserObj(cromObj)
VALUES(#VarBinary);
SELECT ##identity";
string connectionstring;
connectionstring = ConfigurationManager.ConnectionStrings[0].ConnectionString;
SqlConnection objConn = new SqlConnection(connectionstring);
if (objConn.State == ConnectionState.Open)
{
objConn.Close();
}
objConn.Open();
SqlCommand sqlCmd = new SqlCommand(sql, objConn);
sqlCmd.Parameters.Add("#VarBinary", SqlDbType.VarBinary, Int32.MaxValue);
sqlCmd.Parameters["#VarBinary"].Value = memStream.GetBuffer();
string strID = sqlCmd.ExecuteScalar().ToString();
if (objConn.State == ConnectionState.Open)
{
objConn.Close();
}
Table structure
CREATE TABLE [dbo].[tblBrowserObj](
[id] [int] IDENTITY(1,1) NOT NULL,
[cromObj] [varbinary](max) NULL
) ON [PRIMARY]
My problem is that the memStream.GetBuffer() always shows byte[0].
Can any one tell me how can i store and retrieve Chromium Web Browser object from memory or database, or is there another way to do this type of stuff.
1 - Read/Write from memory
From Writing to then reading from a MemoryStream I extract some steps you should follow:
Don't forget to flush after sw.Write(objBrowserTest);
You have to reset the position of the stream with memStream.Position = 0; before read.
Wrap the stream with a StreamWriter and use the ReadToEnd() method to read all bytes of the stream.
Don't use GetBuffer(), it doesn't get the content of the stream, it takes the buffer of a buffered stream.
2 - Read/Write an Object from Byte[]
When you want to serialeze and object you have 2 classes to do it DataContractSerializer (DCS) and BinaryFormatter (BF).
2.1 - Serialize
When you want to serialize to a byte[] you can use the DCS 'WriteObtect' or the BF 'Serialize'. Both methods uses an stream (your memory stream) and an object.
2.2 - Deserialize
To deserialize an stored byte[] from it, you can use the DCS ReadObject and BF Deserialize (casting to the class). Both methods argument is the Stream to read from.
What you need to do
Serialize with one
Use the memStream.ToArray() to get the byte[] to store it.
When retrieving, use a a memory stream to write the array
Tips
Use the MemoryStream constructor with a byte[] argument and then Position = 0.
This code maybe helps you:
public byte[] ObjectToBytes(Object obj)
{
try
{
using (MemoryStream memStream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(memStream, obj);
return memStream.ToArray();
}
}
catch (Exception) { } // do what you want
return null;
}
public T BytesToObject<T>(byte[] array) where T : class
{
try
{
using (MemoryStream memStream = new MemoryStream(array) { Position = 0 })
{
BinaryFormatter formatter = new BinaryFormatter();
T obj = formatter.Deserialize(memStream) as T;
return obj;
}
}
catch (Exception) { } // do what you want
return null;
}
Simply use sqlCmd.Parameters["#VarBinary"].Value = ObjectToBytes(objBrowserTest ); and when retrieving use BytesToObject<ChromiumWebBrowser>(bytes);
Sources
http://www.digitalcoding.com/Code-Snippets/C-Sharp/C-Code-Snippet-Byte-array-to-object.html
How deserialize Byte array to object - Windows 8 / WP 8
https://msdn.microsoft.com/en-us/library/4abbf6k0(v=vs.110).aspx
Related
My end goal is to use protobuf-net and GZipStream in an attempt to compress a List<MyCustomType> object to store in a varbinary(max) field in SQL Server. I'm working on unit tests to understand how everything works and fits together.
Target .NET framework is 3.5.
My current process is:
Serialize the data with protobuf-net (good).
Compress the serialized data from #1 with GZipStream (good).
Convert the compressed data to a base64 string (good).
At this point, the value from step #3 will be stored in a varbinary(max) field. I have no control over this. The steps resume with needing to take a base64 string and deserialize it to a concrete type.
Convert a base 64 string to a byte[] (good).
Decompress the data with GZipStream (good).
Deserialize the data with protobuf-net (bad).
Can someone assist with why the call to Serializer.Deserialize<string> returns null? I'm stuck on this one and hopefully a fresh set of eyes will help.
FWIW, I tried another version of this using List<T> where T is a custom class I created and I Deserialize<> still returns null.
FWIW 2, data.txt is a 4MB plaintext file residing on my C:.
[Test]
public void ForStackOverflow()
{
string data = "hi, my name is...";
//string data = File.ReadAllText(#"C:\Temp\data.txt");
string serializedBase64;
using (MemoryStream protobuf = new MemoryStream())
{
Serializer.Serialize(protobuf, data);
using (MemoryStream compressed = new MemoryStream())
{
using (GZipStream gzip = new GZipStream(compressed, CompressionMode.Compress))
{
byte[] s = protobuf.ToArray();
gzip.Write(s, 0, s.Length);
gzip.Close();
}
serializedBase64 = Convert.ToBase64String(compressed.ToArray());
}
}
byte[] base64byteArray = Convert.FromBase64String(serializedBase64);
using (MemoryStream base64Stream = new MemoryStream(base64byteArray))
{
using (GZipStream gzip = new GZipStream(base64Stream, CompressionMode.Decompress))
{
using (MemoryStream plainText = new MemoryStream())
{
byte[] buffer = new byte[4096];
int read;
while ((read = gzip.Read(buffer, 0, buffer.Length)) > 0)
{
plainText.Write(buffer, 0, read);
}
// why does this call to Deserialize return null?
string deserialized = Serializer.Deserialize<string>(plainText);
Assert.IsNotNull(deserialized);
Assert.AreEqual(data, deserialized);
}
}
}
}
Because you didn't rewind plainText after writing to it. Actually, that entire Stream is unnecessary - this works:
using (MemoryStream base64Stream = new MemoryStream(base64byteArray))
{
using (GZipStream gzip = new GZipStream(
base64Stream, CompressionMode.Decompress))
{
string deserialized = Serializer.Deserialize<string>(gzip);
Assert.IsNotNull(deserialized);
Assert.AreEqual(data, deserialized);
}
}
Likewise, this should work for the serialize:
using (MemoryStream compressed = new MemoryStream())
{
using (GZipStream gzip = new GZipStream(
compressed, CompressionMode.Compress, true))
{
Serializer.Serialize(gzip, data);
}
serializedBase64 = Convert.ToBase64String(
compressed.GetBuffer(), 0, (int)compressed.Length);
}
I faced this error while deserialization a custom object
I am trying to insert a collection of custom class into sql database & retrieve it the insertion going well but retrieving the data & deserialize give me this error
My code sample:
private void InsertObject()
{
ReceiptCollection items = SqlDataRepository.ReceiptProvider.GetAll();
string connectionString = "my connection";
System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(connectionString);
string sql = "INSERT INTO [dbo].[LogHeader]([MasterObject]) VALUES (#MasterObject)";
BinaryFormatter binaryFormatter = new BinaryFormatter();
MemoryStream memoryStream = new MemoryStream();
binaryFormatter.Serialize(memoryStream, items);
using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(sql, connection))
{
byte[] bytes = new byte[memoryStream.Length];
memoryStream.Write(bytes, 0, bytes.Length);
connection.Open();
cmd.Parameters.AddWithValue("#MasterObject", bytes);
cmd.ExecuteNonQuery();
}
}
private void RetrieveObjects()
{
string connectionString = "my connection";
System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(connectionString);
string sql = "Select MasterObject From [dbo].[LogHeader] WHERE LogHeaderID=2";
using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(sql, connection))
{
connection.Open();
byte[] bytes = (byte[])cmd.ExecuteScalar();
BinaryFormatter binaryFormatter = new BinaryFormatter();
MemoryStream memoryStream = new MemoryStream(bytes);
memoryStream.Position = 0;
ReceiptCollection items = (ReceiptCollection)binaryFormatter.Deserialize(memoryStream); // the error happened here
}
}
I was facing the same problem in the serialization and deserialization of a custom class. Everywhere I looked around, they have the same code marked as the solution (as your code presented on the top) but I couldn't make it run correctly. All I was recieving after the memoryStream.Write() method, was an array of zeroes. I changed my code and got it to work.
What I did was (implemented in your code):
BinaryFormatter binaryFormatter = new BinaryFormatter();
MemoryStream memoryStream = new MemoryStream();
binaryFormatter.Serialize(memoryStream, items);
using (System.Data.SqlClient.SqlCommand cmd = new System.Data.SqlClient.SqlCommand(sql, connection))
{
byte[] bytes = new byte[memoryStream.Capacity];
bytes = memoryStream.GetBuffer();
connection.Open();
cmd.Parameters.AddWithValue("#MasterObject", bytes);
cmd.ExecuteNonQuery();
}
This is for sending a byte array to the data base. For retrieving it, I did the following:
connection.Open();
byte[] bytes = (byte[])cmd.ExecuteScalar();
BinaryFormatter binaryFormatter = new BinaryFormatter();
using (MemoryStream memoryStream = new MemoryStream(bytes))
{
memoryStream.Position = 0;
ReceiptCollection items = (ReceiptCollection)binaryFormatter.Deserialize(memoryStream);
}
Try it! It really worked for me.
Start by checking what actually got stored in that column, and also check if the column's type is varbinary or similar. The error suggests that the serialized object's data stream got badly corrupted or truncated. If the row/column does not contain a long "hexstring", then there's a write problem with inserting/updating and search further there.
I am using CSVReader in my project for reading .csv files in windows service.
we pass the .csv file to CSVReader for processing the file and it was working fine.
But recently we decided to save the csv file to Database table and read it from there.
when a user submits an csv file for processing , our aspx page will read the csv file
and converts it to byte array and saves it to database.
and the service will read the table and picks up the byte array and converts it to Filestream.
This stream is passed to CSVReader for further work.
Now it throws error for the last row last column.
Its happening only after saving and reading from Database.
I am getting the following error.
No idea how to fix this.
"The CSV appears to be corrupt near record '9' field '3 at position '494'. Current raw data : '
Hear is the code
Converting file to Byte Array .....
try
{
fs = new FileStream(filepath, FileMode.Open);
fsbuffer = new byte[fs.Length];
fs.Read(fsbuffer, 0, (int)fs.Length);
}
Reading from DB to Byte Array ......
myobject.FileByteArray = ObjectToByteArray(row);
public byte[] ObjectToByteArray(DataRow row)
{
if (row["fileBytearray"] == null)
return null;
try
{
BinaryFormatter bf = new BinaryFormatter();
System.IO.MemoryStream ms = new System.IO.MemoryStream();
bf.Serialize(ms, row["fileBytearray"]);
return ms.ToArray();
}
}
Stream fileStream = new MemoryStream(myobject.FileByteArray)
using (CsvReader csv =
new CsvReader(new StreamReader(fileStream, System.Text.Encoding.UTF7), hasHeader, ','))
I haven't been able to recreate your issue, so instead, as, without seeing the save and load from beginning to end, I'll suggest trying the following for retrieval:
public MemoryStream LoadReportData(int rowId)
{
MemoryStream stream = new MemoryStream();
using (BinaryWriter writer = new BinaryWriter(stream))
{
using (DbConnection connection = db.CreateConnection())
{
DbCommand selectCommand = "SELECT CSVData FROM YourTable WHERE Id = #rowId";
selectCommand.Connection = connection;
db.AddInParameter(selectCommand, "#rowId", DbType.Int32, rowId);
connection.Open();
using (IDataReader reader = selectCommand.ExecuteReader(CommandBehavior.SequentialAccess))
{
while (reader.Read())
{
int startIndex = 0;
int bufferSize = 8192;
byte[] buffer = new byte[bufferSize];
long retVal = reader.GetBytes(0, startIndex, buffer, 0, bufferSize);
while (retVal == bufferSize)
{
writer.Write(buffer);
writer.Flush();
startIndex += bufferSize;
retVal = reader.GetBytes(0, startIndex, buffer, 0, bufferSize);
}
writer.Write(buffer, 0, (int)retVal);
}
}
}
}
return stream;
}
You'll need to replace the selectCommand sql and parameters with whatever sql you are using to return the data.
This method uses a SqlDataReader to sequentially read bytes from the appropriate row (identified by rowId in my example) and column (called CSVData in my example) which should avoid any truncation issues on the way out (it could be that your DataTable object is only returning the first n bytes). The MemoryStream object could be used to resave the CSV file to the file system for testing, or fed straight into your CSVReader.
If you can post your Save method (where you actually persist the data to the database) then we can check that too to make sure that truncation isn't happening there, either.
One other suggestion I can make right now involves your loading the file into a byte array. If you are going to load the file in one go, then you can simply replace:
try
{
fs = new FileStream(filepath, FileMode.Open);
fsbuffer = new byte[fs.Length];
fs.Read(fsbuffer, 0, (int)fs.Length);
}
with
byte[] fileBytes = File.ReadAllBytes(filepath);
I'm trying to output an image to the output stream through an HttpHandler but it keeps throwing an ArgumentException. I've googled the issue and tried so many things but I still couldn't fix the problem. Anyway, here's the code:
public void ProcessRequest(HttpContext context)
{
Int32 imageId = context.Request.QueryString["id"] != null ?
Convert.ToInt32(context.Request.QueryString["id"]) : default(Int32);
if (imageId != 0)
{
//context.Response.ContentType = "image/jpeg";
Byte[] imageData = this._imageInfoManager.GetTradeMarkImage(imageId);
using (MemoryStream ms = new MemoryStream(imageData, 0, imageData.Length))
{
using (Image image = Image.FromStream(ms, true, true)) //this line throws
{
image.Save(context.Response.OutputStream, ImageFormat.Jpeg);
}
}
}
throw new ArgumentException("Image could not be found.");
}
Note that the imageData byte array is not empty and the memory stream is being filled up correctly. Any thoughts?
UPDATE:
Here's the code for GetTradeMarkImage... Note that the images are stored in the an SQL Server database in the image format.
public Byte[] GetTradeMarkImage(Int32 id)
{
object result = DB.ExecuteScalar(SqlConstants.SqlProcedures.Request_GetImageById, id);
if (result != null)
{
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, result);
return ms.ToArray();
}
}
return null;
}
Okay, now you've posted the GetTradeMarkImage code, that's almost certainly the problem:
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, result);
return ms.ToArray();
}
Why would you expect the value of BinaryFormatter to be a valid image stream? It's not clear what's in your database (a BLOB?) nor what the execution-time type of result is here (which you should find out by debugging) but you shouldn't be using BinaryFormatter here. I suspect you just want to get the raw data out of the database, and put that into the byte array.
If you're lucky, you may just be able to cast result to byte[] to start with. (I don't know what ExecuteScalar does with blobs, and this obviously isn't the "normal" ExecuteScalar method anyway). Otherwise, you may need to use an alternative approach, opening a DataReader and getting the value that way.
I want to make a binary serialize of an object and the result to save it in a database.
Person person = new Person();
person.Name = "something";
MemoryStream memorystream = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(memorystream, person);
How can I transform memorystream in a string type to be saved in database, and after this to be able to deserialize the object?
What you're really asking for is a safe way of representing arbitrary binary data as text and then converting it back again. The fact that it stores a serialized object is irrelevant.
The answer is almost to use Base 64 (e.g. Convert.ToBase64String and Convert.FromBase64String). Do not use Encoding.UTF8.GetString or anything similar - your binary data is not encoded text data, and shouldn't be treated as such.
However, does your database not have a data type for binary data? Check for BLOB, IMAGE and BINARY types...
Here's the sample. TData must be marked [Serializable] and all fields type also.
private static TData DeserializeFromString<TData>(string settings)
{
byte[] b = Convert.FromBase64String(settings);
using (var stream = new MemoryStream(b))
{
var formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
return (TData)formatter.Deserialize(stream);
}
}
private static string SerializeToString<TData>(TData settings)
{
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, settings);
stream.Flush();
stream.Position = 0;
return Convert.ToBase64String(stream.ToArray());
}
}
//-------write to database-------------------------
Person person = new Person();
person.name = "Firstnm Lastnm";
MemoryStream memorystream = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(memorystream, person);
byte[] yourBytesToDb = memorystream.ToArray();
//here you write yourBytesToDb to database
//----------read from database---------------------
//here you read from database binary data into yourBytesFromDb
MemoryStream memorystreamd = new MemoryStream(yourBytesFromDb);
BinaryFormatter bfd = new BinaryFormatter();
Person deserializedperson = bfd.Deserialize(memorystreamd) as Person;
I used something like this
MemoryStream memoryStream = new MemoryStream();
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(memoryStream, Person);
memoryStream.Flush();
memoryStream.Position = 0;
string value = Convert.ToBase64String(memoryStream.ToArray());
Basically, don't save the data as string to the database, there are blob fields available to store binary data.
If you really need to have the data as string, you'll need to convert your byte[] to a string using base64 encoding, and to grab the byte[] from a string use decoding.
Have you not looked into converting the memorystream into a base64hex string to be put into the database?
byte[] mStream = memorystream.ToArray();
string sConvertdHex = System.Convert.ToBase64String(mStream)
Then you can dump the contents sConvertdHex to the database. To deserialize it you need to do the reverse
byte[] mData = System.Convert.FromBase64String(...)
then deserialize mData back to your object.