3

拿这个 SSCCE(安装了 Joda-Money 库):

public static void main(String[] args) {
    BigDecimal bd = new BigDecimal("100");
    MoneyFormatter mf = new MoneyFormatterBuilder().appendLiteral("$ ").appendAmount(MoneyAmountStyle.LOCALIZED_GROUPING).toFormatter();
    String money_as_string = mf.print(Money.of(CurrencyUnit.USD, bd)); // The MoneyFormatter is what printed this string...
    System.out.println(money_as_string);
    Money money = mf.parseMoney(money_as_string); // You think it should be able to parse the string it gave me, right?
}

我用MoneyFormatter来打印String: money_as_string。我的(合理的?)期望是我可以使用相同MoneyFormatter的方法将字符串解析回Money对象。但是,唉,没有骰子。它抛出这个错误:

Exception in thread "main" org.joda.money.format.MoneyFormatException: Parsing did not find both currency and amount: $ 100.00
    at org.joda.money.format.MoneyFormatter.parseBigMoney(MoneyFormatter.java:237)
    at org.joda.money.format.MoneyFormatter.parseMoney(MoneyFormatter.java:258)
    at test4.Test12.main(Test12.java:35)

所以,我的问题是:一个人究竟是如何Money从 a 中得到一个对象的String

编辑:@durron597,您的信息很有帮助,但没有回答问题。那么,你究竟是如何从一个对象转到String一个Money对象的呢?

我添加了删除美元符号的代码:

public static void main(String[] args) {
    BigDecimal bd = new BigDecimal("100");
    MoneyFormatter mf = new MoneyFormatterBuilder().appendLiteral("$ ").appendAmount(MoneyAmountStyle.LOCALIZED_GROUPING).toFormatter();
    String money_as_string = mf.print(Money.of(CurrencyUnit.USD, bd)); // The MoneyFormatter is what printed this string...
    System.out.println(money_as_string);
    Money money = mf.parseMoney(money_as_string.replace("$", "").trim()); // You think it should be able to parse the string it gave me, right?
}

我得到了这个:

Exception in thread "main" org.joda.money.format.MoneyFormatException: Text could not be parsed at index 0: 100.00
    at org.joda.money.format.MoneyFormatter.parseBigMoney(MoneyFormatter.java:233)
    at org.joda.money.format.MoneyFormatter.parseMoney(MoneyFormatter.java:258)
    at test4.Test12.main(Test12.java:35)

因此,它无法解析带有或不带有货币符号的文本。

任何人都可以使该parseMoney()功能正常工作吗?

4

1 回答 1

3

所以让我印象深刻的第一件事是你正在使用appendLiteral而不是appendCurrencySymbolLocalized(如果你正在使用CurrencyUnit.EUR呢?你不会想要$)。

但是,当您将其更改为:

MoneyFormatter mf = new MoneyFormatterBuilder()
        .appendCurrencySymbolLocalized()
        .appendAmount(MoneyAmountStyle.LOCALIZED_GROUPING)
        .toFormatter();

您的代码会引发此异常:

Exception in thread "main" java.lang.UnsupportedOperationException: MoneyFomatter has not been configured to be able to parse
    at org.joda.money.format.MoneyFormatter.parse(MoneyFormatter.java:281)
    at org.joda.money.format.MoneyFormatter.parseBigMoney(MoneyFormatter.java:229)
    at org.joda.money.format.MoneyFormatter.parseMoney(MoneyFormatter.java:258)
    at MoneyTest.main(MoneyTest.java:17)

进一步检查揭示了 javadoc 中的这一行:

appendCurrencySymbol本地化

publicMoneyFormatterBuilderappendCurrencySymbolLocalized()

将本地化货币符号附加到构建器。本地化货币符号是由格式化程序的语言环境选择的符号。

无法解析符号。

返回:this,用于链接,从不为空

为什么会这样?可能是因为货币符号不明确许多国家使用美元。以下是一些例子

除了世界上使用美元或比索的国家外,其他一些国家也使用 $ 符号来表示其货币,包括:

  • 尼加拉瓜科尔多瓦(通常写成 C$)
  • 萨摩亚语 tālā(美元的音译)
  • 汤加潘加
  • 津巴布韦(通常写为 Z$)

试试这个代码:

MoneyFormatter mf = new MoneyFormatterBuilder()
        .appendCurrencyCode()
        .appendAmount(MoneyAmountStyle.LOCALIZED_GROUPING)
        .toFormatter();

这将产生类似USD 100.00打印的东西,它将被正确解析。如果您绝对必须有美元符号,您将需要实现自己的打印机/解析器。或者你可以使用这个:

import java.io.IOException;
import java.math.BigDecimal;

import org.joda.money.BigMoney;
import org.joda.money.CurrencyUnit;
import org.joda.money.IllegalCurrencyException;
import org.joda.money.Money;
import org.joda.money.format.MoneyAmountStyle;
import org.joda.money.format.MoneyFormatter;
import org.joda.money.format.MoneyFormatterBuilder;
import org.joda.money.format.MoneyParseContext;
import org.joda.money.format.MoneyParser;
import org.joda.money.format.MoneyPrintContext;
import org.joda.money.format.MoneyPrinter;

public class MoneyTest {
    private static enum DollarParserPrinter implements MoneyParser,
            MoneyPrinter {
        INSTANCE;

        private static final String DOLLAR_SYMBOL = "$ ";

        @Override
        public void parse(MoneyParseContext context) {
            int endPos = context.getIndex() + 2;
            if (endPos > context.getTextLength()) {
                context.setError();
            } else {
                String code =
                        context.getTextSubstring(context.getIndex(), endPos);
                if(DOLLAR_SYMBOL.equals(code)) {
                    context.setCurrency(CurrencyUnit.USD);
                    context.setIndex(endPos);
                }
            }
        }

        @Override
        public void print(MoneyPrintContext context, Appendable appendable,
                BigMoney money) throws IOException {
            if(CurrencyUnit.USD == money.getCurrencyUnit()) {
                appendable.append(DOLLAR_SYMBOL);
            } else {
                throw new IllegalCurrencyException("This parser only knows how to print US Dollar money!");
            }
        }
    }

    public static void main(String[] args) {
        BigDecimal bd = new BigDecimal("100");
        MoneyFormatter mf =
                new MoneyFormatterBuilder().append(DollarParserPrinter.INSTANCE, DollarParserPrinter.INSTANCE)
                        .appendAmount(MoneyAmountStyle.LOCALIZED_GROUPING)
                        .toFormatter();
        String money_as_string = mf.print(Money.of(CurrencyUnit.USD, bd)); 
        System.out.println(money_as_string);
        Money money = mf.parseMoney(money_as_string);
        System.out.println(money);
    }
}
于 2014-05-12T14:06:28.643 回答