-4

This is a sequel to the question here where I was wondering why my stream was not fordable.

Utilizing ideas from some of the cats who answered the other question, I've now got this code:

private readonly FileStream _fileStream;
private readonly StreamWriter _streamWriter;

. . .

private ExceptionLoggingService()
{
    const int MAX_LINES_DESIRED = 1000;
    int linesInLogFile;

    string uriPath = GetExecutionFolder() + "\\Application.log";
    string logPath = new Uri(uriPath).LocalPath;
    _fileStream = File.Open(logPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
    StreamReader _streamReader = new StreamReader(_fileStream);
    List<String> logList = new List<String>();

    while (!_streamReader.EndOfStream)
    {
        logList.Add(_streamReader.ReadLine());
    }
    linesInLogFile = logList.Count;
    while (logList.Count > MAX_LINES_DESIRED)
    {
        logList.RemoveAt(0);
    }

    if (linesInLogFile > MAX_LINES_DESIRED)
    {
        _fileStream.Close();
        File.Delete(logPath);
        File.Create(logPath);
        _fileStream.Close(); // added this; did not help
        _fileStream.Dispose(); // this also did no good
        _fileStream = File.OpenWrite(logPath); // <= exception occurs here
    }

    _streamWriter = new StreamWriter(_fileStream);

    foreach (String s in logList)
    {
        _streamWriter.WriteLine(s);
    }
    _streamWriter.Flush(); // here is okay, right (as opposed to within the foreach loop)?
}

...but on the indicated ("OpenWrite()") line I get the following exception (I added the two lines above it, first the call to Close(), then Dispose(), but the exception remains the same):

System.IO.IOException was unhandled
  _HResult=-2147024864
  _message=The process cannot access the file 'C:\HoldingTank\Sandbox\bin\Debug\Application.log' because it is being used by another process.

So if Close doesn't close _fileStream, and Dispose doesn't dispose it, what can be done?

UPDATE

This doesn't strictly answer my question, but it works, inspired by Lloyd's comment:

const int MAX_FILESIZE_ALLOWED = 20000;
string uriPath = GetExecutionFolder() + "\\Application.log";
string logPath = new Uri(uriPath).LocalPath;
FileInfo f = new FileInfo(logPath);
long fileLenInBytes = f.Length;
if (fileLenInBytes > MAX_FILESIZE_ALLOWED)
{
    File.Delete(logPath);
}
_fileStream = File.OpenWrite(logPath);
_streamWriter = new StreamWriter(_fileStream);
Community
  • 1
  • 1
B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862
  • Idea is simple. Since you want to update your `Application.log` file (ref: http://stackoverflow.com/questions/27429716/how-can-i-remove-the-oldest-lines-in-a-file-when-using-a-filestream-and-streamwr/) don't try to read and write it at the same time. Read your file, close it, write the result. It is not a magic. – L.B Dec 11 '14 at 22:17
  • Yes, the idea is simple; el Diablo is in the details. – B. Clay Shannon-B. Crow Raven Dec 11 '14 at 22:24
  • 1
    Why you can't solve it after so many questions is because your inability, not because of comments or answers posted so far. For ex. I think my previous comment is the exact answer to your question. (Do you know how to implement it? then read the basic c# tutorials.) – L.B Dec 11 '14 at 22:25
  • 1
    Maybe so, but what I lack in brainpower I make up for in persistence. – B. Clay Shannon-B. Crow Raven Dec 11 '14 at 22:40
  • 1
    @B.ClayShannon Actually, according to the previous comment's sharpness - it seems you're fine in both :) – ispiro Dec 11 '14 at 22:52
  • I feel like I am repeating myself. [`File.Create` returns an open handle to the file.](http://stackoverflow.com/questions/27431351/why-is-my-stream-not-readable?noredirect=1#comment43304037_27431351) – Mike Zboray Dec 11 '14 at 22:59
  • I am no longer using File.Create (see the Update). – B. Clay Shannon-B. Crow Raven Dec 11 '14 at 23:06

1 Answers1

2

You can use one of the FileShare enumeration, for example:

_fileStream = File.Open(logPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);

You can use FileShare.None to lock the file, as described on MSDN:

Declines sharing of the current file. Any request to open the file (by this process or another process) will fail until the file is closed.

However, because this is logging I'd advise you to use something like NLog or Log4Net rather than rolling you own, let that deal with log output.

Lloyd
  • 29,197
  • 4
  • 84
  • 98
  • On the first File.Open() (not the File.OpenWrite()), right? – B. Clay Shannon-B. Crow Raven Dec 11 '14 at 22:06
  • You'd want it on the first instance that you want to lock the file. – Lloyd Dec 11 '14 at 22:09
  • This is a Windows CE / Compact Framework app; I don't think those are available in this case (I do love Log4Net normally, though). – B. Clay Shannon-B. Crow Raven Dec 11 '14 at 22:11
  • Well, the file conditionally gets destroyed, and then re-created, so I still don't know just what needs to happen here. Locking a file that then gets destroyed and resurrected doesn't seem to make sense. I tried every combination of that code (using it with my first assignment to _fileStream, my second, with both, and with the Close and Dispose calls intact and commented out - and in all cases I still get an IO exception. – B. Clay Shannon-B. Crow Raven Dec 11 '14 at 22:14
  • 1
    I think reading in the file is wasteful. Why MAX_LINES_DESIRED rather than say a max log size? You can then just check the file size before acting. BTW NLog does support Windows Mobile iirc. – Lloyd Dec 11 '14 at 22:18