2

クライアントはラベルを印刷し、これを行うために一連の記号 (?) フォントを使用しています。アプリケーションは、シングル バイト データベース (Latin-1 を使用する Oracle) を使用します。私が置き換えようとしている古いアプリケーションは、Unicode に対応していませんでした。なんとかOKになりました。私が書いている代替アプリケーションは、古いデータを処理することになっています。

chammap アプリケーションから選択された記号は、多くの場合、特定の Unicode 文字にマップされますが、マップされない場合もあります。たとえば、LAB3 フォントを使用した月のように見えるものは、実際には U+2014 (EM DASH) です。ユーザーがこの文字を Swing テキスト フィールドに貼り付けると、その文字のコード ポイントは 8212になります。これは、(Windows? Java? によって) Private Use Area に「移動」されました。この文字をデータベースに保存するとき、Oracle は安全にエンコードできないと判断し、恐ろしい ¿ に置き換えます。したがって、文字を 8000 ずつシフトし始めました。保存するときは -= 8000、フィールドを表示するときは += 8000 です。残念ながら、他の文字が同じ量だけシフトされていないことがわかりました。たとえば、ある特定のフォントでは、ž のコード ポイントは 382 であるため、+/-256 だけシフトして「修正」しました。

今では、もっと奇妙なオフセットが発見されることを恐れており、疑問に思っています: Java を使用してこのマッピングを取得できますか? おそらく、TTF フォントには、エンコードする 255 個のグリフと、それらが対応する Unicode 文字のリストがあり、それを「正しく」行うことができますか?

現在、私は次のクラッジを使用しています:

static String fromDatabase(String str, String fontFamily) {

  if (str != null && fontFamily != null) {
    Font font = new Font(fontFamily, Font.PLAIN, 1);

    boolean changed = false;
    char[] chars = str.toCharArray();
    for (int i = 0; i < chars.length; i++) {
      if (font.canDisplay(chars[i] + 0xF000)) {
        // WE8MSWIN1252 + WinXP
        chars[i] += 0xF000;
        changed = true;
      }
      else if (chars[i] >= 128 && font.canDisplay(chars[i] + 8000)) {
        // WE8ISO8859P1 + WinXP
        chars[i] += 8000;
        changed = true;
      }
      else if (font.canDisplay(chars[i] + 256)) {
        // ž in LAB1 Eastern = 382
        chars[i] += 256;
        changed = true;
      }
    }
    if (changed) str = new String(chars);
  }
  return str;
}

static String toDatabase(String str, String fontFamily) {

  if (str != null && fontFamily != null) {
    boolean changed = false;
    char[] chars = str.toCharArray();
    for (int i = 0; i < chars.length; i++) {
      int chr = chars[i];
      if (chars[i] > 0xF000) {
        // WE8MSWIN1252 + WinXP
        chars[i] -= 0xF000;
        changed = true;
      }
      else if (chars[i] > 8000) {
        // WE8ISO8859P1 + WinXP
        chars[i] = (char) (chars[i] - 8000);
        changed = true;
      }
      else if (chars[i] > 256) {
        // ž in LAB1 Eastern = 382
        chars[i] = (char) (chars[i] - 256);
        changed = true;
      }
    }
    if (changed) return new String(chars);
  }

  return str;
}
4

2 に答える 2

3

フォント ファイルには、確かに Unicode からグリフへのマッピングがあります。残念ながら、グリフは完全に恣意的なものであり、Moon/Em-Dash で見られるように、マップ先の文字との関係を持つ必要はありません。1 バイト文字から Unicode コードポイントへのマッピングは、おそらくWindows コード ページ 1252見つけることができますが、それはあなたが望むものではありません。— EM DASH U+2014よりも。残念ながら、フォントの各文字を調べて、利用可能な Unicode 文字と比較する以外に提案することはできません。

于 2012-10-09T16:20:05.973 に答える
0

閉鎖を提供するために、これがうまくいくようです:

static String fromDatabase(String str, String fontFamily) {
  if (str != null && fontFamily != null) {
    try {
      byte[] bytes = str.getBytes("ISO-8859-1"); // database encoding
      if (fontFamily.startsWith("LAB")) {
        str = new String(bytes, "Windows-1252");
      }
    }
    catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
  }
  return str;
}

static String toDatabase(String str, String fontFamily) {
  if (str != null && fontFamily != null) {
    try {
      if (fontFamily.startsWith("LAB")) {
        str = new String(str.getBytes("Windows-1252"), "ISO-8859-1");
      }
    }
    catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
  }
  return str;
}

public void exportFormData(EigentumsbezeichnungInformationFormData formData) throws ProcessingException {
  super.exportFormData(formData);
  formData.getWert().setValue(toDatabase(formData.getWert().getValue(), formData.getSchrift().getValue()));
}

public void importFormData(EigentumsbezeichnungInformationFormData formData) throws ProcessingException {
  super.importFormData(formData);
  getWertField().setValue(fromDatabase(formData.getWert().getValue(), formData.getSchrift().getValue()));
}

これが私の説明です。データベースは ISO 8859-1 (aka. Latin 1) を使用しています。10 年前、クライアントは、意図的に Latin-1 でエンコードされていると主張する特殊なフォントの束を依頼しましたが、実際には異なる文字を表示します。この例のオメガが Ù の代わりになっていることに注目してください。

マッピングを説明するためのcharmapスクリーンショット

さらに、Latin-1 で使用されていない文字の一部も使用されます。最も簡単な解決策は、対応する Windows コード ページが使用されていることを前提としているようです。これにより、Java はデータベース「偽の Windows-1252」からのバイトを Unicode にトランスコードしたり、元に戻すことができます。翻訳後、Swing アプリケーションは Omega グリフを示すフォントを使用して Ù を表示します。問題が解決しました。"

于 2012-11-22T10:13:40.780 に答える