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が
表示されます。(コンパイルは出来る。)

うむ、分からない。どこが悪いのだろう???
以上

このQ&Aに関連する最新のQ&A

A 回答 (6件)

>コロン:で分けられた数字部分のみをバイト配列に格納したいのですが、そのうまい方法がわかりません。



java.util.StringTokenizer を使いましょう。

例)StringTokenizer st=new StringTokenizer(args[0],":");

これで、st.nextToken() を呼び出せば「コロンで分けられた部分」の文字列を抽出出来ます。

例)
StringTokeinzer st=new StringTokeizer(args[0],":");
String[] s=new String[st.countTokens()];
for(int i=0; i<s.length; i++){
s[i]=st.nextToken();
}

>byte mac_addr[0] = Byte.parseByte("0x".concat(str.substring(0,1))); なんて事もしてみました

public static byte parseByte(String s)

は、文字列表現を基数10として扱うものです。
この場合は、もう1つの parseByte() 。。。

public static byte parseByte(String s, int radix)

を使ってみてください。radix は基数の指定です。

例)mac_addr[0]=Byte.parseByte(str, 16);

これで、基数16として数値の文字列表現(str)を byte型に変換します。

それと、Java の byte は 127 ~ -128 の値しか取りません。ご注意を。
    • good
    • 0
この回答へのお礼

早速の回答ありがとうございます。
早速試してみました。
うまく文字列を引き出すことには成功いたし、大変感謝いたします。今まで数十行でやっていたことがたった数行で収まりました。気持ちいいですね。

ところで、str = "a5"で
>例)mac_addr[0]=Byte.parseByte(str, 16);
の時、
>それと、Java の byte は 127 ~ -128 の値しか取りません。ご注意を。
ということで、byteに格納するのは不可能となると考えました。(間違っているかな?)
こうするとうまくMACアドレスを指定できるのですが
mac_addr[0]=(byte)(0xa5);
String型の"a5"を0xa5に指定できる方法はありませんでしょうか?
以上

お礼日時:2003/07/10 23:56

>もっとスマートな方法があれは私も知りたい。



1.4 以上で可なら#5さんのコードが可読性も高いし良さそうな気がします。。。

StringTokenizer を使うか、または substring() などで数字部分のみを抽出してから parseInt() 後に byte にキャストする。。。ってのも、まぁ大まかには同じことなんでしょうけどね・w

ちょっと目先をかえるとしたら。。。

StringBuffer sb=new StringBuffer(args[0]);
int index;
while((index=sb.indexOf(":"))!=-1){
  sb.deleteCharAt(index);
}
long lg=Long.parseLong(sb.toString(),16);
byte[] b=new byte[6];
for(int i=0 ; i<b.lenght ; i++){
  b[i]=(byte)(lg>>(40-i*8));
}

って感じで、一旦区切り文字を排除してから一括で long にしてしまって、後はシフトを使って byte 配列にぶち込むってのもありかな?(それにしても可読性悪過ぎ・w)

