65.9K
CodeProject 正在变化。 阅读更多。
Home

使用通配符匹配您的字符串

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.67/5 (2投票s)

2008年7月23日

CPOL

3分钟阅读

viewsIcon

52974

downloadIcon

356

本文为您提供了如何使用 * 和 ?(所谓的通配符)比较字符串的思路。

引言

你是否曾经在Windows操作系统中搜索过文件和文件夹?通常,大多数用户会尝试搜索各种*.doc文件、*.pdf文件等。我们通常通过在Windows操作系统的搜索窗口的文本框中输入*.doc*.pdf来进行搜索。当然,Windows操作系统还提供了一些其他的更具体的搜索实用程序。然而,这种搜索方式被应用于许多应用程序中。如果一个应用程序提供了这种功能,它就会被认为是该应用程序的最佳特性。

背景

对于一个应用程序来说,用户将如何提供搜索条件,这一点至关重要。并非所有类型的搜索条件都总是可行的。通常,人们普遍认为,用户可以基于某些规范进行搜索。就此规范而言,我们通常通过提供通配符来进行搜索。通配符是*?。这些字符背后有一个概念。我希望你了解它。这种搜索规范在各种应用程序中反复出现。如果你正在开发一个应用程序,那么将有一个文本字段,用户必须通过提供*?或两者与字母数字字符的组合来搜索人员的姓名。例如,如果我需要搜索一个名字,我可以输入J*,这样我的输出可能是“John”、“Johnson”或以“J”开头的任何内容。还有一种情况是我需要精确地搜索四个字符,所以我可以将我的搜索条件设置为????。但是,用户可以给出任何类型的组合来搜索String模式。在基于Java的应用程序中,你可以使用正则表达式来实现此功能。但是正则表达式的形成取决于你。有时我们可能会发现很难形成精确的正则表达式以满足预期。但是,如果要求仅仅是基于通配符模式查找String匹配项,我已经在下面提供了一个示例。你可以在任何你希望基于通配符模式搜索名称的地方使用它。

Using the Code

以下类是一个实用程序类,你可以将其用作通配符模式的string查找器。例如,你的原始String是“John”,你想查找原始string是否与通配符模式“J*”匹配。你可以轻松做到。我已经提供了测试工具类来测试功能。你可以通过各种方式进行测试。

package com.ddlabs.core.util;
import java.util.Vector;

/**This class is a utility for finding
 * the String based upon the wild card
 * pattern. For example if the actual
 * String "John" and your wild card pattern
 * is "J*", it will return true.
 * @author Debadatta Mishra(PIKU)
 *
 */
public class WildCardStringFinder 
{
	/**
	 * String variable for wild card pattern 
	 */
	private String wildCardPatternString;
	/**
	 * Variable for the length of the wild card pattern
	 */
	private int wildCardPatternLength;
	/**
	 * Boolean variable to for checking wild cards,
	 * It is false by default.
	 */
	private boolean ignoreWildCards;
	/**
	 * Boolean variable to know whether the pattern
	 * has leading * or not.
	 */
	private boolean hasLeadingStar;
	/**
	 * Boolean variable to know whether the pattern
	 * has * at the end.
	 */
	private boolean hasTrailingStar;
	/**
	 * A String array to contain chars
	 */
	private String charSegments[];
	/**
	 * Variable to maintain the boundary of the String.
	 */
	private int charBound;
	
	/**
	 * Default constructor
	 */
	public WildCardStringFinder()
	{
		super();
		ignoreWildCards = false;
	}
	
	/**This is the public method which will be called to match a String
	 * with the wild card pattern.
	 * @param actualString of type String indicating the String to be matched
	 * @param wildCardString of type String indicating the wild card String
	 * @return true if matches
	 */
	public boolean isStringMatching( String actualString , String wildCardString )
	{
		wildCardPatternString = wildCardString;
		wildCardPatternLength = wildCardString.length();
		setWildCards();
		return doesMatch( actualString, 0, actualString.length() );
	}
	
	/**
	 * This method is used to set the wild cards.
	 * The pattern for the wild card may be *, ? or 
	 * a combination of *,? and alphanumeric character.
	 */
	private void setWildCards()
	{
		if(wildCardPatternString.startsWith("*"))
		{
			hasLeadingStar = true;
		}
		if (wildCardPatternString.endsWith("*") && wildCardPatternLength > 1 )
		{
			hasTrailingStar = true;
		}
		Vector temp = new Vector();
		int pos = 0;
		StringBuffer buf = new StringBuffer();
		while(pos < wildCardPatternLength) 
		{
			char c = wildCardPatternString.charAt(pos++);
			switch(c)
			{
			case 42: // It refers to *
				if(buf.length() > 0)
				{
					temp.addElement(buf.toString());
					charBound += buf.length();
					buf.setLength(0);
				}
				break;
			case 63: // It refers to ? 
				buf.append('\0');
				break;

			default:
				buf.append(c);
			break;
			}
		}
		if(buf.length() > 0)
		{
			temp.addElement(buf.toString());
			charBound += buf.length();
		}
		charSegments = new String[temp.size()];
		temp.copyInto(charSegments);
	}
	
