bpayne111 Posted December 13, 2003 Posted December 13, 2003 first off here's the code #region Declarations FileSystemWatcher _watcher = new FileSystemWatcher("C:\\" ,"*.pgn"); #endregion private void frmMain_Load(object sender, System.EventArgs e) { _watcher.IncludeSubdirectories = true; _watcher.EnableRaisingEvents = true; } private void _watcher_Created(object sender, System.IO.FileSystemEventArgs e) { StreamReader sr; StreamWriter sw; try { sr = new StreamReader(e.FullPath); sw = new StreamWriter("AutoCompiledChessGames",true); while (sr.Peek() != -1) { sw.WriteLine(sr.ReadLine()); } sr.Close(); sw.Close(); } catch (Exception err) { MessageBox.Show(err.Message); } } When this code is run and a .pgn file is created the _watcher_Created event fires twice (that's expected) i can get around that fairly easily... my problem though is that i get different exceptions thrown when i run this method. Sometimes i will get "FileNotFoundException" and sometimes i will get "This file is in use by another program" (Note a step through in the debugger works though; although it does call the event twice so my file is written twice.) it seems as if with the FileNotFoundException that the watcher is doing it's job so well that the file isn't actually created yet when the event fires. The second seems to be that the file is in the process of being written to so therefore cannot be accessed. My question is... How can i ensure that the file is ready to be read by my program. So that i can write it's data to my file. Is there a method that checks for a files status? looks like i'm hitting the books on this one i hope someone has some info for me thanks brandon Quote i'm not lazy i'm just resting before i get tired.
HJB417 Posted December 13, 2003 Posted December 13, 2003 using System; using System.Threading; using System.IO; namespace ConsoleApplication1 { /// <summary> /// Summary description for Class1. /// </summary> class Class1 { /// <summary> /// The main entry point for the application. /// </summary> [sTAThread] static void Main(string[] args) { string filename = @"C:\somefile.tmp"; //see if the file can be read, if not, sleep the thread for 30 sec. while(!CanReadFile(filename)) Thread.Sleep(30000); //open the file 2 read TextReader text = File.OpenText(filename); //open the file 2 write StreamWriter sw = new StreamWriter("AutoCompiledChessGames.mcg", true); //write all the lines in readFile sw.Write(text.ReadToEnd()); //flush the buffer, always important when writing. sw.Flush(); //close the streams sw.Close(); text.Close(); } /// <summary> /// Determines if a <see cref="FileStream"/> can be created with read-only access. /// </summary> /// <param name="filename">The path of the filename to open.</param> /// <returns>true if a read-only <see cref="FileStream"/> can be created using the specified filename.</returns> /// <remarks><see cref="FileStream.Close"/> can throw an <see cref="IOException"/>. This exception /// will be caught but not handled and the <see cref="FileStream"/>.</remarks> static bool CanReadFile(string filename) { try { File.OpenRead(filename).Close(); } catch { return false; } return true; } } } If the remarks for CanReadFile bother, it can be easily modified so Close() will throw an exception and let the caller deal w/ it. Quote
bpayne111 Posted December 14, 2003 Author Posted December 14, 2003 well what i found was that a change event occurs as well and calling my method during the change even worked fine. It turns out nullifying the 'double' call to the Created and Changed method is harder than i thought... i've considered some ways of dealing with it but all have a bug somewhere... is there a fool proof way of canceling the extra create and changed events? i'd like to learn the basics of threading... where should i start? thanks for the code that alone teaches me some about threading brandon Quote i'm not lazy i'm just resting before i get tired.
HJB417 Posted December 14, 2003 Posted December 14, 2003 What do you want the FileSystemWatcher to do? plz be as detailed as possible. Quote
bpayne111 Posted December 14, 2003 Author Posted December 14, 2003 The final goal is to have the FileSystemWatcher find new chess games and from it's methods add those games to a database (for now a text file is my temporary database). When a new chess game created... the created and changed events are both called twice... i'd like to stop that or at least make sure that i'm not being redundant with my file access. thanks brandon Quote i'm not lazy i'm just resting before i get tired.
HJB417 Posted December 14, 2003 Posted December 14, 2003 I think the only event you need to listen for is the FileSystemWatcher.Created event. If that event is still being raised twice for the same file, you'll need to work around that. I option is to maybe use an Array to store ackonwledged created file paths so that way when the Created event gets raised, you'll know if it's a dupe event. When your done processing the file, just remove the file path from the Array. There are other ways though, depends on what you plan to do with the file in the future. I've only used the FileSystemWatcher in a project once. FOrtunately, I've didn't have the Created event raised multiple times for the same file. The docs state that this can happen though. I was using it on win2k server. Quote
bpayne111 Posted December 14, 2003 Author Posted December 14, 2003 yes i've considered many ways of nullifying the extra event. The problem is i can not simply just use a string to see if it's the same file being used each time because the file might be edited twice in a row legitimatly. i've considered using the filename and the LastAccessTime or LastWriteTime property of a file. but even then i'm assuming that a file is never accessed or written too twice in the same minute. That's as fool proof as i can think to get it. There is a thing called Lightning chess and it is quite popular among players. Lightning chess games are usually less than 2 minutes long. Making it very possible to lose in less than a minute. If a game like that was played immediatly after any other game and the program being used Appended a file each time a game was completed. Then the game would not be recorded. My third idea to help kill that bug was to use the size of a file as a determining factor. The problem is i can't find a way to determine the file size (i'm embarassed to say that one). The only assumption with that idea is. A user edited the file manually, saved it, immeditatly saw the mistake and corrects it in a way that the file size does not change. If that situation happens in less than a minute once again the edit is missed. So i'll need a third stipulation to completly verify everything... but now i'm out of ideas besides completly checking every line of the file. Which is a very bad idea in this case because files can contain thousands of chess games at once. In case you've forgotten the Questions are HOW DO I RETRIVE THE FILE SIZE? WHAT ELSE CAN I CHECK TO MAKE IT FOOL PROOF? What's a chess nerd to do? brandon sorry it's so long of a post... just decided to break down what's going on to the fullest Quote i'm not lazy i'm just resting before i get tired.
bpayne111 Posted December 15, 2003 Author Posted December 15, 2003 ohh i thought that was the length of the filename whoops... can you think of any other ideas that would make this work flawless? Quote i'm not lazy i'm just resting before i get tired.
HJB417 Posted December 15, 2003 Posted December 15, 2003 I would still use the array, just manage it differently like, maybe just have the filepath added to the array (allow duplicate filepaths in the array) when events get raised and have a seperate thread process the files in the array. or maybe, when adding a filepath to the array, if the filepath already exists, remove it from the array and add the removed filepath to the end of the array. Quote
bpayne111 Posted December 15, 2003 Author Posted December 15, 2003 that's my whole issue... reduce redundancy while keeping accuracy files can be thousands of lines if i check it twice i would be wasting a lot of time and resources can i implement the checksum of a file to see if it has changed from the last time it was caught by filesystemwatcher? i never thought this would be so difficult thanks for the help brandon Quote i'm not lazy i'm just resting before i get tired.
HJB417 Posted December 15, 2003 Posted December 15, 2003 (edited) Don't allow duplicate filepaths in the array. Problem solved! Well, when I think about it later... not really. give me a few min Edited December 15, 2003 by HJB417 Quote
bpayne111 Posted December 15, 2003 Author Posted December 15, 2003 problem not solved.. because if the same file is edited twice in a row it will be ignored... nice try though thanks brandon Quote i'm not lazy i'm just resting before i get tired.
HJB417 Posted December 15, 2003 Posted December 15, 2003 Tell me this. The created event gets raised What methods listen on this event, and what do they do? My guess is you have aMethod Foo that 1) Open the 'created' file 2) read some data from the file 3) close the file 4) write some data to a db What is the file format for the chess games? Can you get all of the chess games in a file? I'm still trying to think of a way to handle this properly Also, what does the created event signify? That a game has been added to the file? Quote
bpayne111 Posted December 16, 2003 Author Posted December 16, 2003 ok the created event is called, but sometimes is not ready to be read. Then another created event is called for the same file. The changed event is called, and the file is ready for access. The changed event is called again for the same file. .pgn files are chess game files. They can hold as many chess games as a file can be large. As of now i'm not writing to a db because i know just enough to piss me off about them. So i'm writing them to another text file instead. My text file i created in my program will contain all games from all files. Which will eventually actually be a db which gathers statistics about these games. I think file.Length will be enough to satisfy my users. it is very rare a person would go into a pgn file and edit it. the only reason would be if they are playing the game blind (without a board) or if a certain website they play at has some bugs in the way they notate a chess game in the pgn file. Both of these occurances are fairly rare, but they can happen so therefore as a programmer i feel obligated to do something to fix that. so one day i may think of a solution but who knows i'm curious of the CheckSum of a file. I know antivirus software uses this to determine if the file has been edited or something. know anything about CheckSum? i may start anoher post with that question Quote i'm not lazy i'm just resting before i get tired.
HJB417 Posted December 17, 2003 Posted December 17, 2003 http://www.relisoft.com/Science/CrcMath.html I know I'm beating a dead horse with the ArrayList idea, but how about if you use a collection that stores the filename and a counter the represents the # of 'created' events raised on that file. To determine the # of chess games written to the file, you would divide the counter by 2. Quote
bpayne111 Posted December 17, 2003 Author Posted December 17, 2003 yes i've been over that idea before... basically it = the same two problems that i ahve alraedy.. hmmm well you know a new thought just occured (amazing considering i've been drinking) If i am allowed to assume that the created and changed events are called twice everytime for a file then i could do that. Well after mental analysis that creates a new problem. (assuming antivirus causes these events) I can not assume everyone has an antivirus that would fire these events twice. So this is leading me in a new direction that might help though... If all antivirus programs cause these events to fire like they do. I could check to see if antivirus software is enabled when the program starts. The more i think about this th emore problems it creates than solutions because more and more things could go wrong with this (let's say for some odd reason they disable the antivirus or something) So this leads me to my newest idea to solve this. If and only if all antivirus programs cause these events to fire again (and it only happens once no matter how many antivirus programs are running) Then i could try somehow to see if antivirus is enabled on that computer and THEN i could easily cancel out the extra event with a counter. This would force me to check for the change of status of antivirus software all the time with another thread which i'm not happy with but able to accept. So where do i go with that idea? i almsot thin ki should start another post for that. but i'd like to see this one get over 100 reads. It looks like we are breaking new ground thanks for your input once again. I hope this post of mine makes sense cuz i did have like 6 beers so i'm likely to have made some typos so bare with me. thanks again brandon Quote i'm not lazy i'm just resting before i get tired.
HJB417 Posted December 17, 2003 Posted December 17, 2003 ArrayList that stores Filename and filesize I'm not sure if CRC will work because I don't know where the file info (last created, last accessed, last written to, date created, etc) is stored. If somehow that info is also used in creating the CRC, you will probably get a unique CRC for each event raised on that file (assuming once the file is created the antivirus is going to access the file and do stuff). So I would try an array list that stores the filelength and the filesize. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.