Solved

How to avoid the error "Cannot write to a closed TextWriter."       from a C# console application with VS2010?

Posted on 2014-01-27
5
2,445 Views
Last Modified: 2014-01-27
I am developing a C# console application using VS2010.

I am reading a combination binary and text file and writing out 3 different output files.

My code is attached.

I am getting an error "Cannot write to a closed TextWriter."

when the following line of code is executed:

sw.WriteLine(stringb.ToString());

I placed the following 2 statements before the FOR LOOP:

string indFilePath = System.IO.Path.Combine(MyGlobals.BASE_DIR, MyGlobals.BASE_FILE_Name + ".ard.ind");

using(StreamWriter sw = new StreamWriter(indFilePath, true))

            for (int i = 0; i < bytes.Length; i++)
            {

               ...
TCSBankImage.txt
0
Comment
Question by:zimmer9
5 Comments
 
LVL 62

Expert Comment

by:Fernando Soto
ID: 39812154
Hi zimmer9;

The following line of code,

using(StreamWriter sw = new StreamWriter(indFilePath, true))

needs curly brackets, { ... }, around the code that the StreamWriter will be used with. This line of code will open the StreamWriter when it enters the first, { , and keep it open until it goes outside of the second , }. So it would seem that the StreamWriter is never opened. Try placing , { ... }, around the code that is used by the StreamWriter.
0
 

Author Comment

by:zimmer9
ID: 39812177
I tried the following using statement which results in the same error:

 Cannot write to a closed TextWriter.
-------------------------------------------------

                            if (firstTimeFlag)
                                {
                                    sw.WriteLine("COMMENT: specify code page of the index date");
                                    sw.WriteLine("CODEPAGE:819");
                                    firstTimeFlag = false;
                                }

                            using(sw)
                            {
                                sw.WriteLine(stringb.ToString());  <-- offending statement
                                stringb.Length = 0;
                            }
0
 
LVL 40
ID: 39812232
You also close a second sw1 writer that is passed as a paramater to the method. Are you sure that this one has not been closed before the method was called?
0
 
LVL 62

Accepted Solution

by:
Fernando Soto earned 500 total points
ID: 39812271
Hi,

I have modified your code in how I believe it should be but not sure it is what you are looking for. Also I have removed sw.Close() and sw1.Close(), sw because the using statement will close it automatically and sw1 because it is never used in the function and you will need to close it from the calling code.

Please modify your code as shown below and try it out.

private static void ProcessFile(string filePath, StreamWriter sw1)
{
    bool firstTimeFlag = true;
    
    var anchor1 = Encoding.UTF8.GetBytes("55ELRC");
    var anchor2 = Encoding.UTF8.GetBytes("II*");

    //Arrays do not dynamically resize. The List type does.
    //Declare a new List of byte values.
    //This creates a new List of unspecified size.
    List<byte[]> result = new List<byte[]>();

 
    var bytes = File.ReadAllBytes(filePath);

    Int32 CheckOrderNum = 0;
    string checknum = "";
    string routingtransit = "";
    string bankacct = "";
    string checkamt = "";
    string checkdate_yyyy = "";
    string checkdate_mm = "";
    string checkdate_dd = "";
    string checkpaiddate = "";
    string officenumber = "";
    string checkOffset = "";
    string checkimagelength = "";            

    string indFilePath = System.IO.Path.Combine(MyGlobals.BASE_DIR, MyGlobals.BASE_FILE_Name + ".ard.ind");
    using(StreamWriter sw = new StreamWriter(indFilePath, true)) 
    {  // Opening curly bracket for StreamWriter using statement 
				for (int i = 0; i < bytes.Length; i++)
				{                
				    var data = bytes.Skip(i).Take(anchor1.Length);
				    
				    if (data.SequenceEqual(anchor1))
				    {
				        //the int k is assigned the starting pointing of the literal string "55ELRC"
				        for (int k = i + anchor1.Length; k < bytes.Length; k++)
				        {                      
				            //Front Check Image
				            var data2 = bytes.Skip(k).Take(anchor2.Length);
				            if (data2.SequenceEqual(anchor2))
				            {
				                StringBuilder stringb = new StringBuilder();
				
				                var res = bytes.Skip(i).Take(k - i).ToArray();
				               
				                result.Add(res);
				                //i is set to k, which contains the column position of the fist of the two "II*" values within the 55 type record.
				                i = k;
				               
				                Byte[] bytes1 = res.Skip(46).Take(4).ToArray();
				              
				                Array.Reverse(bytes1);
				
				                //intpos1 is assigned the record size of the Front Check Image (position 47 of the 55 type records
				                Int32 intpos1 = BitConverter.ToInt32(bytes1, 0);
				               
				                Int32 multiplier1 = (Int32)Math.Min(Math.Floor(intpos1 / 252D) + 1, Math.Ceiling(intpos1 / 252D));
				                Int32 intpos1revised = 252 * multiplier1;
				                Byte[] bytes2 = res.Skip(54).Take(4).ToArray();
				                Array.Reverse(bytes2);
				
				                //intpos2 is assigned the record size of the Back Check Image (position 55 of the 58 type records
				                Int32 intpos2 = BitConverter.ToInt32(bytes2, 0);
				
				                Int32 multiplier2 = (Int32)Math.Min(Math.Floor(intpos2 / 252D) + 1, Math.Ceiling(intpos2 / 252D));
				                //The Back Image size value is rounded up to the next highest multipe of 252, the lrecl for type 55 records
				                Int32 intpos2revised = 252 * multiplier2;
				               
				                CheckOrderNum = CheckOrderNum + 1;
				                                            
				                //s will assigned a full 252 byte, 55 type record from which we can extract the field values
				                string s = Encoding.UTF8.GetString(res, 0, res.Length);
				                checknum = s.Substring(246, 6);
				                
				                routingtransit = s.Substring(219, 8);           
				               
				                //the bankacct 
				                bankacct = s.Substring(194, 8);              
				                                                                                             
				                //the check amount will be assembled and a decimal point inserted into the converted value
				                string checkdollars = s.Substring(138, 8);
				                string checkcents = s.Substring(146, 2);
				                checkamt = checkdollars + '.' + checkcents;
				                
				                //The check date will be assembled from its elementary parts and converted to format mm/dd/yyyy
				                checkdate_yyyy = s.Substring(12, 4);                                     checkdate_mm = s.Substring(19, 2);
				                checkdate_dd = s.Substring(21, 2);
				                checkpaiddate = checkdate_mm + "/" + checkdate_dd + "/" + checkdate_yyyy;
				                
				                officenumber = s.Substring(243, 3);
				                
				                //The column position that marks the starting point for the next Check Image, whether Front or Back Image
				                //The first check would have a Front Check Image offset of 0
				                checkOffset = MyGlobals.intcheckOffset.ToString("000000");
				                                            
				                //The total check image length = the rounded up values of the Front Check Image plus the rounded Back Check Image
				                Int32 intcheckimagelength = intpos1revised + intpos2revised;
				                //the check image length value is padded with Zeros on the left to ensure a 6 digit value zero filled
				                checkimagelength = intcheckimagelength.ToString("000000");
				                                                                                          
				                BuildFile(stringb, CheckOrderNum, checknum, routingtransit, bankacct, checkamt, checkpaiddate, officenumber, checkOffset, checkimagelength);
				
				                if (firstTimeFlag)
				                    {
				                        sw.WriteLine("COMMENT: specify code page of the index date");
				                        sw.WriteLine("CODEPAGE:819");
				                        firstTimeFlag = false;
				                    }
				
				
				                sw.WriteLine(stringb.ToString());
				                stringb.Length = 0;                                                                                 
				                
				                MyGlobals.intcheckOffset = MyGlobals.intcheckOffset + intcheckimagelength;
				                break;
				            }
				        }
				        // sw.Close(); remove this line it would close the Stream before it should
				        // sw1.Close(); With in this function you do not use sw1, so I am not sure you need it.
				    }
				}
			}  // Closing curly bracket for StreamWriter using statement 
}

Open in new window

0
 
LVL 29

Expert Comment

by:Paul Jackson
ID: 39812287
Encompass all the code using the streamwriter object as shown below:

        private static void ProcessFile(string filePath, StreamWriter sw1)
        {
            bool firstTimeFlag = true;
            
            var anchor1 = Encoding.UTF8.GetBytes("55ELRC");
            var anchor2 = Encoding.UTF8.GetBytes("II*");

            //Arrays do not dynamically resize. The List type does.
            //Declare a new List of byte values.
            //This creates a new List of unspecified size.
            List<byte[]> result = new List<byte[]>();

         
            var bytes = File.ReadAllBytes(filePath);

            Int32 CheckOrderNum = 0;
            string checknum = "";
            string routingtransit = "";
            string bankacct = "";
            string checkamt = "";
            string checkdate_yyyy = "";
            string checkdate_mm = "";
            string checkdate_dd = "";
            string checkpaiddate = "";
            string officenumber = "";
            string checkOffset = "";
            string checkimagelength = "";            

            string indFilePath = System.IO.Path.Combine(MyGlobals.BASE_DIR, MyGlobals.BASE_FILE_Name + ".ard.ind");
            using(StreamWriter sw = new StreamWriter(indFilePath, true)) 
            {
            	for (int i = 0; i < bytes.Length; i++)
            	{                
                    var data = bytes.Skip(i).Take(anchor1.Length);
                
                    if (data.SequenceEqual(anchor1))
                    {
                        //the int k is assigned the starting pointing of the literal string "55ELRC"
                        for (int k = i + anchor1.Length; k < bytes.Length; k++)
                        {                      
                            //Front Check Image
                            var data2 = bytes.Skip(k).Take(anchor2.Length);
                            if (data2.SequenceEqual(anchor2))
                            {
                                StringBuilder stringb = new StringBuilder();

                                var res = bytes.Skip(i).Take(k - i).ToArray();
                           
                                result.Add(res);
                                //i is set to k, which contains the column position of the fist of the two "II*" values within the 55 type record.
                                i = k;
                           
                                Byte[] bytes1 = res.Skip(46).Take(4).ToArray();
                          
                                Array.Reverse(bytes1);

                                //intpos1 is assigned the record size of the Front Check Image (position 47 of the 55 type records
                                Int32 intpos1 = BitConverter.ToInt32(bytes1, 0);
                             
                                Int32 multiplier1 = (Int32)Math.Min(Math.Floor(intpos1 / 252D) + 1, Math.Ceiling(intpos1 / 252D));
                                Int32 intpos1revised = 252 * multiplier1;
                                Byte[] bytes2 = res.Skip(54).Take(4).ToArray();
                                Array.Reverse(bytes2);

                                //intpos2 is assigned the record size of the Back Check Image (position 55 of the 58 type records
                                Int32 intpos2 = BitConverter.ToInt32(bytes2, 0);

                                Int32 multiplier2 = (Int32)Math.Min(Math.Floor(intpos2 / 252D) + 1, Math.Ceiling(intpos2 / 252D));
                                //The Back Image size value is rounded up to the next highest multipe of 252, the lrecl for type 55 records
                                Int32 intpos2revised = 252 * multiplier2;
                           
                                CheckOrderNum = CheckOrderNum + 1;
                                                        
                                //s will assigned a full 252 byte, 55 type record from which we can extract the field values
                                string s = Encoding.UTF8.GetString(res, 0, res.Length);
                                checknum = s.Substring(246, 6);
                            
                                routingtransit = s.Substring(219, 8);           
                           
                                //the bankacct 
                                bankacct = s.Substring(194, 8);              
                                                                                                         
                                //the check amount will be assembled and a decimal point inserted into the converted value
                                string checkdollars = s.Substring(138, 8);
                                string checkcents = s.Substring(146, 2);
                                checkamt = checkdollars + '.' + checkcents;
                           
                                //The check date will be assembled from its elementary parts and converted to format mm/dd/yyyy
                                checkdate_yyyy = s.Substring(12, 4);                                     checkdate_mm = s.Substring(19, 2);
                                checkdate_dd = s.Substring(21, 2);
                                checkpaiddate = checkdate_mm + "/" + checkdate_dd + "/" + checkdate_yyyy;
                            
                                officenumber = s.Substring(243, 3);
                            
                                //The column position that marks the starting point for the next Check Image, whether Front or Back Image
                                //The first check would have a Front Check Image offset of 0
                                checkOffset = MyGlobals.intcheckOffset.ToString("000000");
                                                        
                                //The total check image length = the rounded up values of the Front Check Image plus the rounded Back Check Image
                                Int32 intcheckimagelength = intpos1revised + intpos2revised;
                                //the check image length value is padded with Zeros on the left to ensure a 6 digit value zero filled
                                checkimagelength = intcheckimagelength.ToString("000000");
                                                                                                      
                                BuildFile(stringb, CheckOrderNum, checknum, routingtransit, bankacct, checkamt, checkpaiddate, officenumber, checkOffset, checkimagelength);

                                if (firstTimeFlag)
                                {
                                    sw.WriteLine("COMMENT: specify code page of the index date");
                                    sw.WriteLine("CODEPAGE:819");
                                    firstTimeFlag = false;
                                }


                                sw.WriteLine(stringb.ToString());
                                stringb.Length = 0;                                                                                 
                            
                                MyGlobals.intcheckOffset = MyGlobals.intcheckOffset + intcheckimagelength;
                                break;
                            }
                       }
                  }
            }
            sw.close();
      }

}

Open in new window

0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Suggested Solutions

Recently while returning home from work my wife (another .NET developer) was murmuring something. On further poking she said that she has been assigned a task where she has to serialize and deserialize objects and she is afraid of serialization. Wha…
Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now