	/**This is the actual method which makes comparison
	 * with the wild card pattern.
	 * @param text of type String indicating the actual String
	 * @param startPoint of type int indicating the start index
	 * of the String
	 * @param endPoint of type int indicating the end index of
	 * the String
	 * @return true if matches.
	 */
	private final boolean doesMatch(String text, int startPoint, int endPoint)
	{
		int textLength = text.length();
		
		if(startPoint > endPoint)
		{
			return false;
		}
		if(ignoreWildCards)
		{
			return endPoint - startPoint == wildCardPatternLength
			    && wildCardPatternString.regionMatches(false, 0, text,
			    startPoint, wildCardPatternLength);
		}
		int charCount = charSegments.length;
		if(charCount == 0 && ( hasLeadingStar || hasTrailingStar ) )
		{
			return true;
		}
		if(startPoint == endPoint)
		{
			return wildCardPatternLength == 0;
		}
		if(wildCardPatternLength == 0)
		{
			return startPoint == endPoint;
		}
		if(startPoint < 0)
		{
			startPoint = 0;
		}
		if(endPoint > textLength)
		{
			endPoint = textLength;
		}
		int currPosition = startPoint;
		int bound = endPoint - charBound;
		if(bound < 0)
		{
			return false;
		}
		int i = 0;
		String currString = charSegments[i];
		int currStringLength = currString.length();
		if( !hasLeadingStar )
		{
			if(!isExpressionMatching(text, startPoint, 
					currString, 0, currStringLength))
			{
				return false;
			}
			i++;
			currPosition += currStringLength;
		}
		if(charSegments.length == 1 && !hasLeadingStar && !hasTrailingStar)
		{
			return currPosition == endPoint;
		}
		for(; i < charCount; i++)
		{
			currString = charSegments[i];
			int k = currString.indexOf('\0');
			int currentMatch;
			currentMatch = getTextPosition(text, currPosition, 
							endPoint, currString);
			if(k < 0)
			{
				if(currentMatch < 0)
				{
					return false;
				}
			}
			currPosition = currentMatch + currString.length();
		}
		if(!hasTrailingStar && currPosition != endPoint)
		{
			int clen = currString.length();
			return isExpressionMatching(text, 
				endPoint - clen, currString, 0, clen);
		}
		return i == charCount;
	}
	
	/**This method finds the position of the String based upon the
	 * wild card pattern. It also considers some special case
	 * like *.* and ???.? and their combination.
	 * @param textString of type String indicating the String
	 * @param start of type int indicating the start index of the String
	 * @param end of type int indicating the end index of the String
	 * @param posString of type indicating the position after wild card
	 * @return the position of the String
	 */
	private final int getTextPosition(String textString, int start, 
						int end, String posString)
	{
		/*
		 * String after *
		 */
		int plen = posString.length();
		int max = end - plen;
		int position = -1;
		int i = textString.indexOf(posString, start);
		/*
		 * The following conditions are met for the
		 * special case where user give *.* 
		 */
		if( posString.equals("."))
		{
			position = 1;
		}
		if(i == -1 || i > max)
		{
			position = -1;
		}
		else
		{
			position = i;
		}
		return position;
	}

	/**This method is used to match the wild card with the String
	 * based upon the start and end index.
	 * @param textString of type String indicating the String
	 * @param stringStartIndex of type int indicating the start
	 * index of the String.
	 * @param patternString of type String indicating the pattern
	 * @param patternStartIndex of type int indicating the start index
	 * @param length of type int indicating the length of pattern
	 * @return true if matches otherwise false
	 */
	private boolean isExpressionMatching(String textString, int stringStartIndex,
			String patternString, int patternStartIndex, int length)
	{
		while(length-- > 0) 
		{
			char textChar = textString.charAt(stringStartIndex++);
			char patternChar = patternString.charAt(patternStartIndex++);
			if ((ignoreWildCards || patternChar != 0)
					&& patternChar != textChar
					&& (textChar != patternChar 
					&& textChar != patternChar))
			{
				return false;
			}
		}
		return true;
	}

}

以下类是上述类的测试工具类。

package com.ddlabs.core.util;

/**This is a test harness class to test
 * the wild card pattern on a particular
 * String.
 * @author Debadatta Mishra(PIKU)
 *
 */
public class WildCardTestharness
{
	public static void main(String[] args) 
	{
		String name = "John";
		String searchString = "John";
		
		WildCardStringFinder finder = new WildCardStringFinder();
		boolean flag = finder.isStringMatching(name, searchString);
		System.out.println(flag);
	}
}		

关注点

要测试上述程序,请创建程序中提到的适当包。你也可以创建自己的包,并修改上述程序中的包名。你可以在你最喜欢的Java编辑器中拥有所有代码。我希望你会喜欢我的文章。如果你发现任何问题或错误,请随时通过电子邮件向我发送邮件,邮箱地址为debadattamishra@aol.com。本文仅适用于那些刚开始接触Java开发的人。本文不具有任何商业意义。请向我提供有关本文的反馈。

历史

  • 2008年7月23日:初始发布
© . All rights reserved.