2

I have a class that appends new configuration to existing one by reading a uploaded file. The problem is it runs fine on windows, but not so on Linux - I am using Servlet for receiving the file. The new configuration must begin one a new line and must not have empty line(s) anywhere. Following is the code.

    public class ConfigGen {

        public static void process(File configFile, File uploadedFile)
                throws IOException {
            synchronized (configFile) {
                if (shouldAppend(configFile, uploadedFile)) {
                    StringBuilder builder = readFile(uploadedFile);
                    StringBuilder orig = readFile(configFile);
                    FileWriter writer = new FileWriter(configFile, true);
                    // If the content ends with a new line character then remove the
                    // new line from content to be appended
                    if (orig.toString().endsWith(
                            System.getProperty("line.separator"))) {
                        writer.append(builder.substring(1));
                    } else {
                        writer.append(builder);
                    }
                    writer.flush();
                    writer.close();
                }
            }
        }

        /**
         * @param configFile
         * @param uploadedFile
         * @return true if config change is required, false otherwise
         * @throws IOException
         */
        private static final boolean shouldAppend(File configFile, File uploadedFile)
                throws IOException {
            synchronized (configFile) {
                String originalConfig = readFile(configFile).toString().trim();
                String newAddition = readFile(uploadedFile).toString().trim();
                String newSecGroup = newAddition.substring(0,
                        newAddition.indexOf(":"));
                return !originalConfig.contains(newSecGroup);
            }
        }

        private static final StringBuilder readFile(File file) throws IOException {
            BufferedReader br = new BufferedReader(new FileReader(file));
            String str = "";
            StringBuilder builder = new StringBuilder();
            while ((str = br.readLine()) != null) {
                builder.append(System.getProperty("line.separator") + str);
            }
            br.close();
            return builder;
        }
    }

The file to which new configurations is being appended will at many time be edited by hand using vim or similar editor. The behavior I am getting is - on linux machine. If the file has been edited using vim, then the new text is appended after an additional new line, thereafter any subsequent updates appears from the next line - until it is edited using vim.

For example: Let say I have the following content in file - initially written using vim.

sg-e696a08c:
  classes:
    tomcat6:
    myappmodule:
      endpoint: "10.0.2.11"
      port: "1443"

And the new file posted with the following content

sg-fde2a89d:
  classes:
    tomcat7:
    servmod:
      db: "xyz.com"
      port: "1336"

The expected content of the configuration file is.

sg-e696a08c:
  classes:
    tomcat6:
    myappmodule:
      endpoint: "10.0.2.11"
      port: "1443"
sg-fde2a89d:
  classes:
    tomcat7:
    servmod:
      db: "xyz.com"
      port: "1336"

But instead I get

sg-e696a08c:
  classes:
    tomcat6:
    myappmodule:
      endpoint: "10.0.2.11"
      port: "1443"

sg-fde2a89d:
  classes:
    tomcat7:
    servmod:
      db: "xyz.com"
      port: "1336"

Notice there is an empty line. Any subsequent file that is posted will not result in any empty new line, until the file is edited using vim. I am not sure why I have getting this kind of behavior. The results of windows are fine. Because of this behavior the generated configuration become invalid. On Windows I am using Notepad++ to edit the files.

Is it that vim adds some special character to the end of file that I might be missing or something else ? What should I do to fix this, and Why this behaviour ?

ykesh
  • 1,199
  • 2
  • 21
  • 33
  • This is due to a difference in the "DOS" and "Unix" conventions for what "newline"/"end of line" means. See this question: http://stackoverflow.com/questions/19240082/why-do-gedit-and-vim-hide-the-final-newline-from-the-user – Pandu Mar 12 '14 at 18:47
  • Try to remove the condition `(orig.toString().endsWith()` and just use `writer.append(builder.trim());` – iTech Mar 12 '14 at 18:51
  • using `writer.append(builder.trim());` does it right for first upload after editing using vim, but otherwise on next upload, the text starts on the same line as it ended on after first upload. – ykesh Mar 12 '14 at 19:07
  • vim automatically adds a new line to the end of the file if there wasn't one originally. Looking at the comments it seems you don't expect there to be a new line at the end of the file. – FDinoff Mar 12 '14 at 19:25

1 Answers1

3

You are prepending a newline unnecessarily in readFile():

//builder.append(System.getProperty("line.separator") + str);
builder.append(str).append(System.getProperty("line.separator"));

and the commented code (from process) seems superflous.

 //if (orig.toString().endsWith(
 //          System.getProperty("line.separator"))) {
 //  writer.append(builder.substring(1));
 //} else {
 //  writer.append(builder);
 //} 

 // just use this:
 writer.append(builder);

Apart from that it may be worth mentioning that a file written in Vim ends with a newline if fileformat=unix and with a carriage return+newline if fileformat=dos. However, that should be of no consequence in this case since you use trim().