ん、なんか話が脱線してしまいましたね。。。申し訳ない(汗
    • good
    • 0

String[] parts = "12:23:45:67:FF:AB".split(":");


byte[] macAddress = new byte[parts.length];
for(int i = 0 ; i < parts.length ; i++){
  macAddress[i] = (byte)Integer.parseInt(parts[i], 16);
  System.out.println(macAddress[i]);
}

でどうですか?

j2sdk1.4必須ですけど・・・。
    • good
    • 0

ifHex2Byteは


これでいいみたい

public static int ifHex2Byte(String sHex){
int iAns=0;
byte bHex[] = sHex.getBytes();
iAns = Character.digit(sHex.charAt(0),16);
iAns *= 16;
iAns += Character.digit(sHex.charAt(1),16);
return iAns;
}
    • good
    • 0
この回答へのお礼

ありがとうございます。
うまくいきました。
Dos窓にもキチンと格納されたMACアドレスを表示することができました。ただWindowsからフレームを送信しても
MACアドレスは指定したものにならないようです。

Jpcapドキュメント
http://www.goto.info.waseda.ac.jp/~fujii/jpcap/d …

もうしばらく格闘してみます。

以上

お礼日時:2003/07/12 00:59

もっとスマートな方法があれは


私も知りたい。

import java.util.StringTokenizer;
import java.lang.Character;


public class Test {

public static void main(String[] args) {
String sMac = "12:23:45:67:FF:AB";
byte[] bMac = ufStr2Mac(sMac);
for (int j=0; j<bMac.length; j++){
System.out.println(Integer.toHexString(bMac[j]).toUpperCase());
}
}

public static byte[] ufStr2Mac(String sMac){
byte[] bMac =new byte[6];
StringTokenizer oStringTokenizer = new StringTokenizer(sMac,":");
String sHex;
for(int j=0; j<6; j++){
sHex = oStringTokenizer.nextToken();
bMac[j] = (byte)ifHex2Byte(sHex);
}
return bMac;
}

public static int ifHex2Byte(String sHex){
int iAns=0;
byte bHex[] = sHex.getBytes();
Character cTmp = new Character(sHex.charAt(0));
iAns = cTmp.digit(sHex.charAt(0),16);
iAns *= 16;
iAns += cTmp.digit(sHex.charAt(1),16);
return iAns;
}
}
    • good
    • 0

>こうするとうまくMACアドレスを指定できるのですが mac_addr[0]=(byte)(0xa5);



mac_addr[0] に本当に望む通りの値が格納されてますか?
System.out.println() を使って確認してみて下さい。
ヒントは「ナローキャストは例外を発生させず、値が失われるだけ」

>>それと、Java の byte は 127 ~ -128 の値しか取りません。ご注意を。
>ということで、byteに格納するのは不可能となると考えました。

単に 127 までの値しか格納できないという事です。
仮にですけど、127 までの値しか使わないというのならば byte であってもかまわないでしょう(有り得るかどうかは別として・笑)
他にも、byte 配列に代入する際に 128 を引き、取り出す際に 128 を足すというルールに沿えるなら byte で済ませる事は可能でしょう。
けれど、特に理由が無ければ int 型にしておいた方が良いのではないですかね?(状況が解らず適当な発言ですが)
    • good
    • 0
この回答へのお礼

>特に理由が無ければ
詳しい状況をご説明していないのにも関わらず、回答を頂きありがとうございます。
byteにしたい理由は、Jpcapというフレーム生成キャプチャAPIを公開されている方の指定です。

http://www.goto.info.waseda.ac.jp/~fujii/jpcap/d …

ここのEthernetPacketクラスのdst_macへコマンドプロンプトから受け取った引数を格納する方法がなかなかうまいこと出来ないのです。(初めからこういったほうが話は早かったかもしれませんね。)

以上

お礼日時:2003/07/11 13:02

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qinterface,extend,implementのちがい

お世話になります、

Javaを勉強しているのですが、
interface,extend,implementの使い分けがわかりません。

私の解釈としては、
(1)interfaceは、グローバル変数の定義、グローバルメソッドの定義(実装はしない)。

(2)extendは、extendクラスを親クラスとして親クラスの機能を使用できる。

(3)implementは…,implementもextendと同じような意味だと解釈しているんですが、違う点は、implementで定義してあるメソッドは、使用しなくても、実装しなければならないという点でしょうか?

とにかくこの3つのを使い分けるコツとかあれば教えてください。
よろしくお願いします。

Aベストアンサー

バラバラに理解してもしょうがないッス。

まず、
(1)interface と implements
(2)class と extends

が対応しているわけっす。

JavaはC++と違って、比較的言語仕様を「簡単」にしたので「多重継承」という
概念がないです。
多重継承っていうのは、複数のクラスを親クラスにして継承するってことですね。

たとえば、 「TextFieldクラス」と「Japaneseクラス」を多重継承すると、
「JTextFieldクラス」ができるっていうのが自然な考え方でしょう?

まぁ、例えば、日本語クラスであれば、getStringLength()メソッドなどが
あったほうが良いでしょうか。
このgetStringLength()メソッドは、2バイト文字も1バイト文字も「1文字」
と数えてくれると言う点で、まさに、日本語クラス用のメソッドだと言えるでしょう。

例えば、Java的に記述すると、、、
class Japanese {
public int getStringLength() {
  ・・・
return strlength;
 }
 ・・・
}

class TextField {
・・・
}

class JTextField extends TextField, extends Japanese {
・・・・
}

C++ではそのように実装するでしょう。
しかし、Javaにはこのような高度な機能はありません。

そこで、生まれた苦肉の策が、「interfaceとimplements」です。

interface Japanese {
public int getStringLength(); // interfaceは実装を含まない!
                 // すなわち「実装の継承」ができるわけではない。
}

class TextField {
・・・
}

class JTextField extends TextField implements Japanese {
・・・・
public int getStringLength() {
  ・・・
return strlength; //implementsの実装を「各クラスで」実装してやる必要がある。
 }
}


結局のところ、Javaでは、複数のクラスを親クラスには持ち得ないため、継承できなかったクラスは「各クラスで実装してやる必要性」があるのです。


ではどのように使うのが効果的か?

なまえのままです。「代表的なインターフェイス」にたいしてinterfaceを使うのが良いと思います。

例えば、プレイヤー系であれば、ビデオ・コンポ・ウォークマン・などにかかわらず、
interface controlpanel {
public play();
public stop();
public next();
public back();
}
というような基本的インターフェイスを「持っているべき」です。

こうすることで、それぞれのクラス宣言の際に、これらの「インターフェイスを持っているべきであり、実装されるべきである」ということを「強く暗示」することができます。
class videoplayer extends player implements controlpanel {
public play() {・・・}
public stop() {・・・}
public next() {・・・}
public back() {・・・}
}

こうすることで、同様のクラスを作成するユーザーは、
「プレイヤー系は、4つ操作が出来るコントロールパネルをインターフェイスとして持つべきなのだな!?」という暗示を受け取り、自分のクラスでもそれを模倣するでしょう。

class mp3player extends player implements controlpanel {
public play() {・・・}
public stop() {・・・}
public next() {・・・}
public back() {・・・}
}

また、これらのクラスを使用するユーザーも、「implements controlpanel」という
表記を見て、「4つの基本操作は押さえられているのだな!」という基本中の基本動作を抑えることが出来ます。

まとめると、クラスに「こういう特徴もたしてください!」「こういう特徴持ってますよ!」という一種の暗示的警告や方向性を与えることができるわけですね。

バラバラに理解してもしょうがないッス。

まず、
(1)interface と implements
(2)class と extends

が対応しているわけっす。

JavaはC++と違って、比較的言語仕様を「簡単」にしたので「多重継承」という
概念がないです。
多重継承っていうのは、複数のクラスを親クラスにして継承するってことですね。

たとえば、 「TextFieldクラス」と「Japaneseクラス」を多重継承すると、
「JTextFieldクラス」ができるっていうのが自然な考え方でしょう?

まぁ、例えば、日本語クラスであれば...続きを読む

Qjavaでunsignedは使えないのですか?

Eclipseを使い始めた初心者です。
short型変数を符号無しで宣言しようと思ったのですが、
赤の下線が出てしまってエラーの扱いになってしまっています。

javaではunsignedは使えないのでしょうか?
使えないのであれば、その理由と対処策を教えていただけましたら嬉しいです。
宜しくお願い致します。

Aベストアンサー

unsigned short などのような構文はありませんが、とりあえず負の値を使いたくないのなら char型を数値のように使えばよろしいかと思います。
char型のとりうる範囲は0~65535で、範囲外の数値はint型とみなされます(数値を直接代入する場合のみ)。
ただし負のintをcharにキャストすると上位ビットが欠落します。

char c;
c = 0;
c = 65535;
c = 65536; ←コンパイルエラー
c = -1; ←コンパイルエラー
c = (char)-1; ←コンパイルエラーにはならないが65535になる

Qファイルやディレクトリの存在確認を行う方法

ファイルをオープンするのはfopenでOKですが、ファイルやディレクトリの存在確認を行う方法が知りたいです。

何か組み合わせて作るものなのでしょうか?
perlとか便利な演算子があるのですが、C/C++って器用ではないですね。
これは処理系?依存の内容ですか?

私の環境は VC6, VC2005 Windows2000です。

Aベストアンサー

int access(const char* path, int mode);
int stat(const char* path, struct stat* sb);

かな?
MSDN を引くと _access_s() を使えとか書いてあるけど。


人気Q&Aランキング

おすすめ情報