Что такое эквивалент Java sscanf для синтаксического анализа значений из строки с использованием известного шаблона?
Итак, я родом из C-фона (первоначально изначально, хотя я не использовал этот язык почти 5 лет), и я пытаюсь разобрать некоторые значения из строки в Java. В C я бы использовал sscanf. В Java люди сказали мне "использовать Scanner или StringTokenizer", но я не вижу, как их использовать для достижения моей цели.
Моя строка ввода выглядит как "17-MAR-11 15.52.25.000000000". В C я бы сделал что-то вроде:
sscanf(thestring, "%d-%s-%d %d.%d.%d.%d", day, month, year, hour, min, sec, fracpart);
Но в Java все, что я могу сделать, это такие вещи, как:
scanner.nextInt();
Это не позволяет мне проверять шаблон, а для "MAR" мне приходится делать такие вещи, как:
str.substring(3,6);
Ужасный! Наверняка есть лучший способ?
Ответы
Ответ 1
Проблема заключается в том, что Java не выводит параметры (или передает по ссылке) как C или С#.
Но есть лучший способ (и более твердый). Используйте регулярные выражения:
Pattern p = Pattern.compile("(\\d+)-(\\p{Alpha}+)-(\\d+) (\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)")
Matcher m = p.matcher("17-MAR-11 15.52.25.000000000");
day = m.group(1);
month= m.group(2);
....
Конечно, код C более краткий, но этот метод имеет одну прибыль:
Шаблоны задают формат более точным, чем "% s" и "% d". Поэтому вы можете использовать \d {2}, чтобы указать, что этот день ДОЛЖЕН составлять ровно 2 цифры.
Ответ 2
Вот решение, использующее сканеры:
Scanner scanner = new Scanner("17-MAR-11 15.52.25.000000000");
Scanner dayScanner = new Scanner(scanner.next());
Scanner timeScanner = new Scanner(scanner.next());
dayScanner.useDelimiter("-");
System.out.println("day=" + dayScanner.nextInt());
System.out.println("month=" + dayScanner.next());
System.out.println("year=" + dayScanner.nextInt());
timeScanner.useDelimiter("\\.");
System.out.println("hour=" + timeScanner.nextInt());
System.out.println("min=" + timeScanner.nextInt());
System.out.println("sec=" + timeScanner.nextInt());
System.out.println("fracpart=" + timeScanner.nextInt());
Ответ 3
Ни один из этих примеров не был действительно удовлетворительным для меня, поэтому я сделал свою собственную утилиту java sscanf:
https://github.com/driedler/java-sscanf/tree/master/src/util/sscanf
Вот пример разбора шестнадцатеричной строки:
String buffer = "my hex string: DEADBEEF\n"
Object output[] = Sscanf.scan(buffer, "my hex string: %X\n", 1);
System.out.println("parse count: " + output.length);
System.out.println("hex str1: " + (Long)output[0]);
// Output:
// parse count: 1
// hex str1: 3735928559
Ответ 4
Для "17-MAR-11 15.52.25.000000000":
SimpleDateFormat format = new SimpleDateFormat("dd-MMM-yy HH.mm.ss.SSS");
try
{
Date parsed = format.parse(dateString);
System.out.println(parsed.toString());
}
catch (ParseException pe)
{
System.out.println("ERROR: Cannot parse \"" + dateString + "\"");
}
Ответ 5
Это далеко не столь элегантное решение, как с помощью регулярного выражения, но должно работать.
public static void stringStuffThing(){
String x = "17-MAR-11 15.52.25.000000000";
String y[] = x.split(" ");
for(String s : y){
System.out.println(s);
}
String date[] = y[0].split("-");
String values[] = y[1].split("\\.");
for(String s : date){
System.out.println(s);
}
for(String s : values){
System.out.println(s);
}
Ответ 6
Вы знакомы с концепцией регулярных выражений? Java предоставляет вам возможность использовать регулярное выражение с помощью класса Pattern.
Проверьте это:
http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html
Вы можете проверить свою строку следующим образом:
Matcher matcher = Pattern.match(yourString);
matcher.find();
а затем используйте методы, предоставленные Matcher, для управления найденной вами строкой или NOT.
Ответ 7
System.in.read() - это еще один вариант.