the process can't acces the file using streamwriter - c#

i read the file, when Form loads
string line;
if (!File.Exists(dir)) File.Create(dir);
StreamReader reader = new StreamReader(dir);
while ((line = reader.ReadLine()) != null)
{ /* do something */}
reader.Close();
then I press the button and write something in this file. but in line
System.IO.StreamWriter file = new StreamWriter(dir);
i have an error "file used by another process". why? i close my reader..

File.Create opens the file and returns you FileStream. Try:
using (var fs = File.Open(dir, FileMode.OpenOrCreate))
{
using (var reader = new StreamReader(fs))
{
while ((line = reader.ReadLine()) != null)
{ /* do something */}
}
}
EDIT
You can also do
if (!File.Exists(dir)) File.Create(dir).Close();
to make sure stream is closed

These 2 lines conflict:
if (!File.Exists(dir)) File.Create(dir);
StreamReader reader = new StreamReader(dir);
because File.Create() creates a new file and keeps it open. Therefore blocking the opening of the file for the StreamReader.
On the API level, File.Create() does not what you think. It is very different from Directory.Create().
But functionally your code makes no sense either, why would you create a new file just before reading it? It will always be empty.
Just use
if (File.Exitst(dir))
{
var lines = System.IO.File.ReadLines(dir);
foreach(string line in lines) { /* do something */ }
}

Related

How to read a line and write to that line, of a text file?

