• ベストアンサー

readLine()時に表示される□(四角)の意味(文字コードの問題?)

FLASHのソケットから文字列をJAVAで作った サーバで受け取りますが、 必ず一文字目に□(四角)が表れます。 これは何を意味しているのでしょうか。trim()を 使っても取れません。 (FLASHのコード) xmlsocket.send("Hello!!\r"); (JAVAのコード) str=mybufferedreader.readLine(); こんな感じです。 FLASHは、Shift-JISか、UTF-8で文字列を送って います(おそらくShift-JIS)。 なにか分かることがありましたらお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.4

 #1です。  \0、CやC++で使うヌル文字のようですね。  たぶん、Flashの xmlsocket.send() が一回に送る文字列の終端を表すためにヌル文字を付加しているのではないでしょうか。  もし、そうなら、Javaではヌル文字を使わないので、どうにかしなくてはいけないでしょう。  対策としては、 1.ヌル文字 \0を探して、削除していく。 2.逆に利用しちゃう。  2.がおもしろそうです。  というのも、BufferedReaderのreadLine()で文字列を受け取っていると、もし、Flashのクライアントが改行を付け忘れると、送った文字列はBufferedReaderのバッファの中に貯まってしまい次に改行が来るまで、出てきません。  まあ、忘れないようにクライアントを作ればいい話ですが、せっかく、フラッシュが有無を言わさず\0を付けてくるなら、これを区切りにしてしまった方がいいのではないでしょうか。  サンプル作ってみました。  例によってテキストファイルですが、Flashから "abc\0"、"こんにちは\0"、"def\0" とメッセージが来ていると思って、見てください。  readString()メソッドは、BufferedReaderのreadLine()みたいな感じで使います。 import java.io.*; public class NullTest {   InputStreamReader in;      public static void main(String[] args) {     try {       //Test.txtに"abc\0こんにちは\0def"を書き込む       OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream("Test.txt"), "Shift_JIS");       try {         ow.write("abc\0こんにちは\0def\0");       }       catch (IOException ex) {         ex.printStackTrace();       }       finally {         ow.close();       }              NullTest nt = new NullTest();       try {         String s;         //readString()メソッドを使って1メッセージ毎に読み込む         while ((s = nt.readString()) != null) {           System.out.println(s);         }       }       catch (IOException ex) {         ex.printStackTrace();       }       finally {         nt.in.close();       }     }     catch (IOException ex) {       ex.printStackTrace();     }   }      public NullTest() throws FileNotFoundException, UnsupportedEncodingException {     in = new InputStreamReader(new FileInputStream("Test.txt"), "Shift_JIS");   }      //ヌル文字までを一つの文字列として返すメソッド   public String readString() throws IOException {     StringBuffer sb = new StringBuffer();     int c;     while (true) {       c = in.read();       if (c > 0)         sb.append((char)c);       else         break;     }          if (sb.length() > 0)       return sb.toString();     else       return null;   } }

noname#10667
質問者

お礼

いろいろありがとうございます。 謎が解けました。 FLASHがらみなので無理かと思いましたが、 質問してみて、よかったと思います。

その他の回答 (3)

  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.3

 再び#1です。  今度は、Readerを通した場合です。  ReaderがUTF-8をUTF-16に変換してくれます。 import java.io.*; public class CharSetTest {   public static void main(String[] args) {     try {       InputStreamReader ir = new InputStreamReader(new FileInputStream("Test.txt"), "UTF-8");       try {         int c;         while ((c = ir.read()) > -1) {           System.out.print(Integer.toHexString(c) + " ");         }         System.out.println();       }       catch (IOException ex) {         System.out.println("入出力エラー");         ex.printStackTrace();       }       finally {         ir.close();       }     }     catch (FileNotFoundException ex) {       System.out.println("ファイルが見つからない");       ex.printStackTrace();     }     catch (IOException ex) {       System.out.println("ファイルを閉じることができない");       ex.printStackTrace();     }   } }  結果はこうなります。 feff 61 62 63  0xFEFF がBOMです。  0x61がa、0x62がb、0x63がcです。  UTF-16になったのでBOMは変換され2バイトになりました。  a,b,cは変わってないように見えますが、実際は1バイトから2バイトに変わっています。  私は、BOMが出てきた場合は、めんどくさいけど、取っています。 String s = br.readLine(); if (s.charAt(0) == 0xFEFF)   s = s.substring(1); System.out.println(s);  もっとスマートな方法があるのかも知れません。  参考になればよいのですが・・・。

