Filestream file and Streamwriter in foreach and add line when done - c#

It's like that that right now I'm trying to open my file with FileStream where I saw a little further into the code to use streamwriter compared to writing it into the file every time it goes through Streamwriter.
When it runs through the first time then do it without any problems but as soon as I run it through the second lap. then it fails where it then writes "Stream was not writable"
int count = 0;
using (FileStream fs = new FileStream(#"C:\jpe\Projekt\Utilities\Icons\Icons/WriteLines.txt", FileMode.Append, FileAccess.Write))
{
foreach (SPSite tmpSite in tmpRootColl)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(string.Format("Title {0}", tmpSite.RootWeb.Title));
//Enumerate through each sub-site
foreach (SPWeb tmpWeb in tmpSite.AllWebs)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(string.Format("Title {0}", tmpWeb.Title));
//Enumerate through each List
foreach (SPList tmpList in tmpWeb.Lists)
{
if (tmpList.BaseTemplate == SPListTemplateType.DocumentLibrary)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(string.Format("Title {0}", tmpList.Title));
using (StreamWriter outputFile = new StreamWriter(fs)) //Errors come here when it runs the second round through.
{
await outputFile.WriteLineAsync($"{tmpSite.RootWeb.Title} - {tmpList.Title} {count}");
}
count++;
}
}
}
Console.WriteLine("__________________________________________________");
}
}
What I want to achieve with this is that it has to insert text into the file every time it runs through StreamWriter. It should not first make it to the last when it is finished.
i have read:
https://stackoverflow.com/a/7306243/18055701
C# how to update file(leave old data)

