I'm new to Streams and in the program i'm developing requires reading data from a hex file.
File=level.dat
The code im using:
FileStream fs;
private void Form1_Load(object sender, EventArgs e)
{
Main("PCWorld\\level.dat");
NbtTree nbtTree = new NbtTree();
Stream s = fs;
Stream destStream = new MemoryStream();
nbtTree.ReadFrom(s);
nbtTree.WriteTo(destStream);
}
void Main():
void Main(string filename)
{
// From MSDN Forums, slightly modified by me
try
{
string fileName = filename;
// Create random data to write to the file.
byte[] dataArray = new byte[100000];
new Random().NextBytes(dataArray);
using (FileStream
fileStream = new FileStream(fileName, FileMode.Create))
{
// Write the data to the file, byte by byte.
for (int i = 0; i < dataArray.Length; i++)
{
fileStream.WriteByte(dataArray[i]);
}
// Set the stream position to the beginning of the file.
fileStream.Seek(0, SeekOrigin.Begin);
// Read and verify the data.
for (int i = 0; i < fileStream.Length; i++)
{
if (dataArray[i] != fileStream.ReadByte())
{
MessageBox.Show("Failed to load " + fileName + " (MCPC.dll)\n\nReason: Failed to read bytes\nResult: Close();\nSoloution: Try again and/or tell DMP9 Software", "Error");
Close();
return;
}
fs = fileStream;
}
}
}
catch (OutOfMemoryException ex)
{
MessageBox.Show("Failed to load NBT++.PC.exe\n\nReason: Out of memory (System.OutOfMemoryException: " + ex.Message + ")\nResult: Close();\nSoloution: Your PC Does not have enough RAM to run NBT++", "Error");
Close();
}
}
My program has a reference of Substrate (https://code.google.com/p/substrate-minecraft/downloads/list) and that does most of the work, but its my code giving
the "Cannot access a closed file"
Any help?
Thanks...
Your problem is in:
Stream s = fs;
The fs filestream is closed in your Main method (using statement disposes the filestream). To fix this you should open a new filestream to read from the file:
Stream s = new FileStream("PCWorld\\level.dat", FileMode.Read);
When using
using (FileStream fileStream = new FileStream(fileName, FileMode.Create))
{...}
you are closing this filestream when you go out scope. So you have to re-open file to read
http://msdn.microsoft.com/en-us/library/yh598w02.aspx
Related
Below this code is my Add button on my windows form. When i tried to click it without adding any image & without path also, error occur that i mentioned below these code. I want to fix this exception, even if the user doesn't add image or file path it doesn't get exception. I know its been asked many times but their exception in their code is different so i'm a bit confused there. Thank you
private void btn_add_Click(object sender, EventArgs e)
{
byte[] image = null;
var stream = new FileStream(this.txt_path.Text, FileMode.Open, FileAccess.Read);
var read = new BinaryReader(stream);
image = read.ReadBytes((int)stream.Length);
using (var con = SQLConnection.GetConnection())
{
if (string.IsNullOrEmpty(cbox_supplier.Text) || string.IsNullOrEmpty(txt_code.Text) || string.IsNullOrEmpty(txt_item.Text) || string.IsNullOrEmpty(txt_quantity.Text) || string.IsNullOrEmpty(txt_cost.Text) || string.IsNullOrEmpty(txt_path.Text))
{
MetroMessageBox.Show(this, "Please input the Required Fields", "System Message:", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
else
{
var selectCommand = new SqlCommand("Insert into employee_product (Image, Supplier, Codeitem, Itemdescription, Date, Quantity, Unitcost) Values (#Image, #Supplier, #Codeitem, #Itemdescription, #Date, #Quantity, #Unitcost)",con);
selectCommand.Parameters.AddWithValue("#Image", image);
selectCommand.Parameters.AddWithValue("#Supplier", cbox_supplier.Text);
selectCommand.Parameters.AddWithValue("#Codeitem", txt_code.Text.Trim());
selectCommand.Parameters.AddWithValue("#Itemdescription", txt_item.Text.Trim());
selectCommand.Parameters.AddWithValue("#Date", txt_date.Text.Trim());
selectCommand.Parameters.AddWithValue("#Quantity", txt_quantity.Text.Trim());
selectCommand.Parameters.AddWithValue("#Unitcost", txt_cost.Text.Trim());
selectCommand.ExecuteNonQuery();
MessageBox.Show("Added successfully", "SIMS", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
txt_path.Clear();
pictureBox1.Image = null;
txt_code.Clear();
txt_item.Clear();
txt_quantity.Clear();
txt_cost.Clear();
_view.AddingProduct();
}
}
}
private void btn_upload_Click(object sender, EventArgs e)
{
OpenFileDialog opnfd = new OpenFileDialog();
opnfd.Filter = "Image Files (*.jpg;*.jpeg;.*.gif;*.png;)|*.jpg;*.jpeg;.*.png;*.gif";
opnfd.Title = "Select Item";
if (opnfd.ShowDialog() == DialogResult.OK)
{
var path = opnfd.FileName.ToString();
txt_path.Text = path;
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.Image = Image.FromFile(opnfd.FileName);
}
}
// This is where System Argument Exception occur
byte[] image = null;
-----> var stream = new FileStream(this.txt_path.Text, FileMode.Open, FileAccess.Read);
var read = new BinaryReader(stream);
image = read.ReadBytes((int)stream.Length);
You can either pre-check the file exists:
if (File.Exists(txt_path.Text))
{
var stream = new FileStream(this.txt_path.Text, FileMode.Open, FileAccess.Read);
var read = new BinaryReader(stream);
image = read.ReadBytes((int)stream.Length);
// The rest of your code
}
or catch the error when it occurs:
try
{
var stream = new FileStream(this.txt_path.Text, FileMode.Open, FileAccess.Read);
var read = new BinaryReader(stream);
image = read.ReadBytes((int)stream.Length);
// The rest of your code
}
catch
{
// Creating filestream object failed.
}
As you asked about wrapping the FileStream in a using statement:
When you open a FileStream you need to explicitly close it and make sure you've disposed of it to remove the open file handle - so that other applications can access the file. You can either do this by calling Close and Dispose or you can just wrap the object in a using statement that will automatically call close and dispose for you.
using (var stream = new FileStream(this.txt_path.Text, FileMode.Open, FileAccess.Read))
{
using (var read = new BinaryReader(stream))
{
image = read.ReadByres((int)stream.Length);
} // BinaryReader is Closed and Disposed here
} // FileStream is Closed and Disposed here
The FileStream and BinaryReader objects (stream and read) only exist up to the point where the using statements closing brace } is.
I have an application A that generates a text file for tracing.
While, an application B needs read the same text file and attach in a mailmessage.
But I get the following error, when application B try read the text file:
IOException: The process cannot access the file 'filename' because it
is being used by another process
Any suggestions ? Maybe better use for FileMode and FileAccess?
Application A
if (File.Exists(nFile2)) File.Delete(nFile2);
traceFile2 = File.Open(nFile2, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
if (traceFile2 != null)
{
var twt2 = new TextWriterTraceListener(traceFile2);
// http://www.helixoft.com/blog/archives/20
try
{
if (twt2.Writer is StreamWriter)
{
(twt2.Writer as StreamWriter).AutoFlush = true;
}
}
catch { }
var indiceTraceFile2 = Trace.Listeners.Add(twt2);
System.Diagnostics.Trace.WriteLine("INICIO: " + DateTime.Now.ToString());
Application B
using (FileStream fileStream = File.Open(f, FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
{
var messageAttachment = new Attachment(fileStream, Path.GetFileName(f));
msgMail.Attachments.Add(messageAttachment);
}
You need to make sure that both the service and the reader open the log file non-exclusively. Notice line 2 of App A and Line 1 of App B
Application A:
if (File.Exists(nFile2))
File.Delete(nFile2);
traceFile2 = new FileStream(nFile2, FileMode.Open, FileAccess.Write, FileShare.ReadWrite);
if (traceFile2 != null)
{
var twt2 = new TextWriterTraceListener(traceFile2);
// http://www.helixoft.com/blog/archives/20
try
{
if (twt2.Writer is StreamWriter)
{
(twt2.Writer as StreamWriter).AutoFlush = true;
}
}
catch { }
var indiceTraceFile2 = Trace.Listeners.Add(twt2);
System.Diagnostics.Trace.WriteLine("INICIO: " + DateTime.Now.ToString());
and Application B:
using (FileStream fileStream = new FileStream(f, FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
{
var messageAttachment = new Attachment(fileStream, Path.GetFileName(f));
msgMail.Attachments.Add(messageAttachment);
}
Of course you can read and write from/to the same file at the same time (by different threads/processes).
Here is a sample code. Just see how FileStream is created.
string fname = "a.txt";
//WRITER
Task.Factory.StartNew(() =>
{
var f = new FileStream(fname, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
var s = new StreamWriter(f);
long l = 0;
while (true)
{
s.WriteLine(l++);
s.Flush();
Task.Delay(1000).Wait();
}
});
//READER
Task.Factory.StartNew(() =>
{
Task.Delay(1000).Wait();
var f = new FileStream(fname, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
var s = new StreamReader(f);
while (true)
{
var line = s.ReadLine();
if (line == null) { Task.Delay(100).Wait(); continue; };
Console.WriteLine("> " + line + " <");
}
});
It seems that you are not using the Dispose() and Close() methods of StreamWriter class to release the file.
You need to release control of the file from Program A. Try closing or disposing the streamwriter when you finish.
Or you might attempt using as is described in the answer to this question: Releasing access to files
I am trying to make a simple software which stores data in a TXT log file.
This is my code
FileStream fs = null;
StreamWriter fw = null;
try
{
fs= new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.Desktop)+"/textme.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
fw = new StreamWriter(fs);
fw.Write("sadadasdsadsadsadas");
for (int i = 0; i < AnimalShelter.AnimalList.Count; i++)
{
fw.WriteLine("<chipNr>" + AnimalShelter.AnimalList[i].ChipRegistrationNumber + "<chipNr>");
Console.WriteLine("<chipNr>" + AnimalShelter.AnimalList[i].ChipRegistrationNumber + "<chipNr>");
}
}
catch(IOException)
{
MessageBox.Show("ERROR THROWN");
}
finally
{
if (fs!= null) fs.Close();
// if (fw != null) fw.Close();
}
What I achieved is: the file gets created, but nothing gets written in it.
I checked a lot of posts but I could not find any particular help.
Adding a call to Flush the stream works. This is because you are wrapping the FileStream. StreamWriter will write to the FileStream, but you need to indicate when to send the Stream to the actual file. Also, you can exchange your try finally with a using:
try
{
using (var fs = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.Desktop)+"/textme.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (var fw = new StreamWriter(fs))
{
fw.Write("sadadasdsadsadsadas");
for (int i = 0; i < AnimalShelter.AnimalList.Count; i++)
{
fw.WriteLine("<chipNr>" + AnimalShelter.AnimalList[i].ChipRegistrationNumber + "<chipNr>");
Console.WriteLine("<chipNr>" + AnimalShelter.AnimalList[i].ChipRegistrationNumber + "<chipNr>");
}
fw.Flush(); // Added
}
}
}
catch(IOException)
{
MessageBox.Show("ERROR THROWN");
}
Enclose your StreamWriter in an using block to be sure that everything is correctly closed at the end of the file usage, also I don't think you need to create a FileStream for this to work.
try
{
string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "textme.txt")
using(fw = new StreamWriter(fileName, true))
{
......
}
}
catch(IOException)
{
MessageBox.Show("ERROR THROWN");
}
Note that the StreamWriter has a constructor that accepts two parameters, the name of the file to create/open and a flag to indicate that the file should be opened in append mode or overwritten
See StreamWriter docs
Always use using (as mentioned already) and you won't run into problems (or have to think about it)...
using (FileStream fs = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/textme.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
using (StreamWriter fw = new StreamWriter(fs))
{
fw2.Write("sadadasdsadsadsadas");
}
(also you could have closed the writer instead of filestream which should've worked)
The problem is as I far as I can tell...
FileStream.Close is actually Stream.Close - and that calls Dispose but it ain't virtual, so does some general cleanup.
FileStream.Dispose which is called implicitly when you use using - does specific Flush and then Close/Dispose - so does proper specific cleanup.
You can avoid any of that via using as that is generally recommended pattern (and frankly never got me into any of these)
Indeed, Flush() is the answer; however, I would use File.WriteAllLines() instead.
try
{
var fileName = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)+"/textme.txt";
var lines = AnimalShelter.AnimalList.Select(o=> "<chipNr>" + o.ChipRegistrationNumber + "</chipNr>");
File.WriteAllLines(fileName, lines);
foreach(var line in lines)
Console.WriteLine(line);
}
catch(IOException)
{
MessageBox.Show("ERROR THROWN");
}
Try using this - just replace the array:
try
{
using (Stream fs = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/textme.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (StreamWriter sw = new StreamWriter(fs))
{
int[] test = new int[] { 0, 12, 23, 46 };
sw.Write("sadadasdsadsadsadas");
for (int i = 0; i < test.Length; i++)
{
sw.WriteLine("<chipNr>" + test[i] + "<chipNr>");
Console.WriteLine("<chipNr>" + test[i] + "<chipNr>");
}
sw.Close();
}
fs.Close();
}
}
catch (IOException)
{
MessageBox.Show("ERROR THROWN");
}
I am trying to read from the isolated storage if the file is exist it will delete the whole file and directories before recreating the file.
Then if the file does not exist it will create the file and directories.
Below is my code: I got a error of opertion not permitted on isolated storage at write file
int indexQues;
string rate;
string[] queSplit;
string[] rateSplit;
private void saveBtn_Click(object sender, RoutedEventArgs e)
{
indexQues = queListPicker.SelectedIndex;
rate = rateListPicker.SelectedItem.ToString();
IsolatedStorageFile myStore = IsolatedStorageFile.GetUserStoreForApplication();
try
{
//For question
StreamReader readFileQue = new StreamReader(new IsolatedStorageFileStream("SettingFolder\\queSetting.txt", FileMode.Open, myStore));
//For passing rate
StreamReader readFileRate = new StreamReader(new IsolatedStorageFileStream("SettingFolder\\queSetting.txt", FileMode.Open, myStore));
String queText = readFileQue.ReadLine();
queSplit = queText.Split(new char[] { '^' });
String rateText = readFileRate.ReadLine();
rateSplit = rateText.Split(new char[] { '^' });
readFileQue.Close();
readFileRate.Close();
int noOfQueInDB = queSplit.Count();
int noOfRateInDB = rateSplit.Count();
MessageBox.Show(noOfQueInDB.ToString());
//if (noOfQueInDB == 2)
//{
myStore.DeleteFile("SettingFolder\\queSetting.txt");
myStore.DeleteFile("SettingFolder\\rateSetting.txt");
myStore.DeleteDirectory("SettingFolder");
MessageBox.Show("Deleted all");
myStore.CreateDirectory("SettingFolder");
//Retrieve the content of "noOfQues"
//And write it into queSetting.txt
StreamWriter writeFile = new StreamWriter(new IsolatedStorageFileStream("SettingFolder\\queSetting.txt", FileMode.Create, myStore));
writeFile.Write(indexQues);
// writeFile.Write("^" + indexQues);
writeFile.Close();
StreamWriter writeFile1 = new StreamWriter(new IsolatedStorageFileStream("SettingFolder\\rateSetting.txt", FileMode.Create, myStore));
writeFile1.Write(rate);
writeFile1.Close();
MessageBox.Show("Setting Saved");
MessageBox.Show(indexQues.ToString());
MessageBox.Show(rate);
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
//}
}
catch (Exception)
{
myStore.CreateDirectory("SettingFolder");
//Retrieve the content of "noOfQues"
//And write it into queSetting.txt
// ****
// **** The following line throws an exception
// ****
StreamWriter writeFile = new StreamWriter(new IsolatedStorageFileStream("SettingFolder\\queSetting.txt", FileMode.Create, myStore));
writeFile.Write(indexQues);
// writeFile.Write("^" + indexQues);
writeFile.Close();
StreamWriter writeFile1 = new StreamWriter(new IsolatedStorageFileStream("SettingFolder\\rateSetting.txt", FileMode.Create, myStore));
writeFile1.Write(rate);
writeFile1.Close();
MessageBox.Show("Setting Saved");
MessageBox.Show(indexQues.ToString());
MessageBox.Show(rate);
NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
}
}
one point - this seems wrong (you open the same file twice ?):
//For question
StreamReader readFileQue = new StreamReader(new IsolatedStorageFileStream("SettingFolder\\queSetting.txt", FileMode.Open, myStore));
//For passing rate
StreamReader readFileRate = new StreamReader(new IsolatedStorageFileStream("SettingFolder\\queSetting.txt", FileMode.Open, myStore));
second point - you should use Dispose:
readFileQue.Close(); readFileQue.Dispose(); readFileQue = null;
readFileRate.Close(); readFileRate.Dispose(); readFileRate = null;
third point - user proper FileAccess when creating the files:
StreamWriter writeFile = new StreamWriter(new IsolatedStorageFileStream("SettingFolder\\rateSetting.txt",
FileMode.Create,
FileAccess.Write,
FileShare.Write,
myStore);
Hope the above helps... if not check whether the Directory is really created...
EDIT:
Are you sure the Exception is thrown from the catch-block ? IF so, then there must have happened some Exception before that - what was that Exception?
In Linux, a lot of IPC is done by appending to a file in 1 process and reading the new content from another process.
I want to do the above in Windows/.NET (Too messy to use normal IPC such as pipes). I'm appending to a file from a Python process, and I want to read the changes and ONLY the changes each time FileSystemWatcher reports an event. I do not want to read the entire file content into memory each time I'm looking for changes (the file will be huge)
Each append operation appends a row of data that starts with a unique incrementing counter (timestamp+key) and ends with a newline.
using (FileStream fs = new FileStream
(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs))
{
while (someCondition)
{
while (!sr.EndOfStream)
ProcessLinr(sr.ReadLine());
while (sr.EndOfStream)
Thread.Sleep(100);
ProcessLinr(sr.ReadLine());
}
}
}
this will help you read only appended lines
You can store the offset of the last read operation and seek the file to that offset when you get a changed file notification. An example follows:
Main method:
public static void Main(string[] args)
{
File.WriteAllLines("test.txt", new string[] { });
new Thread(() => ReadFromFile()).Start();
WriteToFile();
}
Read from file method:
private static void ReadFromFile()
{
long offset = 0;
FileSystemWatcher fsw = new FileSystemWatcher
{
Path = Environment.CurrentDirectory,
Filter = "test.txt"
};
FileStream file = File.Open(
"test.txt",
FileMode.Open,
FileAccess.Read,
FileShare.Write);
StreamReader reader = new StreamReader(file);
while (true)
{
fsw.WaitForChanged(WatcherChangeTypes.Changed);
file.Seek(offset, SeekOrigin.Begin);
if (!reader.EndOfStream)
{
do
{
Console.WriteLine(reader.ReadLine());
} while (!reader.EndOfStream);
offset = file.Position;
}
}
}
Write to file method:
private static void WriteToFile()
{
for (int i = 0; i < 100; i++)
{
FileStream writeFile = File.Open(
"test.txt",
FileMode.Append,
FileAccess.Write,
FileShare.Read);
using (FileStream file = writeFile)
{
using (StreamWriter sw = new StreamWriter(file))
{
sw.WriteLine(i);
Thread.Sleep(100);
}
}
}
}