I have a Validate(Stream inputStream)
method. This method calls several other validation methods by passing the inputStream to each one. Each of these creates a new TextFieldParser
and reads/validates the file.
When the first ValidateA(inputStream)
is called, it works. But, when the 2nd ValidateB(inputStream)
is called, the parser.EndOfData
is true so, it does not read the fields.
I've tried to clean up the code to its simplest form.
public int Validate(Stream inputStream, ref List<string> errors)
{
inputStream.Seek(0, SeekOrigin.Begin);
errors.AddRange(ValidateA(inputStream));
// The 2nd time, the EndOfData is true, so it doesn't read the fields
inputStream.Seek(0, SeekOrigin.Begin);
errors.AddRange(ValidateB(inputStream));
...
}
private List<string> ValidateA(Stream inputStream)
{
List<string> errors = new List<string>();
// Works fine the first time
using (var parser = new TextFieldParser(inputStream))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
parser.TrimWhiteSpace = true;
int lineNumber = 0;
while (!parser.EndOfData)
{
string[] fields = parser.ReadFields();
// Processing....
}
if (lineNumber < 2)
errors.Add(string.Format("There is no data in the file"));
}
return errors;
}
Here is where the problem occurs. The ValidateB method cannot process the file because the EndOfData
field does not get reset.
private List<string> ValidateB(Stream inputStream)
{
List<string> errors = new List<string>();
using (var parser = new TextFieldParser(inputStream))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
parser.TrimWhiteSpace = true;
int LineNumber = 0;
while (!parser.EndOfData)
{
// Processing....
}
}
return errors;
}
The comment by @HansPassant is correct and lead me to change the way I was passing data around. Instead of passing a Stream
around, I converted the MemoryStream
to a byte[]
.
Then, in the ValidateX(byte[] fileByteArray)
method, I would create a new MemoryStream
from the byte array and use it.
Example:
Stream stream = model.PostedFile.InputStream;
MemoryStream memStream = new MemoryStream();
stream.CopyTo(memStream);
byte[] data = memStream.ToArray();
var result = ValidateB(data);
And then,
private List<string> ValidateB(byte[] fileByteArray)
{
List<string> errors = new List<string>();
MemoryStream ms = new MemoryStream(fileByteArray);
ms.Position = 0;
ms.Seek(0, SeekOrigin.Begin);
using (var parser = new TextFieldParser(ms))
{
// Processing...
}
}
This prevented problems with the EndOfData
and trying to access a Stream that was closed.