• ベストアンサー

byte型のマイナスの扱いについて

COMポートを使用して通信をしようとしています。 制御コマンドを1byte区切りで送信するのですが、byte型で扱う際、-128~-1の扱いが思うようにいきません。 ウェブを検索して符号拡張など検討してみたのですが解決できませんでした。 いろいろやってみましたが、基本的には byte[] byteArray = {0x12,0x20,-0x80}; String str = new String(byteArray,0); BufferedWriter bw; bw.write(str); このようになっています。 0x12や0x20の送信は、信号を調べる機器にて正しく送信されていることが確認できたのですが、-0x80は予期せぬ値になってしまいます。 -0x80では、16進でC0,3Fなどになってしまいます。 二進で先頭に1がたっていることが原因なのでしょうか。。。 int型にしたり、byte型そのままで送ったり、0x40から左にビットシフトして(&ffも忘れずに)代入したりもしたのですが、結果は同じでした。 ご教授宜しくお願いします!

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

  • ベストアンサー
  • liar_adan
  • ベストアンサー率48% (730/1515)
回答No.1

こちらで実験してみました。 たしかに変な数値になります。 実際にどういう仕組でおかしくなっているのかはわかりません。 しかし、おそらく出力にWriterを使っているのが問題だろうと思われます。 Javaの出力には、OutputStream系列と、Writer系列があり、 バイナリデータはOutputStream、テキストファイルはWriterと、 使い分けをすることになっています。 Writer系列では、おそらく内部で1回Unicodeに変換されるので、 その過程でエラーが出たのだろうと思います。 見たところ、出力したいのはバイナリデータのようなので、 プログラム中でWriterを使っているところを OutputStreamに置き換えることをお勧めします。 もしそれが難しければ、OutputStreamとWriterをつなぐ OutputStreamWriterの使用も検討してみてください。 --------------------------- (たぶん正常に動くコード) byte[] byteArray = {0x12,0x20,-0x80}; try{ FileOutputStream fo = new FileOutputStream("test.out"); BufferedOutputStream bw = new BufferedOutputStream(fo); bw.write(byteArray, 0, 3); bw.flush(); }catch(Exception e){} -----------------------------

mitmit
質問者

お礼

ありがとうございます! 早速試してみたいと思います!!

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (1)

  • deadlock
  • ベストアンサー率67% (59/87)
回答No.2

#1さんの仰るとおり、OutputStreamを使用することで解消されます。 予期しない値に変換される箇所は、Writerの内部ですね。 3Fは文字で言うと'?'あたります。順を追っていくと、 > byte[] byteArray = {0x12,0x20,-0x80}; この3つの値は、2行目のnew Stringでcharに変換されます。3つ目の文字は文字に変換できない値になります。(一文字目も見慣れない文字になりますが、サポート内のようですね) > String str = new String(byteArray,0); コンストラクタString(byte[], int)第一引数を2バイト目のビット列に、第二引数を1バイト目のビット列に使用してcharを作成します。APIにあるとおり、第一引数のバイト列はascii文字に使用可能な値をとる必要があります。 > BufferedWriter bw; > bw.write(str); writerがOutputStreamにバイト列として書き出す際に、文字コードの変換が行われます。この際、変換できない値はすべて'?'に置き換えられます。'?'がビット列になって送信されるので、相手には0x003Fという値が送信されることになります。 もう一度短く書くと、 new Stringで-0x80は文字として不正な値になる →writeで'?'に変換される →streamには'?'がビット列になったものが送信される →相手に0x00CFで届く という流れになります。

mitmit
質問者

お礼

