web-dev-qa-db-ja.com

JavaでのIPv4文字列の検証

以下のメソッドは、文字列が正しいIPv4アドレスである場合に検証を行い、有効であればtrueを返します。正規表現とエレガンスの改善は大歓迎です:

public static boolean validIP(String ip) {
    if (ip == null || ip.isEmpty()) return false;
    ip = ip.trim();
    if ((ip.length() < 6) & (ip.length() > 15)) return false;

    try {
        Pattern pattern = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
        Matcher matcher = pattern.matcher(ip);
        return matcher.matches();
    } catch (PatternSyntaxException ex) {
        return false;
    }
}
44
Mat B.

以下は、読みやすく、効率がやや劣る方法です。

public static boolean validIP (String ip) {
    try {
        if ( ip == null || ip.isEmpty() ) {
            return false;
        }

        String[] parts = ip.split( "\\." );
        if ( parts.length != 4 ) {
            return false;
        }

        for ( String s : parts ) {
            int i = Integer.parseInt( s );
            if ( (i < 0) || (i > 255) ) {
                return false;
            }
        }
        if ( ip.endsWith(".") ) {
            return false;
        }

        return true;
    } catch (NumberFormatException nfe) {
        return false;
    }
}
53
rouble

UPDATE:Commons-HttpClientおよびその後続のHttpComponents-HttpClientは、この機能を採用しています。 InetAddressUtils.isIPv4Address(Str)のように、このバージョンを利用できます。


開発バージョンの Apache Commons Validator には InetAddressValidator クラスがあり、このクラスには isValidInet4Address(String) メソッドが実行されます指定されたStringが有効なIPv4アドレスであることを確認するためのチェック。

ソースコード は、リポジトリから表示できます。そのため、改善のアイデアがある場合は、改善のアイデアを提供できます。

提供されているコードを一目見れば、メソッドがメソッドの呼び出しごとにPatternをコンパイルしていることがわかります。 Patternクラスをstaticフィールドに移動して、各呼び出しでのコストのかかるパターンコンパイルプロセスを回避します。

46
coobird

IPv4とIPv6の両方のサポートをサポートするリリースバージョンのライブラリを使用する場合は、 Guava を使用できます。

boolean isValid = InetAddresses.isInetAddress("1.2.3.4");
21
Stefan L

Java 8ストリームを使用して、アドレスがドットで区切られた0〜255の正確に4つの数字で構成されていることを確認するソリューションを次に示します。

public class IpValidation {

    /**
     * Check that a string represents a decimal number
     * @param string The string to check
     * @return true if string consists of only numbers without leading zeroes, false otherwise
     */
    public static boolean isDecimal(String string) {
        if (string.startsWith("0")) {
            if (string.length() == 1) {
                 // "0"
                 return true;
            }
            // The string has a leading zero but is not "0"
            return false;
        }
        for(char c : string.toCharArray()) {
            if(c < '0' || c > '9') {
                return false;
            }
        }
        return true;
    }

    public static boolean isIp(String string) {
        String[] parts = string.split("\\.", -1);
        return parts.length == 4 // 4 parts
                && Arrays.stream(parts)
                .filter(IpValidation::isDecimal) // Only decimal numbers
                .map(Integer::parseInt)
                .filter(i -> i <= 255 && i >= 0) // Must be inside [0, 255]
                .count() == 4; // 4 numerical parts inside [0, 255]
    }
}
15
Raniz

_www.example.com_のような無効なIPアドレスでDNS解決を使用しても構わない場合は、 InetAddress メソッドを使用して次を確認できます。

_public static final boolean checkIPv4(final String ip) {
    boolean isIPv4;
    try {
    final InetAddress inet = InetAddress.getByName(ip);
    isIPv4 = inet.getHostAddress().equals(ip)
            && inet instanceof Inet4Address;
    } catch (final UnknownHostException e) {
    isIPv4 = false;
    }
    return isIPv4;
}
_

メソッドは、それがInet4Addressのインスタンスであるかどうか、およびパラメーターがホスト名ではなくip-addressであったかどうかを確認します。パラメーターとして多くのホスト名が必要な場合、この実装ではDNSを使用して解決を試みることに注意してください。これはパフォーマンスの問題になる可能性があります。

それ以外の場合、boolean Sun.net.util.IPAddressUtil.isIPv4LiteralAddress(String src)にピークがあり、そこでIPv4チェックのためにStringがどのように解析されるかがわかります。

14

this から正規表現の例を見つける

package com.mkyong.regex;

import Java.util.regex.Matcher;
import Java.util.regex.Pattern;

public class IPAddressValidator{

    private Pattern pattern;
    private Matcher matcher;

    private static final String IPADDRESS_PATTERN = 
        "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
        "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
        "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
        "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";

    public IPAddressValidator(){
      pattern = Pattern.compile(IPADDRESS_PATTERN);
    }

   /**
    * Validate ip address with regular expression
    * @param ip ip address for validation
    * @return true valid ip address, false invalid ip address
    */
    public boolean validate(final String ip){         
      matcher = pattern.matcher(ip);
      return matcher.matches();             
    }
}
7
bigspawn

考えてみると、このソリューションは非常にエレガントですが、理解するには少し時間がかかります。

基本的な考え方は、サブストリングを取得し、それを検証することです。
サブストリングの開始は常に最後の1に1を足したものになるため、xとyを切り替えます。

このソリューションは、正規表現バリアントよりも約20倍高速で、分割よりも2倍高速です。

