28

Below is my code, it is intended to take two .ckl files, compare the two, add the new items and create a new merged file. The program executes correctly when run in Netbeans however, when executing the .jar the program doesn't appear to be encoding the file in UTF-8. I am rather new to programming and would like to know where or how I might need to be enforcing this encoding to take place?

** I have removed the Swing code and other lines so that only my method is shown, the method that does all of the comparing and merging.

public void mergeFiles(File[] files, File mergedFile) {

    ArrayList<String> list = new ArrayList<String>();

    FileWriter fstream = null;
    BufferedWriter out = null;
    try {
        fstream = new FileWriter(mergedFile, false);
        out = new BufferedWriter(fstream);
      } catch (IOException e1) {
        e1.printStackTrace();
    }
    // Going in a different direction. We are using a couple booleans to tell us when we want to copy or not. So at the beginning since we start
    // with our source file we set copy to true, we want to copy everything and insert vuln names into our list as we go. After that first file 
    // we set the boolean to false so that we dont start copying anything from the second file until it is a vuln. We set to true when we see vuln
    // and set it to false if we already have that in our list. 
    // We have a tmpCopy to store away the value of copy when we see a vuln, and reset it to that value when we see an </VULN>
    Boolean copy = true;
    Boolean tmpCopy = true;
    for (File f : files) {
        textArea1.append("merging files into: " + mergedFilePathway + "\n");
        FileInputStream fis;
        try {
            fis = new FileInputStream(f);
//                BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(mergedFile), "UTF-8"));
            BufferedReader in = new BufferedReader(new InputStreamReader(fis));
            String aLine;
            while ((aLine = in.readLine()) != null) {
                // Skip the close checklist and we can write it in at the end
                if (aLine.trim().equals("</iSTIG>")) {
                    continue;
                }
                if (aLine.trim().equals("</STIGS>")) {
                    continue;
                }
                if (aLine.trim().equals("</CHECKLIST>")) {
                    continue;
                }
                if (aLine.trim().equals("<VULN>")) {
                    // Store our current value of copy
                    tmpCopy = copy;
                    copy = true;
                    String aLine2 = in.readLine();
                    String aLine3 = in.readLine();
                    String nameLine = in.readLine();

                    if (list.contains(nameLine.trim())) {
                        textArea1.append("Skipping: " + nameLine + "\n");
                        copy = false;
                        while (!(aLine.trim().equals("</VULN>"))) {
                            aLine = in.readLine();
                        }
                        continue; // this would skip the writing out to file part
                    } else {
                        list.add(nameLine.trim());
                        textArea1.append("::: List is now :::");
                        textArea1.append(list.toString() + "\n");
                    }
                    if (copy) {
                        out.write(aLine);
                        out.newLine();
                        out.write(aLine2);
                        out.newLine();
                        out.write(aLine3);
                        out.newLine();
                        out.write(nameLine);
                        out.newLine();
                    }
                } else if (copy) {
                    out.write(aLine);
                    out.newLine();
                }
                // after we have written to file, if the line was a close vuln, switch copy back to original value
                if (aLine.trim().equals("</VULN>")) {
                    copy = tmpCopy;
                }
            }

            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        copy = false;
    }

    // Now lets add the close checklist tag we omitted before
    try {
        out.write("</iSTIG>");
        out.write("</STIGS>");
        out.write("</CHECKLIST>");
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        out.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

}                                        
Halvor Holsten Strand
  • 19,829
  • 17
  • 83
  • 99
NewToThis
  • 413
  • 1
  • 5
  • 12
  • 3
    That's a lot of code. Please edit your question and remove all the Swing code, as it's not relevant to your question. I'm pretty sure only the `mergeFiles` method is relevant. – VGR Feb 01 '16 at 14:29
  • Thank you, I have deleted the code that didn't seem necessary. We are now left with the method that compares and merges. – NewToThis Feb 01 '16 at 14:58
  • You have removed too much. The entire mergeFiles method needs to be in your question, especially the line of code which creates `out`, as that's likely to be the cause of your problem. – VGR Feb 01 '16 at 15:24
  • I apologize, I did not realize I had deleted so much. The entire mergeFiles method is shown now. – NewToThis Feb 01 '16 at 16:27

3 Answers3

65

Java has extensive, highly informative documentation. Keep it bookmarked. Refer to it first, whenever you have difficulty. You'll find it's frequently helpful.

In this case, the documentation for FileWriter says:

The constructors of this class assume that the default character encoding and the default byte-buffer size are acceptable. To specify these values yourself, construct an OutputStreamWriter on a FileOutputStream.

If you want to be sure your file will be written as UTF-8, replace this:

FileWriter fstream = null;
BufferedWriter out = null;
try {
    fstream = new FileWriter(mergedFile, false);

with this:

Writer fstream = null;
BufferedWriter out = null;
try {
    fstream = new OutputStreamWriter(new FileOutputStream(mergedFile), StandardCharsets.UTF_8);
VGR
  • 40,506
  • 4
  • 48
  • 63
21

For those, who use FileWriter in order to append to an existing file, the following will work

try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true), StandardCharsets.UTF_8)) {

    //code

}
Sam Hartman
  • 6,210
  • 3
  • 23
  • 40
Saandji
  • 428
  • 4
  • 9
  • 1
    Actually, this seems like a valid answer given that you're focusing on the append situation, and as such I don't think should be posted as a comment. In the future, wait until you have reputation to comment. Answers that are comments just get deleted – Sam Hartman Oct 17 '17 at 00:01
  • 3
    This construction should be avoided, preferring `try (FileOutputStream fos = ...; OutputStreamWriter osw = ...(fos); BufferWriter bw = new BufferedWriter(osw)) {`. Otherwise the intermediate objects won't have `close()` called on them if an exception occurs in a subsequently executed constructor. For example if the `BufferedWriter()` has an exception (highly unlikely in this particular case), the `OutputStreamWriter` and `FileOutputStream` instances won't have `close()` called. See [Java 8 JLS](https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.20.3.1). – neuralmer Apr 12 '18 at 19:03
  • @neuralmer -- Excellent point.Attempting to paraphrase -- when we have a nested wrapping of `AutoCloseable` resource objects (here `BufferedReader` wraps `OutputStreamWriter` which wraps `FileOutputStream`), rather than have a *try-with-one-resource* statement on just the outermost wrapper object, it is preferable to have a *try-with-multiple-resources* statement, and then break the nested instantiation.into multiple separate resource-initialization statements of the *try* clause. There. Phew. That was a mouthful from me. I'm sure your eyes would have glazed over. :-) – fountainhead Aug 19 '19 at 12:39
7

You can just run it with the command java -Dfile.encoding=UTF-8 -jar yourjar.jar.

Follow this for more info.

Community
  • 1
  • 1
BlueMoon93
  • 2,910
  • 22
  • 39