本日意図するとおりに通信することができました。 ありがとうございました!!

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • String型をbyte型へ

    MACアドレス(16進数) 00:00:00:00:00:01 これが引数で指定される。 String str = args[0]; というものがありまして(String型)、 そのコロン:で分けられた数字部分のみをバイト配列に格納したいのですが、そのうまい方法がわかりません。お助けください。 byte mac_addr[0] = Byte.parseByte("0x".concat(str.substring(0,1))); なんて事もしてみましたが、NumberForamtExceptionが 表示されます。(コンパイルは出来る。) うむ、分からない。どこが悪いのだろう??? 以上

    • ベストアンサー
    • Java
  • [VB.net] StringからByte配列への変換

    皆さんこんばんは。 最近VB.NET2000でVisual Basicをはじめたのですが、どうにもString型の値をByte配列へ変換するやり方が分かりません。 VB6.0だとByte配列にStringを代入するだけでいいそうなのですが、.NETで代入しようとすると『型"String"の値を"Byteの1次元配列"に変換できません』というビルドエラーが表れてしまいます。 CByte( Mid(str,i,1) ) CLng( Mid(str,i,1) ) 他にも上記コードのように一つずつ変換しようと試みたのですが、String中のある文字がワイドバイトらしく、System.InvalidCastExceptionが表れてしまいます。 ("『"を上下反転したような文字) ワイドバイトのStringを1バイトずつ区切ってByte配列やLong配列へ格納する手法というものはありませんでしょうか。 よろしくお願いします。

  • javaプログラム初心者です。

    入力ファイルの内容をWebサーバプログラムへ送信し、サーバからの応答を別ファイルに出力するクライアントプログラムを作っているのですが、出力ファイルにはなにも書き込みがされていません。(サーバからの応答は事前に不明でその長さが可変長である) 以下が作ったプログラムです。間違っているところを詳しくご指摘いただけるとありがたいです。お願いします。 import java.net.*; import java.io.*; public class client{ static final int BUFSIZE = 1792; public static void main(String[] args){ try{ String server = args[0]; //接続先のIPアドレス File file1 = new File(args[1]); //入力ファイル(HTTPリクエスト) FileReader filereader = new FileReader(file1); BufferedReader br = new BufferedReader(filereader); int serverport = Integer.parseInt(args[2]); //ポート番号 File file2 = new File(args[3]); //サーバからの応答をファイルに書き込む用 FileWriter filewriter = new FileWriter(file2); BufferedWriter bw = new BufferedWriter(filewriter); byte[] bytebuffer = new byte[BUFSIZE]; String str; while((str = br.readLine()) != null){ //入力ファイルの内容を1行ずつ読み込む bytebuffer = str.getBytes(); //入力ファイルの文字列をバイトに変換 } Socket socket = new Socket(server,serverport); //ソケットの生成 System.out.println("Connected to server...sending echo string"); InputStream in = socket.getInputStream(); //入出力ストリームの取得 OutputStream out = socket.getOutputStream(); out.write(bytebuffer); //文字列を送信 int receive; while((receive = in.read(bytebuffer))!=-1){ bw.write(new String(bytebuffer)); //サーバからの応答をファイルに出力 } bw.close(); socket.close(); }catch(IOException e){ } } }

  • [再質問]VC#で2進数の文字列をバイト列に変換する方法

    No.1029439で質問して回答頂きましたが、もう一度お願いします。 string strに2進数の文字列がNバイト分入っているとします(0か1が8×N個入っている)。これを1バイト分ずつbyte型の配列に入れたいです。 例えば、str = "1010111100101100"と2バイト分入ってるときは、byte型の配列bytesに bytes[0] =0xAF(10101111) bytes[1] =0x2C(00101100) となるようにしたいです。 最終的には↓のようにして、文字を出力したいためです。 Encoding sjisEnc = Encoding.GetEncoding("Shift_JIS"); string str = sjisEnc.GetString(bytes); http://www.atmarkit.co.jp/fdotnet/dotnettips/011byte2str/byte2str.html よろしくお願いします。

  • ネットワークプログラミングでの読み込みについて

    現在ネットワークプログラミングの勉強をしています。 クライアント側の標準入力で文字列入力→Enter押下→ サーバ側の標準出力でその文字列を出力 という処理を行いたいのですが、サーバ側の出力が表示されません。 まず具体的にソースを出した方が状況を説明しやすいので、提示致します。 ------------------------------- サーバ側 public static void main(String[] args)throws Exception ServerSocket ss=new ServerSocket(7777); while(true){ sock=ss.accept(); BufferedReader br=new BufferedReader(new InputStreamReader(sock.getInputStream())); String str=br.readLine(); if(str.equals("end"))break; System.out.println(str); } sock.close(); ss.close(); br.close(); } ---------------------------------- クライアント側 public static void main(String[] args)throws Exception { Socket sock=new Socket(コンピュータ名,7777); while(true){ BufferedWriter bw=new BufferedWriter(new InputStreamReader(sock.getOutputStream())); BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); String str=br.readLine(); bw.write(str); bw.flush(); if(str.equals("end"))break; } bw.close(); sock.close(); ---------------------------------- 自分で色々試したところバッファリングで入力された文字列を溜めたまま 吐き出していないのが原因のような気がするのですが、BufferedReader#readLineのドキュメントを見ると >1 行のテキストを読み込みます。1 行の終端は、改行 (「\n」) か、復帰 (「\r」)、または復行とそれに続く改行のどれかで認識されます。 とあるのでクライアント側のbw.write(str)の後にbw.newLine()を呼んだりstr+="\n" などを行ってみたところ、 サーバ側は最初の入力をすぐに出力し、その後のクライアントからの入力には無反応になりました。 このようになる原因と解決が分かる方居ましたら、教えてください。

    • ベストアンサー
    • Java
  • charで宣言した変数をstringへの代入で

    wchar_t cOrg[128]と宣言している変数にstringで宣言しているstrを cOrg[i] = str[i]; このように代入することはできたのですが、 char cAns[ 128 ]; このように宣言した変数の値をstrの41番目と42番目に 次のように入れようとするとエラーが出ます。 str[41]=cAns[1]; str[42]=cAns[2]; (エラー内容) \Form1.h(428): error C2664: 'System::String::String(wchar_t,int)' : 1 番目の引数を 'wchar_t [128]' から 'wchar_t' に変換できません。(新しい機能 ; ヘルプを参照) このような代入はできないのでしょうか? プログラムの詳細は下のようなものです。 wchar_t cOrg[128],*p; String^ str; String^ str2; int i; int iVal1,iVal2,iTotal = 0,iHosu; char cAns[ 128 ]; str = this->textBox1->Text; for(i=0;i<41;i++) { cOrg[i] = str[i]; } -------(中略)------------------------------------------ iHosu = ~iTotal; // 1の補数 iHosu++; // +1 iHosu = iHosu & 0x00FF; sprintf( cAns, "%s%02X%c", cOrg, iHosu, 0x22 ); str[41]=cAns[1]; str[42]=cAns[2];

  • 2010 excel マクロ 記号の変化

    エラー発生で強制終了になってしまいます。2007年のexcelで作成したものですが、2010だと強制終了になってしまいます。 内容は□をダブルクリックすると■になるように作っています。 記述は2003年からのマクロ記述なので、変化が必要なのでしょうか? Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) 'Private Sub Worksheet_SelectionChange(ByVal Target As Range) 'セルをダブルクリックすると、・→○→△→×→・と変更する。 Dim S1 As String Dim S2 As String Dim S01 As String Dim S02 As String Dim S03 As String Dim S04 As String S1 = "□" S2 = "■" S01 = "・" S02 = "○" S03 = "△" S04 = "×" On Error GoTo ERR_12 sCheckXY S1, S2 sCheckX1234 S01, S02, S03, S04 sChangeXY S1, S2 Exit Sub ERR_12: End End Sub Sub sChangeXY(X As String, Y As String) '選択セルに□があれば■に変える Dim Str0 As String 'str1の左端 Dim Str1 As String 'strの右側更新 Dim Str2 As String 'strの左側更新 Dim Str20 As String 'strの左側一部保存 Dim L As Long Dim M As Long Dim N As Long Str1 = ActiveCell.Text L = Len(Str1) Debug.Print L If L = 0 Then End End If For N = 1 To L Debug.Print Str2 Str0 = Left(Str1, 1) If Str0 = X Or N = L Then If Str20 <> "" Then If N = L Then Str20 = Str20 + Str0 End If If MsgBox(Str20 & "  はチェックしますか?", vbYesNo, "選択肢") = vbYes Then Str2 = Str2 + Replace(Str20, X, Y) Str20 = Str0 Else Str2 = Str2 + Replace(Str20, Y, X) Str20 = Str0 End If Else Str20 = Str0 End If Else Str20 = Str20 + Str0 End If Str1 = Right(Str1, L - N) Next N ActiveCell.Value = Str2 End Sub Sub sCheckXY(X As String, Y As String) '選択セルがXならY,YならXにチェックをかえる If ActiveCell.Text = X Then ActiveCell.Value = Y End ElseIf ActiveCell.Text = Y Then ActiveCell.Value = X End End If End Sub Sub sCheckX1234(X1 As String, X2 As String, X3 As String, X4 As String) '選択セルがXならY,YならXにチェックをかえる If ActiveCell.Text = X1 Then ActiveCell.Value = X2 End ElseIf ActiveCell.Text = X2 Then ActiveCell.Value = X3 End ElseIf ActiveCell.Text = X3 Then ActiveCell.Value = X4 End ElseIf ActiveCell.Text = X4 Then ActiveCell.Value = X1 End End If End Sub

  • javaプログラミング

    javaとYahooのWebサービスを利用して、検索結果のxmlを取り出し、 ○○.xmlという引数を与えて、結果を書き出そうとしていますが、 以下のプログラムだと文字(日本語)が化けてしまいます。 どうにかして文字化けせず取り出すことはできないでしょうか。 よろしくおねがいします。 import java.io.BufferedWriter; import java.io.FileWriter; import java.io.InputStream; import java.net.URL; public class YahooWebServiceExample { public static void main(String[] args) { String request = "http://api.search.yahoo.co.jp/WebSearchService/V1/webSearch? appid=web_research&query=%e6%b2%96%e7%b8%84&results=2"; try { // ファイル出力ストリームを取得(第二引数) BufferedWriter bw = new BufferedWriter(new FileWriter(args[0])); URL url = new URL(request); InputStream in = url.openStream(); byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { for (int i = 0; i < len; i++) { System.out.print((char) buf[i]); bw.write(buf[i]); } } in.close(); bw.close(); } catch (Exception e) { System.out.println("Web services request failed"); } } }

    • ベストアンサー
    • Java
  • Tera Termを使ったマイコンとの通信

    H8/3048Fと通信をしようと思い、「Tera Term」を使ってみたのですが、 下のプログラムを実行してもTera Termに何も表示されません(COMの番号はしっかり確認しました) while( 1 ){ ITU0.TCNT = 0; while( ITU0.TCNT < 40000 ); counter++; if( counter > 100 ){ if( P4DR == 0x00 ){ //LEDを点滅させる(確認用) P4DR = 0x10; } else{ P4DR = 0x00; } while( ( SCI0.SSR.BYTE & 0x80 ) == 0 ); SCI0.TDR = 'A'; //Aを送信する SCI0.SSR.BYTE &= ~0x80; counter = 0; } } SCI0の設定は int i; SCI0.SCR.BYTE = 0x00; SCI0.SMR.BYTE = 0x00; SCI0.BRR = 51; for( i = 0 ; i < 1000 ; i++); i = SCI0.SSR.BYTE; SCI0.SSR.BYTE = 0x80; SCI0.SCR.BYTE = 0x30; となっております。 このプログラムを実行すると確認用のLEDは点滅しますが、Tera Termには何も表示されません。 どこか間違っているところなどがあれば教えていただけないでしょうか? ちなみに、使用しているOSはWindows7です。 よろしくお願いします。

  • VBで自身の研究用にグラフ描写ソフトを作成中ですが、行き詰ってます

    VB2008で研究用ソフトの作成をしています。 数式を入力しそのグラフを書く、と言ったものを作ろうとしているのですがうまくいきません。 たとえば、TextBox1に何か数値を入力したとして、 Dim str As String = textbox1.text Dim num As Decimal = Decimal.Parse(str) とすれば確かにnumはInt型で計算ができるのですが、同様にy=3*xのグラフを入力してそのxに-1から1までの数値を代入させて点を取りたいとき、この方法ではどうにもできずに困っています。 たとえば上の例では、3*xを入力した後xに好きな値を代入できるようにするようにはどうしたらできるのでしょうか? 説明がわかりにくくてすみません。よろしくお願いします。