Currently you're creating a StreamWriter, writing to it, and disposing it for every list, this is what's causing the issue. Internally the Dispose method closes the underlying stream causing the exception. To solve this we can do one of 2 things
Tell our StreamWriter to not close the underlying stream.
Not dispose our StreamWriter until we're also done with the underlying stream.
Here's how to do #1:
Simply replace your call to the constructor with this
using (StreamWriter outputFile = new StreamWriter(fs, leaveOpen: true))
Here's how to do #2:
Move the using (StreamWriter ... block up to be "one level deeper" than the using (FileStream ... block
using (FileStream fs = new FileStream("..."))
{
using (StreamWriter outputFile = new StreamWriter(fs))
{
// Your foreach loops here
}
}
Personally I'd go with #2 as I'm not a fan of creating and disposing objects in a loop

Assuming you are using at least .NET framework 4.5.
The StreamWriter closes the base stream in its Dispose() method. You can adjust that behavior by using another construcor: https://learn.microsoft.com/en-us/dotnet/api/system.io.streamwriter.-ctor?view=netcore-3.1#system-io-streamwriter-ctor(system-io-stream-system-text-encoding-system-int32-system-boolean)

Related

C# using Statement when working with Stream's objects

I have the method :
public static void Main()
{
string path = #"C:\Temp\ProgrammingInCSharp\DirectoryInfo\111.txt";
using (FileStream fileStream = File.Create(path))
{
using (BufferedStream bufferedStream = new BufferedStream(fileStream))
{
using (StreamWriter streamWriter = new StreamWriter(bufferedStream))
{
streamWriter.WriteLine("A line of text.");
}
}
}
}
Which is using 3 using statements and method works perfectly : create 111.txt and write "A line of text." inside it.
But when I change the method to :
public static void Main()
{
string path = #"C:\Temp\ProgrammingInCSharp\DirectoryInfo\111.txt";
FileStream fileStream = File.Create(path);
BufferedStream bufferedStream = new BufferedStream(fileStream);
StreamWriter streamWriter = new StreamWriter(bufferedStream);
streamWriter.WriteLine("A line of text.");
}
It just creates 111.txt file but doesn't write "A line of text." inside.
I cannot understand why.
As I read using Statement just call Dispose() method when the object leaves the scope of using Statement. So it should be used to dispose unmanaged code from CLR but why without using Statement I cannot write the text message to my machine's file?
There is caching going on in the background: WriteLine writes to a cache, not directly to the file. So if the file isn't closed properly, the cache doesn't actually get written to the disk. The using statement disposes the object, which flushes the cache into the file and closes the file.
You can see the source code for StreamWriter.Dispose() here (notice that it calls Flush()): https://referencesource.microsoft.com/#mscorlib/system/io/streamwriter.cs,236
Note that with multiple using statements, you only need one code block. The effect is the same, but it's just easier to read.
using (FileStream fileStream = File.Create(path))
using (BufferedStream bufferedStream = new BufferedStream(fileStream))
using (StreamWriter streamWriter = new StreamWriter(bufferedStream))
{
streamWriter.WriteLine("A line of text.");
}

Issues with File Copy Asynchronously

I am copying files asynchronously with the article Microsoft provided https://learn.microsoft.com/en-us/dotnet/standard/io/asynchronous-file-i-o
The issue I am running into using this is that when the files are finished copying, it doesn't keep the date modified value and is set to the time the file was created.
To compensate for that, I am trying to set the date modified time for each file after their finished copying with the File.SetLastWriteTime static method.
foreach (var file in dir.EnumerateFiles())
{
string temppath = Path.Combine(destDirName, file.Name);
using (FileStream reader = new FileStream(file.FullName, FileMode.Open, FileAccess.Read))
{
using (FileStream writer = new FileStream(temppath, FileMode.Create, FileAccess.ReadWrite))
{
await reader.CopyToAsync(writer);
File.SetLastWriteTime(temppath, file.LastWriteTime);
}
}
}
Unfortunately, it seems that the File.SetLastWriteTime method executes immediately before await reader.CopyToAsync(writer) has finished.
How can I make sure that the File.SetLastWriteTime method isn't executed until after reader.CopyToAsync has finished?
It appears to work as intended if I change the method to copy synchronously within a Task.Run, but not sure if that is the correct way to do it.
I was able to figure it out.
The reason why it couldn't set the file time is because it was still within the stream.
I simply moved the method outside of the write stream and that resolved the problem.
foreach (var file in dir.EnumerateFiles())
{
string temppath = Path.Combine(destDirName, file.Name);
using (FileStream reader = new FileStream(file.FullName, FileMode.Open, FileAccess.Read))
{
using (FileStream writer = new FileStream(temppath, FileMode.Create, FileAccess.ReadWrite))
{
await reader.CopyToAsync(writer);
}
File.SetLastWriteTime(temppath, file.LastWriteTime);
}
}

Few last lines missing in CSV downloaded [duplicate]

Here is my code. :
FileStream fileStreamRead = new FileStream(pathAndFileName, FileMode.OpenOrCreate, FileAccess.Read, FileShare.None);
FileStream fileStreamWrite = new FileStream(reProcessedFile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
StreamWriter sw = new StreamWriter(fileStreamWrite);
int readIndex = 0;
using (StreamReader sr = new StreamReader(fileStreamRead))
{
while (!sr.EndOfStream) {
Console.WriteLine("eof" + sr.EndOfStream);
readIndex++;
Console.WriteLine(readIndex);
string currentRecord = "";
currentRecord = sr.ReadLine();
if (currentRecord.Trim() != "")
{
Console.WriteLine("Writing " + readIndex);
sw.WriteLine(currentRecord);
}
else {
Console.WriteLine("*******************************************spaces ***********************");
}
}
It is cutting off 2 lines with one test file and half a line, and then 1 line and half a line with the other test file I am running it against.
I am not a streamreader/writer expert you can probably see.
Any ideas or suggestions would be greatly appreciated as this is driving me batty. I am sure it is me using these incorrectly.
You are missing Flush/Close or simply using for your writer.
using(FileStream fileStreamWrite =
new FileStream(reProcessedFile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
{
using(StreamWriter sw = new StreamWriter(fileStreamWrite))
{
// .... write everything here
}
}
Right after the closing brace of the using statement, do this:
sw.Flush();
sw.Close();
There, that should do it.
You need to Flush your StreamWriter. A StreamWriter has a buffer, and it writes to disk only when the buffer is full. By flushing at the end you make sure all the text in the buffer is written to the disk.
In addition to other answers (use using, and/or flush/close), would say that they do not actually respond to the question: "why it may cut several lines."
I have an idea on subject that it is related to a fact that you use StreamReader and call EndOfStream twice: in a while loop header, and another inside it.
The only possible way of understanding if the stream ends is try to read some data from it. So I suspect EnfOfStream does it, and reading it twice, may create a problem in stream processing.
To resolve an issue:
Or use simple TextReader, considering that you are reading text file (seems to me)
Or change your logic to call only once, so no more call to Console.WriteLine("eof" + sr.EndOfStream);
Or change your logic, so do not use EndOFStream at all, but read line by line till the line is null.
You're not using StreamWriter properly. Also, since you're always reading lines, I would use a method that already does all that for you (and manages it properly).
using (var writer = new StreamWriter("path"))
{
foreach(var line in File.ReadLines("path"))
{
if (string.IsNullOrWhiteSpace(line))
{ /**/ }
else
{ /**/ }
}
}
... or ...
/* do not call .ToArray or something that will evaluate this _here_, let WriteAllLines do that */
var lines = File.ReadLines("path")
.Select(line => string.IsNullOrWhiteSpace(line) ? Stars : line);
var encoding = Encoding.ASCII; // whatever is appropriate for you.
File.WriteAllLines("path", lines, encoding);

Filestream.write does not work

I used the following code to write on *.txt file, but nothing happens. Even, there is no exception.
FileStream fs = new FileStream(#"D:\file.txt",FileMode.OpenOrCreate,FileAccess.Write,FileShare.None); //Creating a stream with certain features to a file
StreamWriter writer = new StreamWriter(fs); //Use the fs to write
// writer.WriteLine(Text.Text); none of the following methods works
writer.Write("aaaaaaaaaaaa");
fs.Close();
Thanks
Try to enclose it in a using block like this:
using ( FileStream fs = new FileStream(#"D:\file.txt",FileMode.OpenOrCreate,FileAccess.Write,FileShare.None))
using (StreamWriter fw = new StreamWriter(fs))
{
fw.Write("aaaaaaaaaaaa");
}
A StreamWriter buffers data before writing it to the underlying stream. You need to flushes the buffer by disposing the StreamWriter

File.AppendAllText vs StreamWriter

I want to create a log file to track some operations in my Application.In my scenario within one session I wanna to log at least 50 time per min.currently im using StremWriter to create log file.
public static StreamWriter InitializeStream(string path)
{
/*ensuring whether thread safe or not*/
lock (mylock)
{
if (null == _stream)
{
var fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite);
_stream = new StreamWriter(fileStream);
return _stream;
}
return _stream;
}
}
//logging operation
StreamHandler.Log(path)
Still im bit confuse to selecting AppendAllText or StreamWriter.
Instead of StreamWriter way can i get advantage using AppendAllText Directly?(Performance)
Do not use AppendAllText() inside the loop because it uses StremWriter internally where stream object will be initialized and disposed on each iteration.

Categories

Resources