Difference File and Streamwriter class - c#

What is the difference between using File from using System.IO & StreamWriter from using System.IO?
I am using File.WriteAllLines but in many internet-source-codes they are using:
using (StreamWriter writer = new StreamWriter("important.txt"))
{
writer.Write("Word ");
}

File.WriteAllLines is simply a convenience method that internally uses a StreamWriter, which in turn uses a FileStream to write to the file.
The main difference is that while File.WriteAllLines only writes to files, a StreamWriter can write to any stream, for example a network stream.
Either way works, use what suits you the best.

Related

Writing to stream and then creating a new stream

Suppose you have this:
using FileStream fileStream = ...;
fileStream.Write(bytes);
using GZipStream gzipStream = new GZipStream(fileStream, CompressionLevel.Optimal);
gzipStream.Write(bytesToCompress);
Would writing to fileStream first, and then creating a new GZipStream from that stream and then writing bytes to it work?
Do I have to flush fileStream first? Or is this simply unsafe?
Would writing to fileStream first, and then creating a new GZipStream from that stream and then writing bytes to it work?
Yes, that is sort of the point of streams really, that they are chainable. See Compose streams.
Do I have to flush fileStream first? Or is this simply unsafe?
Flush is only necessary when you wish to purge buffers and guarantee that the data are written to the backing store (e.g. the filesystem or network).

Difference Between StreamReader(string filepath) and StreamReader(Stream _stream)

