简体   繁体   中英

Recursion without array. IDE prints correct output, FileWriter does not

For my Fundamentals of computing II class, I need to write code to take a string, read from an external file, and write it to a separate external file backwards. Only the words are in reverse order, not the characters, the words are still readable. My program is complete except that it doesn't write the output line backwards, but the output line shows that it's correct. I'm having trouble troubleshooting this, has anyone had any similar experience? this is the function I'm calling:

public static void writeBackwards(String s, int n)
         {
            try
               {
                  FileWriter fWrite = new FileWriter("newText.txt", true);
                  BufferedWriter bWrite = new BufferedWriter(fWrite);
                  PrintWriter outFile = new PrintWriter(bWrite);
                  
                  StringTokenizer wordsInLine;
                  wordsInLine = new StringTokenizer(s, " ");
                  String lastToken = null;
                  int count = 0;
                  
                  
                  if(n == 0)
                     {
                        outFile.println();                 
                     }
                  else
                     {  
                        while(count != n && wordsInLine.hasMoreTokens())
                           {
                              lastToken = wordsInLine.nextToken();
                              count++;                              
                           }
                        
                        outFile.print("");
                        outFile.print(lastToken + " ");
                        System.out.print(lastToken + " ");
                                        
                        writeBackwards(s, n-1);                                                               
                     }
                     
                  bWrite.flush();
                  bWrite.close(); 
               }
            catch(IOException e)
               {
                  e.getMessage();
               }
               
         }   

And this is the call to the function. The only thing that is printing anything is the function so I don't know how much this helps.

try
               {
                  FileReader fRead = new FileReader(path); //read file
                  BufferedReader bRead = new BufferedReader (fRead); //buffer file to read data
                  
                  line = bRead.readLine();
                  
                  while(line != null)
                     {
                        inLine = new StringTokenizer(line, " ");                        
                        wordCounter = inLine.countTokens();  
                        System.out.println(wordCounter);                      
                        
                        ReverseString.writeBackwards(line, wordCounter);
                        
                        line = bRead.readLine();
                     }
                  bRead.close();
               }
               
            catch(IOException e)
               {
                  e.getMessage();
               }
         }

So a line like "Alligators don't get along with puppies." should be, "puppies. with along get don't Alligators". Like I said, it works in my console(jGrasp) but it writes the file in the order it was input. HALP. Edit: For the record, I'm not allowed to use an array.

I will try to describe what's happening, step by step. The explanation might get a bit long, so grab a coffee or some tea. :)

The tricky part is the combination of recursion, multiple instances of file writers and the flush timing.

In every call of writeBackwards , it instantiantes the writer classes. After that, the code will get the "Nth word" from the text line. Following that, the word is passed to the writer, but it' not flushed . Then, the recursion starts. The recursion will only end if n is zero, then flushing starts.

Let's review this with an example. In the original text file is written "I like apples"

Let's "debug" (actually I encourage you to use your IDE's debug mode):

In the caller method, the line is read and you get the word count of 3.

writeBackwards is called, using the n value of 3. A new file writer is created. Inside the first call of the method, "apples" is selected, and written to the file writer, but it's not flushed . The method is called again, now with n being 2.

writeBackwards is called the second time, using the n value of 3. A new file writer is created. Inside the second call of the method, "like" is selected, and written to the new file writer , but it's not flushed . The method is called again, now with n being 1.

writeBackwards is called the third time, using the n value of 1. A new file writer is created. Inside the third call of the method, "I" is selected, and written to the new file writer , but it's not flushed . The method is called again, now with n being 0.

writeBackwards is called the fourth time, using the n value of 0. A new file writer is created. Inside the fourth call of the method, there are no words left, and a new line is written, and it will be flushed .

Now a brief pause. Let's check what we have in the stack , before everything is flushed.
In the current execution scope, you have a file writer with a new line char to be flushed. In the previous scope, there is a file writer with the "I" text, with the following scopes having each one a writer having "like" and "apples", respectively.

Now everything will be flushed, but since it happens at the end of the recursion, it will be in the reverse order (ironically in this case it will maintain the original order).

First, the new line char is flushed, followed by "I like apples".

How to fix it:

There are multiple ways to achieve your original goal.

A quick fix is to move the flush statement to be executed before the recursion happens.

            outFile.print("");
            outFile.print(lastToken + " ");
            System.out.print(lastToken + " ");
            bWrite.flush();
            writeBackwards(s, n-1);

There are a number of other ways you could rewrite your code, but this answer would get too large. You could create a single file writer and pass it along in the recursion or rewrite the writeBackwards method to only reverse the sentence, leaving the file writing to another piece of code.

One more observation:

  • your code doesn't close the files properly. Try searching for "java try with resources" or articles about safe file handling in Java.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM