File Input/output issue - c#

int AccNum;
FileStream myfile = new FileStream("C:\\bankin.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
StreamReader rd = new StreamReader(myfile);
StreamWriter wt = new StreamWriter(myfile);
int a = Convert.ToInt32(rd.ReadLine());
AccNum = a;
a += 1;
wt.WriteLine(Convert.ToString(a));
Console.WriteLine(rd.ReadLine());
rd.Close();
wt.Close();
myfile.Close();
I am trying to increment an integer value in the file banking.txt, but I am getting the following error:
Cannot access a closed file

Perhaps it's because you're closing rd before wt?
If that is the case, I would recommend using the using statement to prevent this confusion in the future:
int AccNum;
using (FileStream myfile = new FileStream("C:\\bankin.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite)) {
using (StreamReader rd = new StreamReader(myfile)) {
using (StreamWriter wt = new StreamWriter(myfile)) {
int a = Convert.ToInt32(rd.ReadLine());
AccNum = a;
a += 1;
wt.WriteLine(Convert.ToString(a));
Console.WriteLine(rd.ReadLine());
}
}
}

Change your code to make use of the using statements
Provides a convenient syntax that ensures the correct use of
IDisposable objects.
int AccNum;
using(FileStream myfile = new FileStream("C:\\bankin.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
using(StreamReader rd = new StreamReader(myfile))
using (StreamWriter wt = new StreamWriter(myfile))
{
int a = Convert.ToInt32(rd.ReadLine());
AccNum = a;
a += 1;
wt.WriteLine(Convert.ToString(a));
Console.WriteLine(rd.ReadLine());
}

int AccNum;
using(FileStream myfile = new FileStream("C:\\bankin.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using(StreamReader rd = new StreamReader(myfile))
{
using(StreamWriter wt = new StreamWriter(myfile))
{
int a = Convert.ToInt32(rd.ReadLine());
AccNum = a;
a += 1;
wt.WriteLine(Convert.ToString(a));
}
Console.WriteLine(rd.ReadLine());
}
}
It's good practice to use 'using'.

the exception is produced by the line wt.Close() because the file is already closed. the Close method on StreamReader close stream and all the underlying resources (see http://msdn.microsoft.com/en-us/library/system.io.streamreader.close.aspx)
and I assume that you want to save changes, so use Flush to save or use Close with AutoFlush in place of Flush. here is your example with some modification
int AccNum;
using (FileStream myfile = new FileStream("test.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (StreamReader rd = new StreamReader(myfile))
{
using (StreamWriter wt = new StreamWriter(myfile))
{
int a = Convert.ToInt32(rd.ReadLine());
AccNum = a;
a += 1;
wt.WriteLine(Convert.ToString(a));
Console.WriteLine(rd.ReadLine());
wt.Flush();
}
}
}

Related

How to read whole binary file (not only the first variables) including string, long and int

using (var fileStream = new FileStream("data.bin", FileMode.Append, FileAccess.Write))
using (var bw1 = new BinaryWriter(fileStream))
{
bw1.Write(jmeno);
bw1.Write(date);
bw1.Write(rodnecislo);
bw1.Write(sarze);
}
using (var fileStream = new FileStream("data.bin", FileMode.Open, FileAccess.Read))
using (var br1 = new BinaryReader(fileStream))
{
string readname = br1.ReadString();
int readdate = br1.ReadInt32();
long readcislo = br1.ReadInt64();
long readsarze = br1.ReadInt64();
Console.WriteLine(readname);
Console.WriteLine(readdate);
Console.WriteLine(readcislo);
Console.WriteLine(readsarze);
}
This is how the BinaryWriter looks like. I don't know how to make the console write this whole binary file.
OK, then here is how to do it:
using (var fileStream = new FileStream("data.bin", FileMode.Open, FileAccess.Read))
using (var br1 = new BinaryReader(fileStream))
{
while (br1.BaseStream.Position != br1.BaseStream.Length)
{
string readname = br1.ReadString();
int readdate = br1.ReadInt32();
long readcislo = br1.ReadInt64();
long readsarze = br1.ReadInt64();
Console.WriteLine(readname);
Console.WriteLine(readdate);
Console.WriteLine(readcislo);
Console.WriteLine(readsarze);
}
}
For an explanation of the while condition see e.g. here

Value Being Overwritten When Reading From Text File

I am trying to create a list using the FileStream/StreamReader method. Everything works fine except the price calculation is reset every time a new line is added.
I believe the issue is with the save method. I am sure it is not caused from functions in my classes, since the price is showing properly. There seems to be an issue when saving the string.
This is my read method:
public static List<Customer> ReadCustomers()
{
// create an empty customer list
List<Customer> customerList = new List<Customer>();
// new Filestream
FileStream fs = null;
// new StreamReader
StreamReader sr = null;
Customer c; // for reading
string line;
string[] fields;
try
{
fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Read);
sr = new StreamReader(fs);
while (!sr.EndOfStream)// while there is data
{
line = sr.ReadLine();
fields = line.Split(','); // split sections by commas
c = new Customer(); // initializes customer object
c.AccountNo = Convert.ToInt32(fields[0].Trim());
c.CustomerName = Convert.ToString(fields[1].Trim());
c.CustomerType = Convert.ToChar(fields[2].Trim());
c.CustomerCharge = Convert.ToDecimal(fields[3].Trim());
customerList.Add(c);
}
}
catch (Exception ex)
{
throw ex;
}
finally // always execute
{
if (fs != null) fs.Close(); // close file
}
return customerList;
}
This is where I try to save the string...
public static void SaveCustomers(List<Customer> list)
{
FileStream fs = null;
StreamWriter sw = null;
string line;
try
{
fs = new FileStream(path, FileMode.Create, FileAccess.Write);
sw = new StreamWriter(fs);
foreach (Customer c in list) // for each customer in the list
{
line = c.AccountNo.ToString() + ", " + c.CustomerName.ToString() + ", " +
c.CustomerType.ToString() + ", " + c.CustomerCharge.ToString(); // make a line with data
sw.WriteLine(line); // and write it to the file
}
}
catch(Exception ex)
{
throw ex;
}
finally
{
if (sw != null) sw.Close(); // stream writer close
if (fs != null) fs.Close();
}
}
Calculation:
public override decimal CalculateCharge()
{
decimal peak;
decimal offpeak;
if (Kwh1 <= INDUST_BASE_HOURS)
{
peak = KWH_PEAK_BASE_PRICE;
}
else
{
peak = ((Kwh1 - INDUST_BASE_HOURS) * KWH_INDUST_PEAK) + KWH_PEAK_BASE_PRICE;
}
if (Kwh2 <= INDUST_BASE_HOURS)
{
offpeak = KWH_OFF_PEAK_BASE_PRICE;
}
else
{
offpeak = ((Kwh2 - INDUST_BASE_HOURS) * KWH_INDUST_OFFPEAK) + KWH_OFF_PEAK_BASE_PRICE;
}
return peak + offpeak;
}
In SaveCustomers(), are you sure you want to open the file:
fs = new FileStream(path, FileMode.Create, FileAccess.Write);
You may want:
fs = new FileStream(path, FileMode.Append, FileAccess.Write);
FileMode.Create will destroy the file if it exists.
FileMode.Append will append to an existing file it exists.
Maybe for the purposes of clarity around testing, you output to another file rather than the one you read in.
Try using this by using the append parameter:
new StreamWriter("c:\\file.txt", true);
http://msdn.microsoft.com/en-us/library/36b035cb.aspx
Or you can see related answers here, which had similar problems
C# add text to text file without rewriting it?

Error while accessing file C#

I get the Error (IOException) that I don't know where is the error. Here he code:
The constructor:
private const int MAX = 200;
private String path = "\\Registros\\reg";
private FileStream fs;
private BinaryWriter bw = null;
private BinaryReader br = null;
private int N;
private long pos;
public Manejo_Ficheros(String filepath){
this.path = filepath;
if(!File.Exists(path+".dat")){
fs = new FileStream(path + ".dat", FileMode.Create);
this.N = 0;
bw = new BinaryWriter(fs);
fs.Seek(0,SeekOrigin.Begin);
bw.Write(N);
}else{
fs = new FileStream(path + ".dat", FileMode.Open);
br = new BinaryReader(fs);
fs.Seek(0,SeekOrigin.Begin);
this.N = br.ReadInt32();
}
}
Here the Writting:
public void escribirRegistro(Persona p)
{
pos = 4 + this.N * MAX;
int i = (int)pos;
bw = new BinaryWriter(fs);
bw.Seek(i, SeekOrigin.Begin);
bw.Write(p.ID);
bw.Write(p.nombre);
bw.Write(p.apellidos);
bw.Write(p.Num);
bw.Write(p.Nced);
bw.Write(p.pais);
bw.Write(p.observaciones);
bw.Write(p.Anac);
bw.Write(p.tPer);
this.N += 1;
fs.Seek(0, SeekOrigin.Begin);
bw.Write(N);
bw.Close();
fs.Close();
}
As you can see, I am using a flush. It will receive a "Persona" object type and then Writting to a File.
The writting is working fine. But when I want to use the reading method see:
public Persona[] leerTodos()
{
Persona[] p = new Persona[this.N];
br = new BinaryReader(fs);
for (int i = 0; i < p.Length; i++)
{
pos = 4+i*MAX;
br.BaseStream.Seek(pos, SeekOrigin.Begin);
Persona p1 = new Persona();
p1.ID = br.ReadInt32();
p1.nombre = br.ReadString();
p1.apellidos = br.ReadString();
p1.Num = br.ReadString();
p1.Nced = br.ReadString();
p1.pais = br.ReadString();
p1.observaciones = br.ReadString();
p1.Anac = br.ReadInt32();
p1.tPer = br.ReadString();
p[i] = p1;
}
return p;
}
The application breaks in this line fs = new FileStream(path + ".dat", FileMode.Open); The process cannot access the file 'C:\Users\Allan\Desktop\data.dat' because it is being used by another process.
Thing that Writting it does not happen. I dont know what is going wrong.
Try doing this in your code
public Manejo_Ficheros(String filepath){
this.path = filepath;
if(!File.Exists(path+".dat")){
using (fs = new FileStream(path + ".dat", FileMode.Create));
{
this.N = 0;
bw = new BinaryWriter(fs);
fs.Seek(0,SeekOrigin.Begin);
bw.Write(N);
}
}else{
using (fs = new FileStream(path + ".dat", FileMode.Open))
{
br = new BinaryReader(fs);
fs.Seek(0,SeekOrigin.Begin);
this.N = br.ReadInt32();
}
}

Write from a stream to a string

I'm trying to use the streamwriter to write into a file that is created temporarily i.e. _logFileName and at the same time write the data written into the file to a string using stream reader. The current code shows no errors but at runtime says that it can not read from _logFileName as it is in use already.
how to do i do this ?
using (StreamWriter _logFile = File.CreateText(_logFileName))
{
//string s = "";
//using (StreamReader fill_log = new StreamReader(s))
using (StreamReader fill_log = new StreamReader(_logFileName))
{
_logFile.WriteLine("Logfile name is: " + _logFileName);
content += fill_log.ReadLine();
_logFile.WriteLine("LOG FILE STARTED AT: " + _startDateTime.ToString());
content += fill_log.ReadLine();
_logFile.WriteLine("============================================");
content += fill_log.ReadLine();
_logFile.Write(_message);
content += fill_log.ReadLine();
_logFile.WriteLine();
content += fill_log.ReadLine();
}
_logFile.Close();
}
So based on the suggestion i changed the code to this:
using (var fsWrite = new FileStream(_logFileName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
using (var _logFile = new StreamWriter(fsWrite))
using (var fsRead = new FileStream(_logFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var fill_log = new StreamReader(fsRead))
{
_logFile.WriteLine();
content += fill_log.ReadLine();
_logFile.WriteLine("TIME OF LOG ENTRY: " + DateTime.Now);
content += fill_log.ReadLine();
// Arbitrary objects can also be written to the file.
_logFile.WriteLine(_message);
content += fill_log.ReadLine();
_logFile.Flush();
_logFile.Close();
On doing so, i am able to red and write simultaneously! that gave no problem. Thanks. But the content string variable seems to end after everyright. and ideas why this would happen ?
In order to be able to simultaneously read and write from the same file you have to create the FileStream object manually using one of the constructors that take a FileShare parameter, for example this one.
using (var fsWrite = new FileStream(name, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
using (var _logFile = new StreamWriter(fsWrite))
using (var fsRead = new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var fill_log = new StreamReader(fsRead))
{
...
}
Another way to achieve what you want is using a specialized TextWriter that writes the StreamWriter and a StringBuilder:
using (StreamWriter _logFile = File.CreateText(_logFileName))
{
using (var builder = new StringBuildingStreamWriter(_logFile))
{
builder.WriteLine("Logfile name is: " + _logFileName);
builder.WriteLine("LOG FILE STARTED AT: " + _startDateTime.ToString());
builder.WriteLine("============================================");
builder.Write(_message);
builder.WriteLine();
content += builder.ToString();
}
_logFile.Close();
}
public class StringBuildingStreamWriter:TextWriter
{
StringBuilder sb = new StringBuilder();
private StreamWriter sw;
public StringBuildingStreamWriter(StreamWriter sw)
{
this.sw = sw;
}
public override void WriteLine(string value)
{
sb.AppendLine(value);
sw.WriteLine(value);
}
public override void WriteLine()
{
sw.WriteLine();
sb.AppendLine();
}
public override void Write(string value)
{
sb.Append(value);
sw.Write(value);
}
public override string ToString()
{
return sb.ToString();
}
public override Encoding Encoding
{
get { return UTF8Encoding.UTF8; }
}
}

Managed memory mapped file

My problem is that I can not open the file. In another process or in the same process!
Code:
var path = #"c:\work\mmf.dat";
var map = "testmap123";
var fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
if (fs.Length == 0)
{
fs.SetLength(1024);
}
var sec = new MemoryMappedFileSecurity();
var mem = MemoryMappedFile.CreateFromFile(fs, map, fs.Length, MemoryMappedFileAccess.ReadWrite, sec, HandleInheritability.Inheritable, false);
// Problem here System.UnauthorizedAccessException
var tmp = MemoryMappedFile.OpenExisting(map, MemoryMappedFileRights.FullControl, HandleInheritability.Inheritable);
Try the following:
var path = #"c:\diverse\mmf.dat";
var map = "testmap123";
using (var fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
{
if (fs.Length == 0)
{
fs.SetLength(1024);
}
}
using (var mem = MemoryMappedFile.CreateFromFile(path, FileMode.Open, map, 1024, MemoryMappedFileAccess.Read))
{
using (var tmp = MemoryMappedFile.OpenExisting(map))
{
//work with tmp
}
}

Categories