1

My requirement is to replace parameter in rtf template with dynamic values.

I am developing the application in Oracle adf.

Scenario : template file is in arabic with some parameters that need to be replaced at run time and create a send file with updated values.

Solution tried : Method is reading template and generating another .rtf file in Arabic by replacing parameters with dynamic values.

Problem : if parameter value is in Arabic then it's replacing the parameter with some other unicode(unreadable format), where as in case of English value for parameter it's working as expected.

Kindly help me to get it out.

Below is the code that's creating another .rtf file.

            sendingFileName = Constants.TEMPLATE_FILE + key + ".rtf";
        String str = "";
        FileInputStream fi;
        try {
            fi = new FileInputStream(sendingFileName);
            BufferedInputStream bun = new BufferedInputStream(fi);
            StringBuilder sbb = new StringBuilder();
            int c = 0;
            while ((c = bun.read()) != -1) {
                sbb.append((char)c);
            }
            for (String param : (Set<String>)parameters.keySet()) {
                String param1 = param +""; //"$" + param + "$";
                int index = sbb.indexOf(param1);
                String paramValue = (String)parameters.get(param);
              if(index>-1) {
                    sbb.replace(index, index + param1.length(), paramValue);//now run
                }
            }
            str = sbb.toString();
            fileName = Constants.SENT_TEMPLATE + key + "_" + new Date().getTime() + ".rtf";
            DataOutputStream dos;
            File _file = new File(fileName);
            dos = new DataOutputStream(new FileOutputStream(_file));
            dos.writeBytes(str);
            dos.close();
            fi.close();
        } catch (FileNotFoundException e) {
        } catch (IOException e) {
        }
    }
Mohammed
  • 31
  • 5
  • Sounds like you need to set the character encoding for your file. Have a look at this: http://stackoverflow.com/a/7895133/3415090 – mohammedkhan Dec 22 '16 at 17:33

1 Answers1

1

The JavaDoc for FileOutputStream specifically says "FileOutputStream is meant for writing streams of raw bytes such as image data. For writing streams of characters, consider using FileWriter." This is because FileOutputStream has no understanding of character encoding and code pages. What is likely happening is that when you use English characters you are staying inside the default "ANSII-like" start of almost all codepages. When you use Arabic characters then you are both using an invalid codepage, and since String are stored as UTF-16, an invalid number of bytes (Arabic characters are much more likely to be multi-byte then English characters).

The JavaDoc of FileWriter informs us that "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." So, following the instructions we are given, to correct your problem we should implement the following replacement for the dos variable section (using StandardCharsets for brevity):

dos = new OutputStreamWriter(new FileOutputStream(_file), StandardCharsets.UTF_8);
dos.write(str, 0, str.length());

However, because of the way your code is structured, even this correction may run into a problem once you surround the OutputStreamWriter with another Writer, say for example a BufferedWriter. Instead of creating one giant string and writing it all at once, consider writing the output iteratively. OutputStreamWriter uses an internal buffer of a set size to buffer the input in certain circumstances, and giving it a huge input String like this may cause problems or even lead to an IOException. My provided example uses the write(String, int, int) method directly, which skips the buffer, but that workaround only works until you add another Writer wrapper.

You should also replace the BufferedInputStream bun with an InputStreamReader, which is the InputStream version of OutputStreamWriter. It reads a file using a specified character encoding, instead of reading the file byte by byte and hoping that it happens to be UTF-16 as your code currently does. The replacement will look like this:

InputStreamReader bun = InputStreamReader(fi, StandardCharsets.UTF_8);

If you want additional buffering for performance reasons you can wrap this with a BufferedReader. Also, for both the input and output Reader/Writer you may need to choose a different Charset then UTF-8, but as I don't know what file encoding you use/will use, I just defaulted to UTF-8.

Emily Mabrey
  • 1,528
  • 1
  • 12
  • 29