2016-06-24 26 views
3

Apache POIに問題があります。 問題は、.xlsxファイルに16ビット文字値(CJK統一イデオグラフィックエクステンションBなど)を入れることです。しかし、生成された.xlsxファイルでは、セルの値が疑問符(????のようなもの)になります。JavaでApache POIを使用して.xlsxファイルに16ビット文字を書き込む

誰でも、Apache POIの16ビット文字値を.xlsx形式で扱う方法を知っていますか?

XSSFWorkbook workbook = new XSSFWorkbook(); 
XSSFSheet sheet = workbook.createSheet("Test"); 

XSSFRow row1 = sheet.createRow(0); 
XSSFCell r1c1 = row1.createCell(0); 
r1c1.setCellValue(""); // value of CJK Unified Ideographs Extension B 
XSSFCell r1c2 = row1.createCell(1); 

FileOutputStream fos =new FileOutputStream("D:/temp/test.xlsx"); 
workbook.write(fos); 
fos.close(); 

ありがとう:

マイPOIのバージョンは以下の通り3.14

コードサンプルです!

+1

これらの文字を書いているいくつかのコードを共有していただけますか? – Sanjeev

+0

あなたの返事をありがとう。サンプルコードが追加されました。 – leonlai

+0

Javaコンパイラが、それらの文字を含むソースファイルの読み込みに正しいエンコーディングを使用していることを確認しましたか? – Gagravarr

答えて

2

問題が存在します。しかし、0x0000から0xFFFFまでの16ビット(2バイト)のUnicode文字ではありません。 Unicodeエンコーディングで2バイト以上必要な文字があります。これらの文字はUnicode code pointsJava Characterに記載されています。「U + 0000からU + 10FFFFの範囲の文字値にはUnicodeコードポイントが使用され、16ビットのchar値にはUnicodeコードユニットが使用されます。 UTF-16エンコーディング " Javaプラットフォームでは、char配列とStringクラスおよびStringBufferクラスでUTF-16表現が使用されます。この表現では、補足文字(コードポイントがU + FFFFより大きい文字)は、char値のペアとして表されます。最初のものは上位サロゲート範囲(\ uD800- \ uDBFF)から、サロゲート範囲(\ uDC00- \ uDFFF)。

問題はorg.apache.xmlbeans.impl.store.Saverです。これはprivate char[] _bufで動作します。しかし、charの最大値は0xFFFFなので、0x10000から0x10FFFFまでのUnicodeコードポイントはcharに格納することはできません。したがって、char値のペアとして格納されます。

char0x100000x10FFFFの間であれば、それはチェックするため、このコードは完全にバグがある方法

/** 
    * Test if a character is valid in xml character content. See 
    * http://www.w3.org/TR/REC-xml#NT-Char 
    */ 

    private boolean isBadChar (char ch) 
    { 
     return ! (
      (ch >= 0x20 && ch <= 0xD7FF) || 
      (ch >= 0xE000 && ch <= 0xFFFD) || 
      (ch >= 0x10000 && ch <= 0x10FFFF) || 
      (ch == 0x9) || (ch == 0xA) || (ch == 0xD) 
      ); 
    } 

があります。このように、これはまったく不可能です。

また、上位サロゲート範囲(\ uD800- \ uDBFF)と低いサロゲート範囲(\ uDC00- \ uDFFF)は無効な文字として除外されます。したがって、char値のペアとしてのコードポイント表現は除外されます。

この問題は、org.apache.xmlbeans.impl.store.Saverというバグが原因です。


パッチ:

目標:悪い文字として、(\ uDC00- \ uDFFF)、高サロゲートを除外しないが(\ uD800- \ uDBFF)、範囲、および低サロゲートの範囲は。したがって、UnicodeコードポイントはU + 10000を超え、2つの16ビットとして格納されますcharsXMLでは除外されません。

Saver.javaをダウンロードしてください。 private boolean isBadChar (char ch)static final class OptimizedForSpeedSaverstatic final class TextSaver両方で

/** 
    * Test if a character is valid in xml character content. See 
    * http://www.w3.org/TR/REC-xml#NT-Char 
    */ 
    private boolean isBadChar (char ch) 
    { 
     return ! (
      (ch >= 0x20 && ch <= 0xFFFD) || 
      (ch == 0x9) || (ch == 0xA) || (ch == 0xD) 
      ); 
    } 

に変更してください。

コンパイルSaver.java

xmlbeans-2.6.0.jarのバックアップをクラスパスの外側に格納します。

Saver$OptimizedForSpeedSaver.classSaver$TextSaver.classxmlbeans-2.6.0.jar - >/org/apache/xmlbeans/impl/store/に置き換えると、新しいコンパイルされたものになります。

U + 10000を超えるUnicodeコードポイントは、sharedStrings.xmlに格納されます。


免責事項: これは、十分にテストされていません。したがって、これを生産的に使用しないでください。この問題を説明するのはここだけです。たぶんxmlbeans.apache.orgのプログラマーがorg.apache.xmlbeans.impl.store.Saverで問題を解決する時間を見つけるでしょう。


更新 が利用可能になりましxmlbeans-2.6.2.jarがあります。これにはすでにパッチが含まれています。

+0

こんにちはアクセルリッターです。あなたの説明をありがとう!それはPOIを使って.xlsxに16ビット文字を入れる方法がないということですか? – leonlai

+0

@leonlai:16ビット文字で問題はありません。 Unicode文字に問題があり、16ビット以上の** **が必要です。あなたの質問の下に私の最後のコメントを見てください。私は今晩パッチを試します。 –

+0

こんにちはAxel Ricterです。ご説明いただきありがとうございますが、どうすればorg.apache.xmlbeans.impl.store.Saverの問題を解決できますか? – leonlai

関連する問題