tags:

views:

55

answers:

1

Previously, to read XML in UTF-8 encoding through xstream, I am using DomDriver as follow :

XStream xStream = new XStream(new DomDriver("UTF-8"));

However, later I realize this is VERY slow. I use the following way :

http://stackoverflow.com/questions/3623546/optimize-loading-speed-of-xstream

This works fine at least.

However, later, I realize the same technique cannot be applied to write XML. I will get all ??? characters.

This is the last workable code using DomDriver during write

public static boolean toXML(Object object, File file) {
    XStream xStream = new XStream(new DomDriver("UTF-8"));
    OutputStream outputStream = null;

    try {
        outputStream = new FileOutputStream(file);
        xStream.toXML(object, outputStream);
    }
    catch (Exception exp) {
        log.error(null, exp);
        return false;
    }
    finally {
        if (false == close(outputStream)) {
            return false;
        }
        outputStream = null;
    }

    return true;
}

The above code works fine. In order to match with the read method which doesn't use DomDriver, I change the code to

public static boolean toXML(Object object, File file) {
    XStream xStream = new XStream();
    OutputStream outputStream = null;
    Writer writer = null;

    try {
        outputStream = new FileOutputStream(file);
        writer = new OutputStreamWriter(outputStream, Charset.forName("UTF-8"));
        xStream.toXML(object, outputStream);
    }
    catch (Exception exp) {
        log.error(null, exp);
        return false;
    }
    finally {
        if (false == close(writer)) {
            return false;
        }
        if (false == close(outputStream)) {
            return false;
        }
        writer = null;
        outputStream = null;
    }

    return true;
}

This time, all my Chinese characters changes to ???

May I know anything I had done wrong?

+1  A: 

Look at this code:

outputStream = new FileOutputStream(file);
writer = new OutputStreamWriter(outputStream, Charset.forName("UTF-8"));
xStream.toXML(object, outputStream);

You're creating a writer which will use UTF-8 - but then completely ignoring it!

Try this instead:

xStream.toXML(object, writer);

Also as a matter of style, I'd encourage you to consider the following:

  • Don't compare results with Boolean constants; just use if (foo) or if (!foo) instead
  • Catching Exception is very rarely a good idea; catch specific exceptions instead
  • Returning a Boolean value to indicate success or failure isn't idiomatic Java; generally if something fails, an exception is better
  • If the first close fails, you're quitting the method before the second close call, which probably isn't what you want. (In fact, closing the OutputStreamWriter` will close the stream anyway, but consider the principle of the thing.)
  • Setting local variables to null at the end of a method is unnecessary and clutters up your code
Jon Skeet
@Jon Oh my GOD! You have a sharp eye!
Yan Cheng CHEOK
I think there is additional mistake, I should not return in finally block. Instead, I should use boolean status = close(writer); status = status ... and return the status just at the very end of the method.
Yan Cheng CHEOK
@Yan: Returning from a finally block is okay, so long as you're careful. In particular, returning from the *end* of a finally block is fine. You just don't want to miss out some of your cleanup code due to returning half way through it.
Jon Skeet
@Yan: More importantly though - does the change to use `writer` in the `toXML` call work for you? :)
Jon Skeet
Yes. toXML works. Regarding your comment on finally, have you seen this before? http://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java
Yan Cheng CHEOK
@Yan: Hmm... no, I wasn't aware of that. Yikes indeed. That's somewhat surprising.
Jon Skeet