I'm use MS-Visual Studio 2015, develop a Winforms application in C#.
What I'm trying to reach is a reader&writer which opens a CSV file with UTF-8 coding, and reads line for line. My program actually reads a line, split it at the semicolons (;) and send that informations to my database. Now it should mark that line as already read, by appending a text or a special sign e.g. ("read" or "done" or "§$%").
Because it's possible that someone or something (ERP-Systems), appends new data to that CSV file. So, the next time my program iterates through that file, it shall only read the line without my special mark.
my program:
foreach (string sFile in Directory.GetFiles(sImportPfad, "*.*", SearchOption.TopDirectoryOnly))
{
var oStream = new FileStream(sFile, FileMode.Append, FileAccess.Write, FileShare.Read);
var iStream = new FileStream(sFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
var sw = new System.IO.StreamWriter(oStream);
var sr = new System.IO.StreamReader(iStream);
int c = 0;
// alle Zeilen jedes Files laden
while (!sr.EndOfStream)
{
String line = sr.ReadLine();
String[] splitLine = line.Trim().Split(txtDivider.Text.Trim().ToCharArray());
if (line.Contains("§$%"))
break;
DatenbankEintragAuftragsPool dbEintrag = new DatenbankEintragAuftragsPool();
foreach (myImportFilterObject ob in arrImportFilterObjects)
{
.
.
.
}
String result = Program.myPaletti.AuftragInDieDatenbankSchreiben(dbEintrag);
if (result.Equals("ok"))
{
sw.WriteLine(line + " §$%"); sw.Flush();
}
}
}
My problem is the writer is appending the line+"special mark" to the end of my file.
Additionally I didn't figure out how to read the file with UTF-8 coding.
I appreciate your answers !!
EDIT: ##############
This code would do the trick...
string[] lines = System.IO.File.ReadAllLines("test");
lines[0] = lines[0] + " $%&"; /* replace with whatever you need */
System.IO.File.WriteAllLines("test", lines);
But for my usage it's not recommended to read all lines, 'cause it's possible that the guys never delete any data for the next 20 years.
I'll go further to find a solution line by line...
There are some problems in your code that I will try to solve here
using(var stream = new FileStream(sFile, FileMode.Open, FileAccess.Read)
using(var reader = new StreamReader(stream, Encoding.UTF8))
{
long position = GetFirstNewRecordOfFile(sFile);
stream.Seek(position, SeekOrigin.Begin);
while(!reader.EndOfStream)
{
var line = reader.ReadLine();
// Process line
}
SaveFirstNewRecordOfFile(sFile, stream.Position);
}
Now you just need to figure out where and how to save the position of the file.
If you have a writer that appends data to the file the file might grow to a huge size over time, maybe it is better to truncate or delete the file when it has been read.
I recommend deleting the file since you will not have to loop through a lot of empty files, that will however require that you rename/move the file before processing it to avoid that the writer process appends data to it after you close it but before you delete it.
If you just move the file to a sub folder you can use that as a backup.
My solution now is to create a new file, write into this file, delete the original file and rename the new file.
foreach (string sFile in Directory.GetFiles(sImportPfad, "*.*", SearchOption.TopDirectoryOnly))
{
FileStream iStream;
try
{
using (iStream = new FileStream(sFile, FileMode.Open, FileAccess.Read, FileShare.None))
{
var sr = new System.IO.StreamReader(iStream, Encoding.UTF8);
if (rbCSVfilesMarkieren.Checked)
{
using (var oStream = new FileStream(sFile + "_new", FileMode.Create, FileAccess.Write, FileShare.None))
{
var sw = new System.IO.StreamWriter(oStream, Encoding.UTF8);
int c = 0;
while (!sr.EndOfStream)
{
String line = sr.ReadLine();
String[] splitLine = line.Trim().Split(txtDivider.Text.Trim().ToCharArray());
if (line.Contains("$$$"))
{
sw.WriteLine(line);
sw.Flush();
continue;
}
String result = Program.myPaletti.Irgendwasneues(splitLine, arrImportFilterObjects);
if (result.Equals("ok"))
{
sw.WriteLine(line + "$$$");
sw.Flush();
anzNeueDatensätze++;
}
}
}
}
System.IO.File.Delete(sFile);
System.IO.File.Move(sFile + "_new", sFile);
}
}
}
I also included the UTF-8 coding.
Furthermore I've found a way to block the file I'm reading/writing, by using FileShare.None.
Thank you guys for your help !! I appreciate it !

Read last line from website without saving file on disk

I have a website with many large CSV files (up to 100,000 lines each). From each CSV file, I need to read the last line in the file. I know how to solve the problem when I save the file on disk before reading its content:
var url = "http://data.cocorahs.org/cocorahs/export/exportreports.aspx?ReportType=Daily&Format=csv&Date=1/1/2000&Station=UT-UT-24"
var client = new System.Net.WebClient();
var tempFile = System.IO.Path.GetTempFileName();
client.DownloadFile(url, tempFile);
var lastLine = System.IO.File.ReadLines(tempFile).Last();
Is there any way to get the last line without saving a temporary file on disk?
I tried:
using (var stream = client.OpenRead(seriesUrl))
{
using (var reader = new StreamReader(stream))
{
var lastLine = reader.ReadLines("file.txt").Last();
}
}
but the StreamReader class does not have a ReadLines method ...
StreamReader does not have a ReadLines method, but it does have a ReadLine method to read the next line from the stream. You can use it to read the last line from the remote resource like this:
using (var stream = client.OpenRead(seriesUrl))
{
using (var reader = new StreamReader(stream))
{
string lastLine;
while ((lastLine = reader.ReadLine()) != null)
{
// Do nothing...
}
// lastLine now contains the very last line from reader
}
}
Reading one line at a time with ReadLine will use less memory compared to StreamReader.ReadToEnd, which will read the entire stream into memory as a string. For CSV files with 100,000 lines this could be a significant amount of memory.
This worked for me, though the service did not return data (Headers of CSV only):
public void TestMethod1()
{
var url = "http://data.cocorahs.org/cocorahs/export/exportreports.aspx?ReportType=Daily&Format=csv&Date=1/1/2000&Station=UT-UT-24";
var client = new System.Net.WebClient();
using (var stream = client.OpenRead(url))
{
using (var reader = new StreamReader(stream))
{
var str = reader.ReadToEnd().Split('\n').Where(x => !string.IsNullOrEmpty(x)).LastOrDefault();
Debug.WriteLine(str);
Assert.IsNotEmpty(str);
}
}
}

Stream TextReader to a File

I have a TextReader object.
Now, I want to stream the whole content of the TextReader to a File. I cannot use ReadToEnd() and write all to a file at once, because the content can be of high size.
Can someone give me a sample/tip how to do this in Blocks?
using (var textReader = File.OpenText("input.txt"))
using (var writer = File.CreateText("output.txt"))
{
do
{
string line = textReader.ReadLine();
writer.WriteLine(line);
} while (!textReader.EndOfStream);
}
Something like this. Loop through the reader until it returns null and do your work. Once done, close it.
String line;
try
{
line = txtrdr.ReadLine(); //call ReadLine on reader to read each line
while (line != null) //loop through the reader and do the write
{
Console.WriteLine(line);
line = txtrdr.ReadLine();
}
}
catch(Exception e)
{
// Do whatever needed
}
finally
{
if(txtrdr != null)
txtrdr.Close(); //close once done
}
Use TextReader.ReadLine:
// assuming stream is your TextReader
using (stream)
using (StreamWriter sw = File.CreateText(#"FileLocation"))
{
while (!stream.EndOfStream)
{
var line = stream.ReadLine();
sw.WriteLine(line);
}
}

BinaryFile Read to byte[]

I have binary file
BinaryWriter binwriter = new BinaryWriter(File.Open("C:\\temp\\Users.bin", FileMode.Create));
binwriter.Write(buff);
binwriter.Close();
It works, but how can I read data from this file?
I need to read new line each time, while it is not end of file.
BinaryReader binreader = new BinaryReader(File.Open("C:\\temp\\Users.bin", FileMode.Open));
byte[] m = binreader.ReadBytes(??????); //I to read only 1 line to m, and then I need to read again new line to m.
Binary file doesn't have the concept of a "line", however you can try to read it like a text file by doing this way :
using (var streamReader = new StreamReader(filePath))
{
string line;
while ((line = streamReader.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
using (StreamReader sr = new StreamReader(path))
{
while (sr.Peek() >= 0)
{
Console.WriteLine(sr.ReadLine());
}
}
you can of course adapt it to your needs instead of printing it on the Console.

If streamreader doesn't lock a file just to read it, why is the file locked until a dialogue box is clicked away?

Plenty of information on StreamReader and not locking files on stackoverflow, but does a dialogue box somehow change that? I'd have to say no, but maybe I am not using it right, and it is locking the file? My code is:
private void read1()
{
TextReader tr = new StreamReader(#"T:\\testfile");
string input = null;
while ((input = tr.ReadLine()) != null)
{
if (input.Contains("test"))
{
MessageBox.Show(input);
}
}
}
I think you need to use a FileStream to do that.
Also, you're not closing your stream or calling Dispose() on it. You should use a using statement to make sure it happens. The following code should ensure the file isn't locked.
private void read1()
{
using (var fs = new FileStream(#"T:\testfile", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
using (var tr = new StreamReader(fs)) {
string input = null;
while ((input = tr.ReadLine()) != null)
{
if (input.Contains("test"))
{
MessageBox.Show(input);
}
}
}
}
}

Categories