I am little confused between two different constructor of StreamReader class i.e
1.StreamReader(Stream)
I know it takes stream bytes as input but the respective output is same.
here is my code using StreamReader(Stream) contructor
string filepath=#"C:\Users\Suchit\Desktop\p022_names.txt";
using(FileStream fs = new FileStream(filepath,FileMode.Open,FileAccess.Read))
{
using(StreamReader sw = new StreamReader(fs))
{
while(!sw.EndOfStream)
{
Console.WriteLine(sw.ReadLine());
}
}
}
2. StreamReader(String)
This conrtuctor takes the physical file path,
where our respective file exists but the output is again same.
Here is my code using StreamReader(String)
string filepath=#"C:\Users\Suchit\Desktop\p022_names.txt";
using (StreamReader sw = new StreamReader(filePath))
{
while(!sw.EndOfStream)
{
Console.WriteLine(sw.ReadLine());
}
}
So, Which one is better? When and where we should use respective code,
so that our code become more optimized and readable?
A class StreamReader (as well as StreamWriter) is just a wrapper for
FileStream, It needs a FileStream to read/write something to file.
So basically you have two options (ctor overloads) :
Create FileStream explicitly by yourself and wrap SR around it
Let the SR create FileStream for you
Consider this scenario :
using (FileStream fs = File.Open(#"C:\Temp\1.pb", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (StreamReader reader = new StreamReader(fs))
{
// ... read something
reader.ReadLine();
using (StreamWriter writer = new StreamWriter(fs))
{
// ... write something
writer.WriteLine("hello");
}
}
}
Both reader and writer works with the same filestream. Now if we change it to :
using (StreamReader reader = new StreamReader(#"C:\Temp\1.pb"))
{
// ... read something
reader.ReadLine();
using (StreamWriter writer = new StreamWriter(#"C:\Temp\1.pb"))
{
// ... write something
writer.WriteLine("hello");
}
}
System.IOException is thrown "The process cannot access the file C:\Temp\1.pb because it is being used by another process... This is because we try to open file with FileStream2 while we still use it in FileStream1. So generally speaking if you want to open file, perform one r/w operation and close it you're ok with StreamReader(string) overload. In case you would like to use the same FileStream for multiple operations or if by any other reason you'd like to have more control over Filestream then you should instantiate it first and pass to StreamReader(fs) .
Which one is better?
None. Both are same. As the name suggests StreamReader is used to work with streams; When you create an instance of StreamReader with "path", it will create the FileStream internally.
When and where we should use respective code
When you have the Stream upfront, use the overload which takes a Stream otherwise "path".
One advantage of using Stream overload is you can configure the FileStream as you want. For example if you're going to work with asynchronous methods, you need to open the file with asynchronous mode. If you don't then operation will not be truly asynchronous.
When at doubt don't hesitate to check the source yourself.
Note that the Stream overload doesn't take a FileStream. This allows you to read data from any sub class of Stream, which allows you to do things like read the result of a web request, read unzipped data, or read decrypted data.
Use the string path overload if you only want to read from a file and you don't need to use the FileStream for anything else. It just saves you from writing a line of code:
using (var stream = File.OpenRead(path))
using (var reader = new StreamReader(stream))
{
...
}
File.OpenText also does the same thing.
Both are same, just overloads, use one of them according to your need. If you have a local file then you can use StreamReader(string path) otherwise if you have just stream from online or some other source then other overload helps you i-e StreamReader(Stream stream)
Well after searching the new open source reference. You can see that the latter internaly expands to the former one. So passing a raw file path into the StreamReader makes him expand it internaly to a FileStream. For me this means, both are equivalent and you can use them as you prefer it.
My personal opinion is to use the latter one, because its less code to write and its more explicit. I don't like the way java is doing it with there thousand bytereader, streamreader, outputreaderreader and so on...
Basically both works same that is doing UTF8Encodeing and use Buffer of 1024 bytes.
But The StreamReader object calls Dispose() on the provided Stream object when StreamReader.Dispose is called.
You can refer the following Stream and String
You can use either of them depending on what you have in hand Stream or String file path.
Hope this makes it clear
StreamReader(string) is just an overload of StreamReader(Stream).
In the context of your question, you are probably better off using the StreamReader(string) overload, just because it means less code. StreamReader(Stream) might be minutely faster but you have to create a FileStream using the string you could have just put straight into the StreamReader, so whatever benefit you gained is lost.
Basically, StreamReader(string) is for files with static or easily mapped paths (as appears to be the case for you), while StreamReader(Stream) could be thought of as a fallback in case you have access to a file programmatically, but it's path is difficult to pin down.

Passing a FileStream as an argument to StreamWriter

In some code for writing and reading a file first create FileStream object then pass it as an argument to StreamWrite or StreamReader, my question is why they don't just creat StreamWrite or StreamReader ? and does each StreamWrite or StreamReader create FileStream automatically ?
FileStream output=new FileStream(fileName,FileMode.OpenOrCreate,FileAccess.Write);
StreamWriter fileWriter=new StreamWriter(output)
Thanks a lot
You're right, it is possible to instantiate a SteamWriter directly with a FilePath and a FileStream will be created automatically under the hood.
But remember that a StreamWriter is an object that is able to write to any Stream (not just FileStreams); the convenience constructor of creating a FileStream underneath the hood is normally good enough. But if someone has some special need to open up a FileStream with very specific options set, they will first create the FileStream, then pass it to the StreamWriter.
If you want to write or read a file you can use the File class.
File.ReadAllText(path);
File.WriteAllText(path,txt);
File.ReadAllLines(path);
File.WriteAllLines(path,lineArray);
No need to use FileStream..
To answer your question of why StreamWriter and StreamReader need to be passed a FileStream..
So that StreamWriter and StreamReader could be reused..
readStream(new FileStream(path,FileMode.Open));//read file stream
readStream(new NetworkStream(url));//read newtwork stream
readStream(new MemoryStream(object));//read memory stream
public void readStream(StreamReader sr)//general reader method
{
//read stream
}
This method is so general it could read almost any stream thereby reusing the code..

How to specify xml file extension while serializing Xml to a GZipStream

I am serializing an object with the following code, which uses GZip and Xml:
FileStream fs = new FileStream(destinationfolder + "/myFileName.gz",
FileMode.Create, FileAccess.Write);
using (var gz = new GZipStream(fs, CompressionMode.Compress)) {
var serializer = new XmlSerializer(typeof(MyObjectType));
serializer.Serialize(gz, myObject);
}
That works fine, with one single problem: The user can open the .gz file with 7Zip (after setting the file association), but then he can't just doubleclick the shown xml inside the .gz file, since it doesn't have the .xml extension (although the content is actually there, xml formatted and all).
Question is: "How can I serialize XML to a GZipStream so that the .xml extension is saved with the file, inside the .gz archive?" I'm using .NET 4.0.
Thanks for reading.
I have figure out a simple way to solve that. If this way should be considered a hack or a pragmatic and fine solution, is up to each one, I think.
Simply set the GZip filename to myFileName.xml.gz. This actually makes the inner file appear as myFileName.xml (trimming out the .gz extension as before).
I hope this won't break in the future...

FileStream, only producing one result?

I have two filestreams which collects different information from different files:
FileStream dataStruc = new FileStream("c:\\temp\\dataStruc.txt", FileMode.Create, FileAccess.ReadWrite);
FileStream csvFile = new FileStream("c:\\temp\\" + fileName + ".txt", FileMode.Create, FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter(csvFile);
StreamWriter swc = new StreamWriter(dataStruc);
when both streamwriters are used to get the same piece of information like shown below:
sw.WriteLine(sheet);
swc.WriteLine(sheet);
then sw streamwriter has information from file. Have I set up my filestreams incorrectly?
Assuming you don't get any exceptions/errors and that basic stuff like the correct path for the csvFile FileStream is verified and found to be correct: Try adding a Flush() or propery closing the stream using Close(). Even better: use a using statement.
EDIT
After reading your question again: are you sure you just didn't switch the filestreams?
StreamWriter sw = new StreamWriter(csvFile);
StreamWriter swc = new StreamWriter(dataStruc);
as opposed to
StreamWriter sw = new StreamWriter(dataStruc);
StreamWriter swc = new StreamWriter(csvFile);
Your question and description is rather vague: "both streamwriters are used to get the same piece of information". How would stream writers be used to get information? Also: "sw streamwriter has information from file": could you be more specific? This doesn't make sense.
Whatever the case may be; use the debugger luke!
I suppose that you have conflicting concurrent access to the file by both StreamWriters.
You open the streams with FileMode.Create. See the MSDN documentation (highlights by me):
Specifies that the operating system should create a new file. If the
file already exists, it will be overwritten. This operation requires
FileIOPermissionAccess.Write permission. System.IO.FileMode.Create is
equivalent to requesting that if the file does not exist, use
CreateNew; otherwise, use Truncate.
I am not sure if the second StreamWriter, depending on the order of the initialization, overwrites the file of the first StreamWriter or simply fails. Either way, they do try conflicting work.
Possible solutions:
Make sure the streams access the file only one after the other, e.g. by closing the first stream before the second one accesses the file, e.g. with a using block.
Change the FileMode on the streams so that an existing file does not get overridden if possible. (See the documentation above.)

Categories

Resources