Reputation: 139
I am developing a C# tool to read 8 gb of hex data from an unformatted SD card.
It is able to do so, but it randomly throws File Not Found Exception. For instance, it will read a gigabyte or two, then throw it. Other times it will read all 8 gbs a few times in a row, then throw the exception. In other words, it appears to pop up completely randomly.
I have no idea what might be causing it.
EDIT: I have used feedback to tweak a few things. What is pasted below is the updated code.
It still randomly throws the filenotfoundexception, but it now ALWAYS throws an argument exception when it tries to read mb 432 of gig 8 (if it gets that far without randomly throwing filenotfound).
The error complains that the filehandle does not support synchronous operations.
class Program
{
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess,
uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
uint dwFlagsAndAttributes, IntPtr hTemplateFile);
static void Main(string[] args)
{
string testOutputDirectory = @"C:\\Users\\aiovanna\\Desktop\\out1.txt"; //Specifies where to write the results of the read.
try
{
SafeFileHandle fileHandle = CreateFile("\\\\.\\E:", 0x80000000, 0, IntPtr.Zero, 3, 0, IntPtr.Zero);
FileStream readStream = new FileStream(fileHandle, FileAccess.Read); //The stream to be read. Is converted to binary.
BufferedStream bufStream = new BufferedStream(readStream, 1048576);
FileStream writeStream = File.OpenWrite(testOutputDirectory); //Writing stream opened at the specified directory of output.
//BinaryReader reader = new BinaryReader(readStream); //Changes the read stream to binary. Has more powerful methods.
long gigsRead; //Loop counter that specifies the number of gigabytes read thus far.
long megsRead; //Loop counter that specifies the number of megabytes read thus far within the current gigabyte.
Stopwatch totalStopwatch = new Stopwatch(); //Stopwatch to time the total execution of the card read.
Stopwatch megStopwatch = new Stopwatch(); //Stopwatch to time the execution of reading the current megabyte.
Stopwatch gigStopwatch = new Stopwatch(); //Stopwatch to time the executation of reading the current gigabyte.
totalStopwatch.Start(); //Start timing the program.
int bytesRead;
for (gigsRead = 0; gigsRead < 8; gigsRead++) //Gigabyte loop
{
gigStopwatch.Start(); //Start timer for current gigabyte.
for (megsRead = 0; megsRead < 1024; megsRead++) //Megabyte loop
{
megStopwatch.Start(); //Start timer for current megabyte.
try
{
byte[] buffer = new byte[1048576]; //Buffer to be read into from card
long test = gigsRead * 1073741824 + megsRead * 1048576;
bufStream.Position = test;
bytesRead = bufStream.Read(buffer, 0, 1048576); //Read from SD card to buffer
if (bytesRead < 1048576)
{
Console.WriteLine("Didn't read whole chunk!");
}
writeStream.Write(buffer, 0, 1048576); //Write from buffer to output text file.
megStopwatch.Stop(); //Stop timer for current megabyte.
Console.WriteLine("Finished mb {0} of gig {1} in {2}", megsRead + 1, gigsRead + 1, megStopwatch.Elapsed);
megStopwatch.Reset(); //Reset for next megabyte.
}
catch (System.IO.FileNotFoundException ex)
{
System.Console.WriteLine("The error was: {0}", Marshal.GetLastWin32Error());
System.Console.WriteLine("Message: {0}", ex.Message);
System.Console.WriteLine("Source: {0}", ex.Source);
System.Console.WriteLine("Stack Trace: {0}", ex.StackTrace);
System.Console.WriteLine("Target Site: {0}", ex.TargetSite);
System.Console.WriteLine(ex.ToString());
writeStream.Close(); //Close writing stream.
//reader.Close(); //Close the binary reader stream.
bufStream.Close();
fileHandle.Close(); //Close the SD card file.
readStream.Close(); //Close the filestream reader.
System.Console.WriteLine("You will need to turn off your computer, take out the card, turn the computer back on, put the SD card back in, and re-run the program.");
System.Console.WriteLine("Press any key to terminate.");
System.Console.ReadKey();
System.Environment.Exit(1);
}
catch (System.ArgumentException ex)
{
System.Console.WriteLine("The error was: {0}", Marshal.GetLastWin32Error());
System.Console.WriteLine("Message: {0}", ex.Message);
System.Console.WriteLine("Param Name: {0}", ex.ParamName);
System.Console.WriteLine("Source: {0}", ex.Source);
System.Console.WriteLine("Stack Trace: {0}", ex.StackTrace);
System.Console.WriteLine("Target Site: {0}", ex.TargetSite);
System.Console.WriteLine(ex.ToString());
writeStream.Close(); //Close writing stream.
//reader.Close(); //Close the binary reader stream.
fileHandle.Close(); //Close the SD card file.
readStream.Close(); //Close the filestream reader.
System.Console.WriteLine("You will need to turn off your computer, take out the card, turn the computer back on, put the SD card back in, and re-run the program.");
System.Console.WriteLine("Press any key to terminate.");
System.Console.ReadKey();
System.Environment.Exit(1);
}
}
gigStopwatch.Stop(); //Stop timer for current gigabyte.
Console.WriteLine("Finished gig {0} in {1}", gigsRead + 1, gigStopwatch.Elapsed);
gigStopwatch.Reset(); //Reset for next gigabyte.
}
totalStopwatch.Stop(); //Stop total execution timer.
Console.WriteLine(totalStopwatch.Elapsed); //Print total execution timer.
writeStream.Close(); //Close writing stream.
//reader.Close(); //Close the binary reader stream.
writeStream.Close(); //Close writing stream.
fileHandle.Close(); //Close the SD card file.
readStream.Close(); //Close the filestream reader.
bufStream.Close();
}
catch (System.IO.IsolatedStorage.IsolatedStorageException ex)
{
System.Console.WriteLine("The error was: {0}", Marshal.GetLastWin32Error());
System.Console.WriteLine("Isolated Storage Exception");
System.Console.WriteLine("Data: {0}", ex.Data);
System.Console.WriteLine("Help Link: {0}", ex.HelpLink);
System.Console.WriteLine("Inner Exception: {0}", ex.InnerException);
System.Console.WriteLine("Message: {0}", ex.Message);
System.Console.WriteLine("Source: {0}", ex.Source);
System.Console.WriteLine("Stack Trace {0}", ex.StackTrace);
System.Console.WriteLine("Target Site: {0}", ex.TargetSite);
Console.ReadKey();
}
catch (System.ArgumentException ex)
{
System.Console.WriteLine("The error was: {0}", Marshal.GetLastWin32Error());
System.Console.WriteLine("Argument Exception");
System.Console.WriteLine("Data: {0}", ex.Data);
System.Console.WriteLine("Help Link: {0}", ex.HelpLink);
System.Console.WriteLine("Inner Exception: {0}", ex.InnerException);
System.Console.WriteLine("Message: {0}", ex.Message);
System.Console.WriteLine("Param Name: {0}", ex.ParamName);
System.Console.WriteLine("Source: {0}", ex.Source);
System.Console.WriteLine("Stack Trace {0}", ex.StackTrace);
System.Console.WriteLine("Target Site: {0}", ex.TargetSite);
Console.ReadKey();
}
catch (System.IO.DirectoryNotFoundException ex)
{
System.Console.WriteLine("The error was: {0}", Marshal.GetLastWin32Error());
System.Console.WriteLine("Directory Not Found Exception");
System.Console.WriteLine("Data: {0}", ex.Data);
System.Console.WriteLine("Help Link: {0}", ex.HelpLink);
System.Console.WriteLine("Inner Exception: {0}", ex.InnerException);
System.Console.WriteLine("Message: {0}", ex.Message);
System.Console.WriteLine("Source: {0}", ex.Source);
System.Console.WriteLine("Stack Trace {0}", ex.StackTrace);
System.Console.WriteLine("Target Site: {0}", ex.TargetSite);
System.Console.ReadKey();
}
catch (System.ObjectDisposedException ex)
{
System.Console.WriteLine("The error was: {0}", Marshal.GetLastWin32Error());
System.Console.WriteLine("Object Disposed Exception");
System.Console.WriteLine("Data: {0}", ex.Data);
System.Console.WriteLine("Help Link: {0}", ex.HelpLink);
System.Console.WriteLine("Inner Exception: {0}", ex.InnerException);
System.Console.WriteLine("Message: {0}", ex.Message);
System.Console.WriteLine("Object Name {0}", ex.ObjectName);
System.Console.WriteLine("Source: {0}", ex.Source);
System.Console.WriteLine("Stack Trace {0}", ex.StackTrace);
System.Console.WriteLine("Target Site: {0}", ex.TargetSite);
Console.ReadKey();
}
}
}
Below I re-wrote the error that is shown for filenotfoundexception:
Message: Unable to find the specified file. Source: mscorlib Stack Trace: at System.IO.__Error.WinIOError(int32 errorcode, String maybeFullPath) at System.IO.FileStream.ReadCore(Byte[] buffer, int32 offset, int32 count) at System.IO.FileStream.Read(Byte[] array, Int32 offset, Int32 count) at System.IO.BinaryReader.Read(Byte[] buffer, Int32 index, Int32 count) at RawSDAccessTest.Program.Main(String{} args) in C:\Users\etc... at line 67 Target Site: Void WinIOError(Int32, System.String) System.IO.FileNotFoundException: Unable to find the specified file. Line 67 is: reader.Read(buffer, 0, 1048576);
What I find really weird here is that the program is perfectly OK with line 65, which also uses the reader object. Somehow between executing lines 65 and 67, it decides that the file no longer exists. I threw the wait in between to see if that would solve it. It didn't.
Any ideas as to what might be causing it to randomly throw this exception, or how to solve it?
EDIT: Process Monitor Shows the following
8:40:26.1077157 AM SDCardReadAttempt3.vshost.exe 2432 ReadFile E: SUCCESS Offset: 3,228,565,504, Length: 1,048,576, I/O Flags: Non-cached, Priority: Normal
8:40:26.1745974 AM SDCardReadAttempt3.vshost.exe 2432 ReadFile E: NO SUCH DEVICE Offset: 3,229,614,080, Length: 131,072, I/O Flags: Non-cached, Priority: Normal
So in between the reads, the device ceases to exist. I moved the file creation and deletion to the inner loop, so that it will create the file each time it tries to read from it. The problem persists. Smells like hardware to me.
EDIT 2: Now it's occasionally throwing an asynchronous read exception.
9:16:16.1129926 AM SDCardReadAttempt3.vshost.exe 3752 ReadFile E: INVALID PARAMETER Offset: 7,969,177,600, Length: 1,048,576, I/O Flags: Non-cached, Priority: Normal
I don't know how .net works deep down. Maybe it's making this into a threaded process, when the file isn't opened to be read by multiple threads. I'll toss the wait back in there to see if that eliminates this error so I can get back to the original one.
Upvotes: 9
Views: 1682
Reputation: 10862
It might be a long shot, but have you tried the ReadAsync method ?
http://msdn.microsoft.com/en-us/library/hh137813.aspx
Upvotes: 0
Reputation:
I've had similar problems reading from scanners. I ended up having to catch the exception, wait for some time (250 ms worked well for my purposes), then try to reread the same data again. I defined a threshold (6 worked well for me) at which point I gave up and raised an error to the user.
This seemed to give the hardware enough time to catch-up in most cases.
Also, try reading just the block that is giving you trouble. If you consistently get an error reading a specific block, then you obviously have a hardware problem.
Upvotes: 1