public static boolean validIP(String ip) {
    if(ip == null || ip.length() < 7 || ip.length() > 15) return false;

    try {
        int x = 0;
        int y = ip.indexOf('.');

        if (y == -1 || ip.charAt(x) == '-' || Integer.parseInt(ip.substring(x, y)) > 255) return false;

        x = ip.indexOf('.', ++y);
        if (x == -1 || ip.charAt(y) == '-' || Integer.parseInt(ip.substring(y, x)) > 255) return false;

        y = ip.indexOf('.', ++x);
        return  !(y == -1 ||
                ip.charAt(x) == '-' ||
                Integer.parseInt(ip.substring(x, y)) > 255 ||
                ip.charAt(++y) == '-' ||
                Integer.parseInt(ip.substring(y, ip.length())) > 255 ||
                ip.charAt(ip.length()-1) == '.');

    } catch (NumberFormatException e) {
        return false;
    }
}

IPが間違っていることがわかっている場合は、最初のifの下に次のコードを追加することを検討してください。これにより、コードは1.5倍遅くなりますが、エラーが発生した場合は700倍改善します

    for (int i = 0; i < ip.length(); i++) {
        if (!Character.isDigit(ip.charAt(i)) && ip.charAt(i) != '.') return false;
    }
5
arcs

回答のほとんど(Michael Konietzkaの回答を除く)は間違っています。たとえば、10.8は有効なIP4アドレスです(10.0.0.8の省略形)。

See IPアドレスのテキスト表現 Java仕様。

リファレンスに見られるように、数値表現を確認するために、1〜4個のパーツが存在する場合があり、それぞれのパーツに異なる制限が適用されます。

4

質問でコードを使用する場合、次の行を変更する必要があります。

if ((ip.length() < 6) & (ip.length() > 15)) return false;

if ((ip.length() <= 6) || (ip.length() > 15)) return false;
4
jtbr

IPv4に次の正規表現を使用してみてください

String ip4Regex="^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})(\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})){3}$";

それが役に立てば幸い :)

3
bane19

適切な方法は、IPAddressクラスを構築し、IPアドレスの文字列表現を与えることでインスタンス化することだと思います。

このようにして、さまざまな検証手順をインスタンスメソッドに分割し、いくつかの 懸念の分離 を取得できます。

たとえば、これは通常、独自のメソッドであり、単にisEmptyと呼びます:

return (ip == null || ip.isEmpty());

また、これは別のメソッドである必要があり、これをhasProbableLengthと呼ぶことができます。

ip = ip.trim();
return ((ip.length() < 6) & (ip.length() > 15));

ここにはたくさんのことが起こっています。これを分割して、おそらく正規表現を完全にスキップしようとします。

try {
    Pattern pattern = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
    Matcher matcher = pattern.matcher(ip);
    return matcher.matches();
} catch (PatternSyntaxException ex) {
    return false;
}

最初にドットで文字列を分割し、正確に4つのグループが取得されることを確認します。このメソッドを呼び出すdivideIntoGroups

次に、各グループが0〜255の値であることを検証します。このメソッドを呼び出しますvalidateGroups

これで、このクラスを拡張してIPがlocalhostであるか、ブロードキャストアドレスであるかを検索したい場合、これを行うのは非常に簡単です。これが 懸念の分離 が与えるものです。

また、IPアドレス文字列の検証で検証ルールのどれが破られたかを正確に伝えることもできます。正規表現ではできないこと。

3
firelynx

与えられたipがipv4で正しくチェックされていることを確認した最も簡単な方法は、commons-validator-1.4.0.jarを使用することです。

org.Apache.commons.validator.routines.InetAddressValidator

InetAddressValidator

例えば。

InetAddressValidator inetValidator = InetAddressValidator.getInstance();
inetValidator.isValidInet4Address(yourIPAddress);

この単純な正規表現を使用します:-

  "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
2
boolean isValid = inetAddressValidator.isValid(hostName) || hostName.equalsIgnoreCase("localhost");

coobirdと同じ答え。ステートメントにlocalhostを追加するだけです。ほとんどの環境では、有効なホスト名として「localhost」を使用します。 ipv4形式ではありませんが、有効性を考慮するために含める必要があります。

1
rinjan

The IPAddress Java library はそれを行います。javadocはリンクから入手できます。免責事項:私はプロジェクトマネージャーです。

このライブラリは、IPv4とIPv6を透過的にサポートするため、検証は以下と同じように機能し、CIDRプレフィックス長IPC4アドレスもサポートします。 inet_atonのようなより珍しい形式をサポートします(たとえば、10.8は別の回答で言及されています)。

アドレスが有効かどうかを確認します。

    String str = "1.2.3.4";
    IPAddressString addrString = new IPAddressString(str);
    try {
         IPAddress addr = addrString.toAddress();
         ...
    } catch(AddressStringException e) {
        //e.getMessage provides validation issue
    }
1
Sean F
public static boolean ipv4Check(String ipAddress){

    try{
        if(ipAddress!=null && !ipAddress.isEmpty()){
            String [] ip = ipAddress.split("\\.");
            if(ip.length!=4)
                return false;

            for(int i=0;i<=ip.length-1;i++){
                int j=Integer.parseInt(ip[i]);
                if(j<0 || j>255){
                    return false;
                }
            }
            if ( ipAddress.endsWith(".") ) {
                return false;
            }
            if ( ipAddress.startsWith(".") ) {
                return false;
            }

        }
        return true;
    } catch (NumberFormatException ex) {
        return false;
    }       
}
1
user7839057

開発中のプラットフォーム/フレームワークで利用可能なものを使用することをお勧めします。

十分と思われるものが何もない場合は、コンパイル済みの正規表現をヘルパークラスに追加するだけです。たとえば、 here は、Androidフレームワークが行う方法です:

public static final Pattern IP_ADDRESS
    = Pattern.compile(
        "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
        + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
        + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
        + "|[1-9][0-9]|[0-9]))");
1