Go Premium for a chance to win a PS4. Enter to Win

x
?
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
Medium Priority
?
3,164 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 64

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 64

Accepted Solution

by:
Fernando Soto earned 2000 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

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
Simulator games are perfect for generating sample realistic data streams, especially for learning data analysis. It is even useful for demoing offerings such as Azure stream analytics, PowerBI etc.
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…
Loops Section Overview
Suggested Courses

824 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