FileStream Create - c#

Is this syntax
FileStream fs = new FileStream(strFilePath, FileMode.Create);
the same as this?
FileStream fs = File.Create(strFilePath);
When yes, which one is better?

It does matter, according to JustDecompile, because File.Create ultimately calls:
new FileStream(path,
FileMode.Create,
FileAccess.ReadWrite,
FileShare.None,
bufferSize,
options);
With a bufferSize of 4096 (default) and FileOptions.None (also the same as with the FileStream constructor), but the FileShare flag is different: the FileStream constructor creates the Stream with FileShare.Read.
So I say: go for readability and use File.Create(string) if you don't care about the other options.

In my opinion, I use this one:
using (FileStream fs = new FileStream(strFilePath, FileMode.Create))
{
fs.Write("anything");
fs.Flush();
}
They basically doing the same thing, but this one create the file and opens it in create / write mode, and you can set your buffer size and all params.
new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, bufferSize, options);
With File.Create it wraps all those default buffer and params.. You will have a way better flexibility and management with my new FileStream(strFilePath, FileMode.Create);
But at this point it's more a personnal choice, if you want more readability or management options!

The second one uses just a different FileMode for the stream: take a look to this article
http://msdn.microsoft.com/en-us/library/47ek66wy.aspx
to manage default values of this method!
But use a using statement, so any resource will be released in the correct way!
using (FileStream fs = new FileStream(strFilePath, FileMode.Create))
{
// HERE WHAT YOU WANT TO DO!
}

They do exactly the same thing. The only real difference is that the former would let you use a different FileMode at runtime if you wanted to (controlling it with a variable) and the latter will only ever be doing a Create operation.
As a side note, convention is to handle things like a filestream in a using block to automatically dispose of them when they are out of scope.
using (var fs = new FileStream(strFilePath, FileMode.Create))
{
//do some stuff
}

First one creates or overwrites file with sharing Read access second with None. So it depends do you want to allow to give access while processing file or not.

With the first one you have more options to do like : handle, file access, file mode, int buffer size,.... but with the second one you have less options to do.

Related

Blocking a file while writing it using FileStream append mode in C#

