Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

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,062 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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

Certified OpenStack Administrator Course

We just refreshed our COA course based on the Newton exam.  With 14 labs, this course goes over the different OpenStack services that are part of the certification: Dashboard, Identity Service, Image Service, Networking, Compute, Object Storage, Block Storage, and Orchestration.

Question has a verified solution.

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

We all know that functional code is the leg that any good program stands on when it comes right down to it, however, if your program lacks a good user interface your product may not have the appeal needed to keep your customers happy. This issue can…
Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…

688 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