Wi-Fi接続時のIPアドレスをJavaで取得したい


まずやってみたこと

InetAddress.getLocalHost()を使ってみる

 とりあえずググってみたらこちらのページが出てきました。
 http://www.yukun.info/blog/2008/10/java-inetaddress-getlocalhost.html

 丸コピしてそのまま走らせてみた結果です。何やら見覚えの無いIPアドレスが出力されました。
 

 首を傾げならコマンドプロンプトを立ち上げipconfig。

 「誰だお前はァ!」

 他の環境でどうなるかは知りませんが、少なくともこのマシンではInetAddress.getLocalHost()を使ってもWi-FiのIPは取得できないことがわかりました。ググり続けてもAndroidの記事しかヒットしないので、ゴリ押しでもなんでも別の手法を考えなければいけないようです。

WindowsのOSコマンドipconfigをJavaで使ってみる

 コマンドプロンプトで見れるんだからこれをJava側でわちゃわちゃできりゃいんじゃね、と思い付き試してみることに。
 C言語で言うSystem()がJavaにもあるはずだとググってみました。

 http://d.hatena.ne.jp/takami_hiroki/20101221/p1

 これをベースに、OSコマンドipconfigによる出力を取得して表示すると……

 はい、そうでした。日本語版Windowsのコマンドプロンプトで使われている文字コードはShift-JISです。出力や取得後の文字列をUTF-8にできないか粘ってみましたが、私が雑魚だからかそれとも仕様なのか叶うことはありませんでした。

<追記>
@KIchiro さんからコメント欄にて助言をいただきました。取得した実行結果は任意の文字コードで文字列にできるようです。ここから下の記事は読み飛ばしてコメント欄をご覧ください。私が費やした4日間はなんだったのか……

ワンクッション置いてみる

 調べていくうちに「Shift-JISで書かれたテキストファイルは読み込める」ことが判明しました。
 「ipconfig > ip.txt」を実行して生成されたテキストファイルを使えばいいわけです。流れとしては

   ipconfig > ip.txt
   ↓
   文字コードをShift-JISに指定してip.txt読み込み
   ↓
   indexOf()やらsplit()やらを使って検索
   ↓
   何食わぬ顔でip.txtを削除

 といったところでしょうか。

落とし穴

 ここで注意する必要があるのは、OSコマンドを叩く本体側と叩かれて結果を返す書き出し側が並列処理になる点です。書き出し側のプロセスが終わるのを待たないで読み込みに入ると当然IOException先生が来てしまいます。

サンプル

Main.java

public class Main {
    public static void main(String[] args) {
        System.out.println(new getWiFiIP().get());
    }
}

getWiFiIP.java

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;


public class getWiFiIP {

    private String ip="";

    public String get(){
        return ip;
    }


    public getWiFiIP() {

        try {

            ProcessBuilder pb=new ProcessBuilder("cmd.exe", "/c", "ipconfig",">","ip.txt");

            Process process = pb.start();   //プロセスの開始
            process.waitFor();              //書き出しが終わるまで待機

            ArrayList<String> list=new Text_read("ip.txt").getText(); //テキストファイル読み込み


            int cnt=list.indexOf("Wireless LAN adapter Wi-Fi:");////////////////////////////////////////////////
            for(;;){
                if(list.get(cnt).indexOf("IPv4")==-1){
                    cnt++;
                }else{
                    break;
                }                                 //読み込んで取得した文字列群からWi-Fi接続のIPアドレス(IPv4)を検索する
            }////////////////////////////////////////////////////////////////////////////////////////////////////


            String[] temp=list.get(cnt).split(":"); //「IPv4 アドレス . . . . . . . . . . . .: ×××.×××.×××.×××」となっているので分割する
            ip= temp[1];                            //取得したIPアドレスを代入

            new File("ip.txt").delete();            //しれっとip.txtを削除

       ////////////////////////////////////////////////////以下エラー処理
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        if(ip.equals(""))ip= "取得に失敗しました";
    }
}


Text_read.java


import java.io.*;
import java.util.ArrayList;

/////////////////////////////////////////////////////////
//テキストファイルを丸ごと読み込みArrayListへ格納する。//
/////////////////////////////////////////////////////////


public class Text_read {

    private ArrayList<String>text=new ArrayList<String>();      //格納用ArrayList

    public Text_read(String path/*ファイルパス*/){

        try {
            BufferedReader br =new BufferedReader(new InputStreamReader(new FileInputStream(path), "Shift_JIS"));
            for(;;){
                text.add(br.readLine());
                if(text.get(text.size()-1)==null){              
                    text.remove(text.size()-1);                 
                    break;
                }
            }
            br.close();
        }catch(IOException e){
            System.out.println("入出力エラー");
        }
    }

    public ArrayList<String> getText(){
        return text;                                            
    }

}


 これでとりあえず解決はしましたが、もっと簡単な方法を知っている方がいれば教えてください……

<追記>
@KIchiro さんありがとうございました。