I'm appending data to a file using Filestream buffer, see below:
using (FileStream filestream = new FileStream(stringPathFile, FileMode.Append, FileAccess.Write, FileShare.None))
{
filestream .Write(stuff.buffer, 0, stuff.bytesRead);
}
As debuging, when writing a larger file, I saw the file being written to the destination by every 4096 bytes, and i was able to move the file to somewhere else. How do I block file being moved around until i complete writing to the file?
Thanks
Use FileShare.ReadWrite instead of FileShare.None.
EDIT: after some testing in VB.NET 2010 (I don't have access to C# at the moment), I replicated your problem. What seems to fix the problem is avoid using using...
FileStream filestream = new FileStream(stringPathFile, FileMode.Append, FileAccess.Write, FileShare.None)
{
filestream.Write(stuff.buffer, 0, stuff.bytesRead);
}

File.Open for read access denied on executing file in Windows

I have a problem with file permissions on executing files in Windows that seems to be solved after following a forum tip[1], but I cannot understand why. Maybe you guys can help.
I'm checking the banner of a file by executing it (reading the console output) and then opening the same file for reading afterwards using FileStream:
public void fileMD5(string filename) {
if (!File.Exists(filename)) return NT.Fail("File does not exist: " + filename);
BinaryReader stream = new BinaryReader(File.Open(filename,
FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
int readBytes;
while ((readBytes = stream.Read(buffer, 0, bufferSize)) > 0) {
md5Hasher.TransformBlock(buffer, 0, readBytes, buffer, 0);
}
stream.Close();
}
fileMD5('sample.exe');
and every once in a while I would get "file is being used by another process". From Wikipedia I know that Windows will set a lock on executing files denying write access[2], but I'm only reading. Also the process should have stopped already when I try to open it.
From the forum post it would seem that adding a FileShare.ReadWrite would help and it seems that It does:
FileStream stream = File.Open('sample.exe',
FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
But I don't understand why. Is there a race condition here that I don't see?
Also the File.Open call seems to be much quicker with FileShare.ReadWrite instead of the default (which I guess is FileShare.Read).
[1] http://www.xtremevbtalk.com/archive/index.php/t-192118.html
[2] http://en.wikipedia.org/wiki/File_locking#In_Microsoft_Windows
When you do not specify a FileShare parameter the default for this option is FileShare.None, in fact the code within the File class simply executes this:
public static FileStream Open(string path, FileMode mode, FileAccess access)
{
return File.Open(path, mode, access, FileShare.None);
}
With regards to the performance I can only imagine that specifying FileShare.ReadWrite means that Windows does not need to aquire a lock on the file.
As far as the "file is being used by another process" error you are getting does this issue go away if you wrap the usage of the stream variable within a using block so that the Stream gets disposed of as soon as you are done?
using (var stream = File.Open('sample.exe', FileMode.Open, FileAccess.Read))
{
//do something with the stream here
}
You should close your FileStream and then afterwards open a new FileStream.
FileShare is needed when applications want to share a file not only one application or an application has multiple readers or writers at the same time.
Why? It's get messy when everyone can read and write at the same time. In this case you should better explicitly set it so its clear that its get messy. :)
It has to do with the underlying windows API CreateFile flags.
See http://msdn.microsoft.com/en-us/library/aa363858%28v=vs.85%29.aspx
for an overview,
http://blogs.msdn.com/b/larryosterman/archive/2004/05/13/131263.aspx
for en explanation on how NT (and following) load the execs with FILE_SHARE_DELETE
And especially this
http://blogs.msdn.com/b/oldnewthing/archive/2004/05/11/129759.aspx
For a great explanation on how the share permission and desired access compose together!
It seems like specifying the wrong FileShare can prohibit you from accessing a file. If you specify FileShare.Read but some other application has currently write access to that file, you cannot access the file, since your FileShare.Read is currently not satisfiable. FileShare.ReadWrite is less restrictive, because its easier satisfiable. Source: http://blogs.msdn.com/b/oldnewthing/archive/2004/05/11/129759.aspx

How can I read a file even when getting an "in use by another process" exception?

In VB.NET or C#, I'm trying to read the contents of a text file that is in use by another program (that's the point, actually, I can't stop the program or it stops writing to the text file, and I want to periodically read out what is currently in the text file in another program).
This is the code I'm using (VB.NET)
Dim strContents As String
Dim objReader As StreamReader
objReader = New StreamReader(FullPath)
strContents = objReader.ReadToEnd()
objReader.Close()
Or in C#:
var objReader = new StreamReader(FullPath);
var strContents = objReader.ReadToEnd();
objReader.Close();
The above, however, throws the IO exception "The process cannot access the file 'file.txt' because it is being used by another process." Are there any workarounds in this scenario?
FileStream logFileStream = new FileStream("c:\test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
StreamReader logFileReader = new StreamReader(logFileStream);
while (!logFileReader.EndOfStream)
{
string line = logFileReader.ReadLine();
// Your code here
}
// Clean up
logFileReader.Close();
logFileStream.Close();
Original source for code
I'll do the fish. The FileShare mode is critical, you must allow for write sharing. That cannot be denied since the process that is writing the file already obtained write access. The StreamReader() constructor uses FileShare.Read and doesn't have an option to use a different value. Using the StreamReader(Stream) constructor is instead is indeed the workaround.
Beware however that this sharing mode also has implications for your code. You cannot predict when the other process flushes the file. The last line you read may contain only part of a line of text. When it flushes is file buffer again, later, you'll get the rest of the line. Clearly this can mess up your logic.
It depends on the FileShare mode with which the file was opened by the other application that is appending to the file. When the other application was opening the file, it specified a FileShare mode for other applications to access the file. This FileShare mode could have been read, write, both, delete, all of these, or none.
You have to specify the very same FileShare mode that the other application specified. If the other application allowed only reading, use FileShare.Read; if it allowed both reading and writing, use FileShare.ReadWrite.
StreamReader uses only FileShare.Read mode, so you can already assume that that's not the right one. So, try ReadWrite, like so:
FileStream fs = new FileStream(FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
StreamReader reader = new StreamReader(fs);
Not sure how this will behave with an already open file, but this will prevent your application from locking it:
FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
StreamReader sr = new StreamReader(fs);
Hope it helps!

Reading / Writing text file repeatedly / simultaneously

How do I read and write on a text file without getting the exception that "File is already in use by another app"??
I tried File.readalltext() and File.Appendalltext() functions..I'm just starting out with filestream.
Which would work out best in my scenario? I would appreciate some code snipplets too ..
Thanks
This is all to do with the lock and sharing semantics that you request when opening the file.
Instead of using the shortcut approach of File.ReadAllText(), try looking into using a System.IO.FileStream and a System.IO.StreamReader / System.IO.StreamWriter.
To open a file:
using (var fileStream = new FileStream(#"c:\myFile", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var streamReader = new StreamReader(fileStream))
{
var someText = streamReader.ReadToEnd();
}
Note the FileShare.ReadWrite - this is telling the stream to allow sharing to either other readers or other writers.
For writing try something like
using (var fileStream = new FileStream(#"c:\myFile", FileMode.Create, FileAccess.Write, FileShare.Read))
using (var streamWriter = new StreamWriter(fileStream))
{
streamWriter.WriteLine("some text");
}
Note the FileShare.Read - this is telling the stream to allow sharing to readers only.
Have a read around the System.IO.FileStream and its constructor overloads and you can tailor exactly how it behaves to suit your purpose.
You need to make sure the file is not being used by any other application.
With your own application, you cannot read from a file multiple times without closing the stream between reads.
You need to find out why the file is in use - a tool like FileMon can help finding out.

Easiest way to read text file which is locked by another application

I've been using File.ReadAllText() to open a CSV file, but every time I forget to close the file in Excel, the application throws an exception because it can't get access to the file.
(Seems crazy to me, I mean the READ in ReadAllText seems pretty clear)
I know that there is File.Open with all the bells and whistles, but is there an 'intermediate' method which doesn't involve messing around with buffers and char arrays?
I think you just want the following:
using (var fileStream = new FileStream("foo.bar", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var textReader = new StreamReader(fileStream))
{
var content = textReader.ReadToEnd();
}
The FileAccess.Read parameter is what is important, to indicate that you only want to read the file. Of course, even to do this, the file must have been opened by Excel in read-share mode (see the FileShare enum in .NET). I haven't tested, so I can't guarantee that Excel does this, though I would expect it does.
[edit]
Here's a method version:
static string ReadAllText(string file)
{
using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var textReader = new StreamReader(fileStream))
return textReader.ReadToEnd();
}
If you want to specify file sharing flags in order to open a file that's in use, you're stuck with File.Open().

Categories