C# using Statement when working with Stream's objects - c#

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.");
}

Related

Filestream file and Streamwriter in foreach and add line when done

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)

WPF code analyze : CA2202 Do not dispose objects multiple timesObject

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

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

Modify File Stream in memory

I am reading a file using StreamReader fileReader = File.OpenText(filePath). I would like to modify one line in the file in memory and push the modified stream to another method.
What I would like to avoid is reading the whole file into a string and modifying the string (doesn't scale). I would also like to avoid modifying the actual file.
Is there a straightforward way of doing this?
There is no built-in way to do that in .Net framework.
Stream and StreamReader/StreamWriter classes are designed to be chained if necessary (like GZipStream wraps stream to compress it). So you can create wrapper StreamReader and update data as you need for every operation after calling wrapped reader.
You can open two stream -one for read, one for write- at the same time. I tested simple code that works, but not sure that's what you want:
// "2.bar\r\n" will be replaced by "!!!!!\r\n"
File.WriteAllText("test.txt",
#"1.foo
2.bar
3.fake");
// open inputStream for StreamReader, and open outputStream for StreamWriter
using (var inputStream = File.Open("test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var reader = new StreamReader(inputStream))
using (var outputStream = File.Open("test.txt", FileMode.Open, FileAccess.Write, FileShare.Read))
using (var writer = new StreamWriter(outputStream))
{
var position = 0L; // track the reading position
var newLineLength = Environment.NewLine.Length;
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
// your particular conditions here.
if (line.StartsWith("2."))
{
// seek line start position
outputStream.Seek(position, SeekOrigin.Begin);
// replace by something,
// but the length should be equal to original in this case.
writer.WriteLine(new String('!', line.Length));
}
position += line.Length + newLineLength;
}
}
/* as a result, test.txt will be:
1.foo
!!!!!
3.fake
*/
As you can see, both streams can be accessed by StreamReader and StreamWriter at the same time. And you can also manipulate both read/write position as well.

Unable to access a file on second call to same function in c#

I am writing to a file through a function. On the first call I am able to write to the file but on the second call I get an exception:
The process cannot access a file because it is being used by some other process.
Basically the function I am calling starts a System.Diagnostics.Process process whose output I have to write to a file with the same name and location each time the function gets called. But whenever the function gets called for the second time I get the exception.
I have tried
Byte[] info = new UTF8Encoding(true).GetBytes(contents);
if (!File.Exists(fileName))
{
// Create the file.
using (FileStream fs = File.Create(fileName))
{
fs.Write(info, 0, info.Length);
fs.Close();
}
}
using (FileStream file_write = File.Open(fileName,FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
file_write.Write(info,0,info.Length);
file_write.Close();
}
and
File.writealltext(filename,contents)
and
using (StreamWriter file_write = new StreamWriter(File_path))
{
file_write.WriteLine(File_data);
file_write.Close();
}
Nothing worked.
Can anyone suggest any other way of doing this I am really stuck.
You need to use lock so that way the processes will wait for each other to finish writing.
static object obj = new object();
static void WriteOnFile(byte[] data)
{
lock(obj)
{
FileStream file_write = new FileStream(ileName,FileMode.Open, FileAccess.ReadWrite);
file_write.Write(data,0,data.Length);
file_write.Close();
}
}

Categories

Resources