- PR -

byte配列の文字コード置換

投稿者投稿内容
bonif
常連さん
会議室デビュー日: 2007/05/25
投稿数: 33
投稿日時: 2007-06-20 13:11
以前も似たような質問をしたのですが、本格的にわからなくなってきたので再度質問をしにきました。

読み込んだ文字列をbyteの配列に変換し、割り当てられてないコードがあった場合に特定の文字に変換するという作業をしようと思っています。それで、

byte bt[]=str.getBytes();
String st[]=new String[bt.length];
for(int i=0;i<bt.length;i++){
  int n=bt[i];
  if(n<0){
    n+=256;
  }
  st[i]=Integer.toString(n,16);
}

と、この操作でbyteの配列を文字配列に変えて16進表記で出力し、その後で文字配列でチェックしてbyte配列を修正・・・という風にしたいのですが、
・16進数のときの効率的なデータ照合
・byte配列の修正法
がわかりません。

どなたかご教授お願いできませんでしょうか。
SUK2
ベテラン
会議室デビュー日: 2005/12/27
投稿数: 69
投稿日時: 2007-06-20 14:44
引用:
・16進数のときの効率的なデータ照合

とは人間にとって効率的という事ですか?その場合はどの様な表記が効率的に感じるか人それぞれですので回答のしようが無いかと思われます。
通常はヒューマンチェック等行わないと思うのですが、プログラム的に効率の良い方法という事でしょうか?その場合、コンピューター内部では2進数でしか処理していないため、基数を考慮する意味はありません。
引用:
・byte配列の修正法

代入するだけでは?(bt[i] = 0; みたいな)

蛇足ですが、2バイト文字を考慮するならばbyte配列よりchar配列をお勧めします。
Edosson
ぬし
会議室デビュー日: 2004/04/30
投稿数: 675
投稿日時: 2007-06-20 14:45
引用:

キューティーB☆O☆Nさんの書き込み (2007-06-20 13:11) より:

と、この操作でbyteの配列を文字配列に変えて16進表記で出力し、その後で文字配列でチェックしてbyte配列を修正・・・という風にしたいのですが、


もともと、ファイルから読み込んだデータなんですよね。
バイナリに戻すのはともかく、わざわざまた文字列に変換しているのがよくわからん。
効率的ってことなら、数値のまま処理する方が速いでしょう。
引用:

・16進数のときの効率的なデータ照合


16進数じゃなくて「数値を16進数表記で表現した文字列」ですね。
照合アルゴリズムについては、照合するためには、大小比較だけならともかく、
マスクをかけようと思ったら、また数値に戻さなきゃならん、以外に、
現時点では、私ではコメントできません。
引用:

・byte配列の修正法
がわかりません。


超能力を発揮して解釈すると、入れ替え時に文字のバイト長が違った場合のことなのかな。
System#arrayCopy()で地道に詰めていくしかなさそうだね。
あすか
ぬし
会議室デビュー日: 2006/07/12
投稿数: 309
投稿日時: 2007-06-20 14:58
まず、最初にchar配列に変換し
for文でchar配列をまわし
if文で置き換える対象の文字が見つかったら置き換える。

次に置換し終わった文字列を文字コード置換する


ではあかんですか。
bonif
常連さん
会議室デビュー日: 2007/05/25
投稿数: 33
投稿日時: 2007-06-20 15:38
言葉足らずで申し訳ありません。

元々やりたかった処理というのが、文字列のチェックなんです。
データベースから呼び出した文字列のコードがシフトJISなんですが、一部割り当てられてないコードが入っていることがありまして、それがあった場合に特定の文字に変換してやろうというのが目的でした。

シフトJISのコード表を見ると16進数表記だったので、文字列を16進のバイト表記にして照合しようと思ったわけですが・・・。
byte配列の件も、変換する対象が見つかってもどう変換していいのかがわからないわけで。
実際置き換える文字は(16進表記で)"8145(・)"なんですけど、これはどうやって代入すればいいのでしょうか。2byteで1文字なんで、配列要素2つ分ですよね。

まぁ、これもあすかさんの言われたことを応用すればできそうですが・・・・・
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2007-06-20 17:41
引用:

キューティーB☆O☆Nさんの書き込み (2007-06-20 15:38) より:
元々やりたかった処理というのが、文字列のチェックなんです。
データベースから呼び出した文字列のコードがシフトJISなんですが、一部割り当てられてないコードが入っていることがありまして、それがあった場合に特定の文字に変換してやろうというのが目的でした。


JDK 1.4以降であれば、
java.nio.charset.Charsetjava.nio.charset.CharsetDecoderで実現できます。

CharsetDecoder.html.decode(ByteBuffer,CharBuffer,boolean)
不正な文字の出現位置まで正確に検出できます。

変換の仕様として、Shift_JIS(Windows-31J等のバリエーションでも)の
完全な定義と比較して不正な文字を検出する必要があるのでしたら
この方法が一番確実だと思います。

が、

この方法だとかなり低水準なAPIを駆使しないといけないので、
現状を推測する限りでは難易度的に現実的ではないでしょう。

引用:

シフトJISのコード表を見ると16進数表記だったので、文字列を16進のバイト表記にして照合しようと思ったわけですが・・・。
byte配列の件も、変換する対象が見つかってもどう変換していいのかがわからないわけで。
実際置き換える文字は(16進表記で)"8145(・)"なんですけど、これはどうやって代入すればいいのでしょうか。2byteで1文字なんで、配列要素2つ分ですよね。



データベース中の不正な文字のパターンを把握していて
そのパターンの変換にのみ対応すればよいのであれば、

Shift_JISでは2バイトからなる文字の先頭バイトの
値の範囲は決まっています(Leading Byteって呼びます)。
これを見つけたら次のバイトが後続文字になるわけです。

コード:
byte []src;
int index = 0;
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
while (index < src.length) {
  if (src[index]がLeading Byteの場合) {
    buffer.write(src[index++]);
    buffer.write(src[index++]);
  } else {
    buffer.write(src[index++]);
  }
}
return new String(buffer.toByteArray(), "Shift_JIS");



という基本構造で、文字単位で処理することが出来ます。
buffer.write()したものが出力データになるので、
不正な文字を見つけたらその文字の入力データを捨てて、

buffer.write(0x81);
buffer.write(0x45);

とバッファに出力すればよいです。

実際はエラーハンドリングなども必要ですが、
基本的にはこんな方針で作れると思います。
bonif
常連さん
会議室デビュー日: 2007/05/25
投稿数: 33
投稿日時: 2007-06-20 18:34
>>あしゅさん
ありがとうございます。
byteへの書き込みの件はそれでやってみたいと思います。

不正な文字のパターンですが、どうやら一定ではないようで、見た限り数パターンあるようです。
なので、これもどうにかして解決したいと思います。
ペンちゃん
ベテラン
会議室デビュー日: 2006/08/04
投稿数: 61
投稿日時: 2007-06-20 21:08
マルチポスト先にもちゃんと報告してくださいね

http://www.javaroad.jp/bbs/answer.jsp?q_id=20070620140613667

スキルアップ/キャリアアップ(JOB@IT)