noname#10667
質問者

お礼

最初はコードが間違っていました。 toHexString()で受けると、最初の□は無視されます。 read()で受け、16進数でコード表示すると 61 62 63 d 0 となります(16進数表示の仕方 だけでも勉強になりました)。 それと、最初の一行目には、□が出ないことが 分かりました。 したがって、恐らく、BOMではないと思います。 改行部分(\r)がd一文字であること、最後に 0(0バイト,文末?)があること、から、 改行後に、FLASH側で、なにかを送り、これが、 次のreadLine()の頭にきているのではないかと 思うのですが。どうでしょうか。 もしかしたらFLASH特有なのかもしれませんが。

  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.2

 #1です。 >[B@1d62270(UTF-8),[B@16f0be8(Shift_JIS)などと >表示されます。  配列の toString()ってなんでしたっけ?  ハッシュが出て来るんでしたっけ?  ちょっと、よくわからないので、サンプルコードを作ってみました。  Windows XP のメモ帳で「abc」と書いて、UTF-8でTest.txtとして保存しました。  これを読み込み、1byteごとに16進数で表示します。  ここでは、FileInputStreamを使っていますが、Socketから取得したInputStreamに読み替えてみてください。 import java.io.*; public class CharSetTest {   public static void main(String[] args) {     try {       FileInputStream fs = new FileInputStream("Test.txt");       try {         int c;         while ((c = fs.read()) > -1) {           System.out.print(Integer.toHexString(c) + " ");         }         System.out.println();       }       catch (IOException ex) {         System.out.println("入出力エラー");         ex.printStackTrace();       }       finally {         fs.close();       }     }     catch (FileNotFoundException ex) {       System.out.println("ファイルが見つからない");       ex.printStackTrace();     }     catch (IOException ex) {       System.out.println("ファイルを閉じることができない");       ex.printStackTrace();     }   } }  その結果が↓です。 ef bb bf 61 62 63  0xEFBBBFがUTF-8でのバイトオーダーマークです。  0x61がa、0x62がb、0x63がcです。  UTF-8では最初の128文字が1バイトで表せる分、後ろにあるバイトオーダーマークは3バイトになります。  これがReaderを通さずにした場合です。  最初の3バイトが 0xEFBBBF なら文字コードはUTF-8で最初にあるのはBOMでいいと思います。

  • PecoPlus
  • ベストアンサー率76% (144/188)
回答No.1

 こんにちは。  Flash のソケットについてはよくわからないのですが、エンコードが「UTF-8」でお節介にも「バイト・オーダー・マーク」ってやつを付けてきているという事じゃないですかねぇ。  一文字目を調べてみてください。  0xFEFF だったら、これです。  Windows Xp のメモ帳が UTF-8 で保存すると、これを付けて来るんです。  いらないはずなのに、邪魔です。  最初の文字が 0xFEFF だったら、削っているんですけど、もっといい方法があるのかも知れません。  あっているといいのですが・・・。

参考URL:
http://www.atmarkit.co.jp/aig/01xml/bom.html
noname#10667
質問者

お礼

回答ありがとうございます。 出来る限りで、□をとり、getBytes()メソッドで、 UTF-8,Shift_JISでバイト配列を得、textareaに 表示すると、 [B@1d62270(UTF-8),[B@16f0be8(Shift_JIS)などと 表示されます。なにか分かるでしょうか。

関連するQ&A