I'm using : boito = Serializer.DeSerializeObject("XOPC.xml"); with try catch.
so here is method :
public static ObjectToSerialize DeSerializeObject(string filename)
{
ObjectToSerialize objectToSerialize;
Stream stream = File.Open(filename, FileMode.Open);
BinaryFormatter bFormatter = new BinaryFormatter();
objectToSerialize = (ObjectToSerialize)bFormatter.Deserialize(stream);
stream.Close();
return objectToSerialize;
}
I had changed structure and it's failing to DeSerialize this file but on next step when I'm trying to serialize it again I'm getting error : "This file is using by another process" and I can't access it.
So how to stop using file after error in deserialization ?
You're not closing the stream if an exception is thrown. Use a using statement:
using (Stream stream = File.Open(filename, FileMode.Open))
{
BinaryFormatter bFormatter = new BinaryFormatter();
return (ObjectToSerialize) bFormatter.Deserialize(stream);
}
This is equivalent to disposing of the stream in a finally block.
This isn't just about deserialization - you should (almost1) always use using statements for unmanaged resources. Any explicit call to Close or Dispose (outside a Dispose implementation merely releasing composed resources) is suspicious.
1 Very occasionally you want to leave a resource open on success, but close it if something else fails. This is rare and awkward.
Related
I onced managed to create the bin-file in my project. I changed the primary key from int to Guid and moved code from Main to my class Quote. At the moment I can only add new entries in said file. If I remove it a new file(0 bytes) is created and the stream gets ArgumentException when I try to feed the file dummy-data. I am trying to use an if-loop to handle stream.Lenght == 0.
public static List<Quote> readBinaryToList() //Crashes if binfile is 0 bytes long
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(#"C:\Users\xxxxxx\Desktop\quotes.bin", FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read);
if (stream.Length == 0)
{
Quote q = new Quote(Guid.NewGuid(), "Quote dummy", false);
List<Quote> quoteList = new List<Quote>();
quoteList.Add(q);
var bformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
bformatter.Serialize(stream, quoteList);
bformatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
List<Quote> quoteListTmp = (List<Quote>)bformatter.Deserialize(stream);
return quoteList;
}
else
{
List<Quote> quoteList = (List<Quote>)formatter.Deserialize(stream);
stream.Close();
return quoteList;
}
}
As pointed out in previous answers, you must give your file stream write permissions which can be done in its constructor, then you should also set the position of the stream back to 0, you can achieve this by using the stream's Position property.
You are creating a lot of unnecessary objects that don't actually contribute to purpose of the method I have omitted these below. In doing so, setting the streams Position property to 0 is redundant but I've left it in a comment to show how its done.
Some other things to consider: Declare the file stream inside a using statement so that it is disposed when the method comes to an end this means you can omit the manual close in the else statement. Some of your code can be written more tersely, this is just a personal preference but I think it would be best to inline some of your code to remove as much noise as possible. It is also convention in C# to use PascalCase for Methods.
public static List<Quote> ReadBinaryToList(){
using(Stream stream = new FileStream(#"quotes.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite)) {
IFormatter formatter = new BinaryFormatter();
if (stream.Length == 0) {
List<Quote> quoteList = new List<Quote> {new Quote(Guid.NewGuid(), "Quote dummy", false)};
formatter.Serialize(stream, quoteList);
//stream.Position = 0;
return quoteList;
}
else return (List<Quote>)formatter.Deserialize(stream);
}
}
The file is being opened as readonly, serializing to the file will require write permissions.
Stream stream = new FileStream(#"C:\temp\quotes.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
The stream should also be returned to the beginning before making any attempts to deserialize from it.
stream.Seek(0, SeekOrigin.Begin);
FileStreams have a single "head" where all read and write operations take places. As a new stream is being written, the head is always at the end and any attempt to read from the end will fail. Some streams (e.g. NetworkStream) behave differently and do not allow seeking at all.
Also, the initial position of the FileStream depends on how the file is opened (based on the specified FileMode). The FileMode specified in the question will result in the stream position starting at the beginning of the file, so this is not required in the else block.
And make sure that the Quote class is marked [Serializable]
in my WPF application code i got the following Warnings:
CA2202 Do not dispose objects multiple times Object 'fs' can be
disposed more than once in method
'MainWindow.TestResults_Click(object, RoutedEventArgs)'. To avoid
generating a System.ObjectDisposedException you should not call
Dispose more than one time on an object. : Lines:
429 yesMonitor MainWindow.xaml.cs 429
for code:
FileStream fs = new FileStream(System.AppDomain.CurrentDomain.BaseDirectory + "TestResult.htm", FileMode.Create);
using (fs)
{
using (StreamWriter w = new StreamWriter(fs, Encoding.UTF8))
{
w.WriteLine(GetTestResultsHtml());
}
}
what should be the reason for these warning?
Nested using statements can cause violations of the CA2202 warning. If the IDisposable resource of the nested inner using statement contains the resource of the outer using statement, the Dispose method of the nested resource releases the contained resource. When this situation occurs, the Dispose method of the outer using statement attempts to dispose its resource for a second time.
In the following example, a Stream object that is created in an outer using statement is released at the end of the inner using statement in the Dispose method of the StreamWriter object that contains the stream object. At the end of the outer using statement, the stream object is released a second time. The second release is a violation of CA2202.
using (Stream stream = new FileStream("file.txt", FileMode.OpenOrCreate))
{
using (StreamWriter writer = new StreamWriter(stream))
{
// Use the writer object...
}
}
To resolve this issue, use a try/finally block instead of the outer using statement. In the finally block, make sure that the stream resource is not null.
Stream stream = null;
try
{
stream = new FileStream("file.txt", FileMode.OpenOrCreate);
using (StreamWriter writer = new StreamWriter(stream))
{
stream = null;
// Use the writer object...
}
}
finally
{
if(stream != null)
stream.Dispose();
}
Personally in this case I would use:
public StreamWriter(
string path,
bool append
)
Initializes a new instance of the StreamWriter class for the specified
file by using the default encoding and buffer size. If the file
exists, it can be either overwritten or appended to. If the file does
not exist, this constructor creates a new file.
But there is NO good solution, see CA2202, how to solve this case
I'm using code bellow to serialize data into myObject
public static void SerializeObject(string filename, MyObject objectToSerialize)
{
Stream stream = File.Open(filename, FileMode.Create);
BinaryFormatter bformatter = new BinaryFormatter();
bformatter.Serialize(stream, objectToSerialize);
stream.Close();
}
This code works fine, but I'm having problem with deleting temporary files (here presented as parameter (filename)).
I'm assuming that problem is in this method code above, so how can I release any resource this code uses so I can delete file.
I did not have any problems deleting the file when I tried your program but I think you should be using the following:
public static void SerializeObject(string filename, MyObject objectToSerialize)
{
var stream = File.Open(filename, FileMode.Create);
BinaryFormatter bformatter = new BinaryFormatter();
bformatter.Serialize(stream, objectToSerialize);
stream.Close();
}
I am not sure that converting to a Stream a FileStream causes any issues, it probably does not anyway.
But this is even probably easier and more fool proof as it ensures that the stream gets closed properly:
public static void SerializeObject(string filename, Object objectToSerialize)
{
using (var stream = File.Open(filename, FileMode.Create))
{
BinaryFormatter bformatter = new BinaryFormatter();
bformatter.Serialize(stream, objectToSerialize);
}
}
If you find a way to reproduce your issue, let me know: as I mentioned, I could delete the file after executing your function and while still running the program, so I cannot reproduce your issue.
This question already has answers here:
CA2202, how to solve this case
(12 answers)
Closed 8 years ago.
CA2000 and CA2202 warnings have recently been the bane of my existence. What am I doing wrong here? I basically get a FileStream using File.Open and then pass it into a function that may return a new stream or may return the same stream. I then perform some more actions on my stream and then in my finally block I dispose the stream I was using if it was different.
I get two CA warnings. 2000 for fileStream in the using block and 2202 for changedStream in the finally block. What gives?
using (Stream fileStream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
Stream changedStream = null;
try
{
changedStream = someCondition ? fileStream : DoSomeActionThatMayReturnNewStream(fileStream);
DoSomeMoreStuffWithStream(changedStream);
}
finally
{
if (changedStream != null && changedStream != fileStream)
{
changedStream.Dispose();
}
}
}
Under what cases, if any, will DoSomeActionThatMayReturnNewStream dispose of the passed-in stream? If when it creates a new stream it disposes of the passed-in one (which would generally be expected), the Dispose triggered by the using block will be redundant.
It appears as though the behavior of your code might be correct if DoSomeActionThatMayReturnNewStream never disposes of the passed-in stream, but FxCop has no way of analyzing its complex and unorthodox pattern of object ownership. I would suggest that it would be better to do something like
Stream inputFile = null;
try
{
inputFile = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
DoSomeActionThatMayReturnNewStream(ref inputFile);
DoSomeMoreStuffWithStream(inputFile);
}
finally
{
if (inputFile != null)
inputFile.Dispose();
}
The DoSomeActionThatMayReturnNewStream should dispose of the old stream if it's going to open a new one. It should null the variable immediately before closing the old stream and and assign it immediately upon opening the new one. That will ensure that if an exception occurs during the method, the old stream will get disposed if and only if it hasn't been disposed before, and the new stream will get disposed if its constructor completed, even if the DoSomeActionThatMayReturnNewStream threw an exception after that [if that method calls Dispose on the new stream in case an exception gets thrown, it should null out the variable in such case].
What's wrong with the following:
using (var fileStream = System.IO.File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var changedStream = someCondition ? fileStream : DoSomeActionThatMayReturnNewStream(fileStream))
{
DoSomeMoreStuffWithStream(changedStream);
}
}
I am trying write a stream to the ram instead of a file. I tried doing this:
Stream stream = new MemoryStream();
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Serialize(stream, objectToSerialize);
stream.Close();
return stream;
But when I look at the stream after I have supposedly written to it it is saying "Length = 'stream.Length' threw an exception of type 'System.ObjectDisposedException'"
Don't close the stream before getting the data, and don't return the stream but the content of the stream:
using (Stream stream = new MemoryStream()) {
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Serialize(stream, objectToSerialize);
return stream.ToArray();
}
You're calling stream.Close(), which is exactly the same as calling Dispose() on the stream.
Just remove that line of code, and you should be fine. Basically, you need to leave the MemoryStream open when it's returned.
On a different note, depending on what you're going to do, you may also want to reset the stream's position. I suspect you'll want:
Stream stream = new MemoryStream();
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Serialize(stream, objectToSerialize);
stream.Position = 0;
return stream;
This works the same as your code, but does not Dispose() the stream (since it's no longer calling stream.Close()), and also resets it to the start position, which is often required if you want to read the object/data back out.
Don't call stream.Close (or IDisposable.Dispose()) until you're done with the stream.
You probably need to set the stream position back to start stream.Position = 0;
Make sure that you do dispose of the stream when you're done. The using statement is your friend here.
It's because you stream.Close(); the object.
You are getting the exception because you call Close(). From MSDN: Stream Class
Closes the current stream and releases any resources (such as sockets
and file handles) associated with the current stream.
You should be able to simply remove stream.Close();.