分析文本文件中的一行并访问括号内的值



所以我正在解析文本文件中的一行并得到一个字符串,如下所示:

color(black)

color(RGB(142,0,0))

所以我写了一个代码:

private Sprite makeSpriteToBackGround(String line) {
if (line.contains("color")) {
ColorsParser colorsParser = new ColorsParser();
Color color = colorsParser.colorFromString(line.substring(line.indexOf("RGB")));
return new Sprite() {
@Override
public void drawOn(DrawSurface d) {
d.setColor(color);
d.fillRectangle(0, 0, 800, 600);
}
@Override
public void timePassed() {
}
};
}

所以我的目标是检查该行是否包含"RGB"。 如果是这样 - 它将通过我的 colorFromString 解析器函数进行解析,如果没有,它将部署为颜色。

你建议我如何解析

color(black)

.part?

因为 RGB 部分工作得很好。

您可能希望首先检查是否存在RGB,然后再回退到在查找表中查找已知值。

Map<String, Color> colors = new HashMap<String, Color>() {{
put("black", Color.BLACK);
put("red", Color.RED);
put("green", Color.GREEN);
put("blue", Color.BLUE);
}};
Color color = null;
int rgbIndex = line.indexOf("RGB");
if (rgbIndex > -1) {
color = colorsParser.colorFromString(line.substring(rgbIndex));
} else {
// There are better ways to extract text between brackets, see https://stackoverflow.com/questions/24256478/pattern-to-extract-text-between-parenthesis/24256532
String colorName = line.substring(line.indexOf("(") + 1, line.indexOf(")"));
color = colors.get(colorName);
}
// TODO: Make sure you check if `color` is null here.
public class TestColor {
public static void main(String[] args) {
String fullColorStr = "color(yellow)";

//Precondition
if (fullColorStr == null || fullColorStr.trim().isEmpty()) {
throw new IllegalArgumentException("Color cannot be empty");
}

String colorStr = fullColorStr.substring(fullColorStr.indexOf("(")+1,fullColorStr.indexOf(")"));
Color color = getColorFromString(colorStr);
System.out.print(color);
}
private static Color getColorFromString(String colorStr) {
//Precondition
if (colorStr == null || colorStr.trim().isEmpty()) {
return null;
}
Color color = null;
String lowerColorStr = colorStr.toLowerCase();
try {
Field colorField = Color.class.getField(lowerColorStr);
//Paranoid check start
Class<?> type = colorField.getType();
if (type != Color.class) {
throw new IllegalStateException("Shoudln't have encountered this : " + colorStr);
} //End 
color = (Color) colorField.get(Color.class);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
throw new IllegalArgumentException("Not a valid color : " + colorStr);
}
return color;
}
}

我想知道为什么其他评论者都没有提到它,但是有一种既定的方法可以解决此类问题:正则表达式

您描述了两种模式:

  • 命名模式:color((w+))(请参阅 regex101.com(
  • RGB 模式:color(RGB((d+),(d+),(d+)))(见 regex101.com 上的实时(

许多开发者都害怕正则表达式,但它们在这里非常有用。在代码中,您所要做的就是从匹配项中选取值:

package color;
import java.awt.Color;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ColorParser {
private final Pattern namedPattern = Pattern.compile("color\((\w+)\)");
private final Pattern rgbPattern = Pattern.compile("color\(RGB\((\d+)\,(\d+)\,(\d+)\)\)");
public Color parse(String line) {
Color result = parseRGB(line);
if (result == null) {
result = parseNamed(line);
}
return result;
}
private Color parseRGB(String line) {
final Matcher matcher = rgbPattern.matcher(line);
if (matcher.find()) {
final int red = Integer.parseInt(matcher.group(1));
final int green = Integer.parseInt(matcher.group(2));
final int blue = Integer.parseInt(matcher.group(3));
return new Color(red, green, blue);
}
return null;
}
private Color parseNamed(String line) {
final Matcher matcher = namedPattern.matcher(line);
if (matcher.find()) {
final String name = matcher.group(1);
try {
// java.awt.Color is not an enum, so let's use Reflection
return (Color) Color.class.getField(name.toUpperCase()).get(null);
} catch (Exception e) {
// ignore
}
}
return null;
}
}

下面是一个 JUnit 测试来验证它:

package color;
import static org.junit.Assert.assertEquals;
import java.awt.Color;
import org.junit.Test;
public class ColorParserTest {
final ColorParser sut = new ColorParser();
@Test
public void testParse_Named() {
assertEquals(Color.BLACK, sut.parse("color(black)"));
}
@Test
public void testParse_NamedInText() {
assertEquals(Color.RED, sut.parse("foo color(Red) bar"));
}
@Test
public void testParse_RGB() {
assertEquals(Color.ORANGE, sut.parse("color(RGB(255,200,0))"));
}
@Test
public void testParse_Unkown() {
assertEquals(null, sut.parse("color(foo)"));
}
}

我在这里使用了 AWT 颜色类。根据您的使用案例,您可能需要一个映射表来解析其他命名颜色,例如 HTML 颜色或 X11 颜色。

最新更新