问题描述
如何在使用 Scanner 读取输入文件时跳过几个字符? 我有这个输入文件,它在实际字符串之前有一些数字,我无法删除这些数字,因为它们也很重要。我需要将它们存储在另一个整数数组中:
3 onion pepper olive
3 mushroom tomato basil
3 chicken mushroom pepper
3 tomato mushroom basil
2 chicken basil
我可以跳过整数并先读取字符串,然后再读取整数吗? 这是我一直在处理的所有代码:
import java.util.*;
import java.io.*;
public class Pizza {
public static int numofpizzas;
public static Scanner input;
public static String[][] pizzaIng;
public static File file;
public static void main(String[] args) throws FileNotFoundException {
// assigning the file object
file = new File("an example");
// setting up the scanner
input = new Scanner(file);
// reading and storing the input file data
pizzaIng = new String[][]{{input.nextLine()},{input.nextLine()},{input.nextLine()}
{input.nextLine()},{input.nextLine()}};
for (String[] i: pizzaIng) {
for (String j: i) {
System.out.println(j);
}
}
}
}
解决方法
有几种方法可以做到这一点,但这一切都取决于数据。以下是少数可能的方法中的两种,
- 获取仅包含项目名称的新子字符串。
如果你的例子中提到的模式是一致的,并且数量总是小于10,那么你可以使用这种方法,这样项目名称的起始索引是固定的。因此,在代码片段的最后一个 for 循环中,您可以执行以下操作,
for (String j: i) {
int startingIndex = 2
j = j.substring(startingIndex)
}
然而,缺点是如果数量超过 9 或更多,则起始索引会发生变化,因此您的子字符串将错过第一个字符。
- 使用正则表达式替换(删除)数字字符。
在这种情况下,即使数量超过一位数(10 个及更多),数字也会被删除,商品将被保留。
for (String j: i) {
String pattern = "[0-9]"
j = j.replaceAll(pattern,"")
}
但是,如果项目名称包含数字,那么它们也会被替换。所以这就是这种方法的缺点。为了克服这个问题,可以使用以下正则表达式,其中仅使用正则表达式
for (String j: i) {
String pattern = "([0-9]+)([A-Za-z\s0-9]+)"
j = j.replaceAll(pattern,"$2")
}
这个正则表达式将部分字符串解析为两部分:“([0-9]+)”表示的数量和“([A-Za-z\s0-9]+)”表示的项目名称我们接受项目名称的字母数字和空格。然后在下一行中,整个字符串被替换为“$2”,其中“$2”代表项目名称。所以只保留项目名称(可能包括数字)。字符串的数量部分被删除。
希望这对您有所帮助:) 如果可以,如果您将我的回答标记为“已接受”,我将不胜感激。美好的一天!
,您可以使用 subString() 方法跳过字符串的第一个字符。使用 .subString(1) 只会跳过字符串的第一个字符(在您的情况下是整数),而 .subString(2) 将跳过前两个字符(在您的情况下是整数和空格)。
新代码如下所示:
import java.util.*;
import java.io.*;
public class Pizza {
public static int numofpizzas;
public static Scanner input;
public static String[][] pizzaIng;
public static File file;
public static void main(String[] args) throws FileNotFoundException {
// assigning the file object
File file = new File("testText.txt");
// setting up the scanner
input = new Scanner(file);
// reading and storing the input file data
pizzaIng = new String[][]{{input.nextLine()},{input.nextLine()},{input.nextLine()}};
for (String[] i: pizzaIng) {
for (String j: i) {
System.out.println(j.substring(2));
}
}
}
}
,
既然“前面的数字也很重要”,为什么不创建一个以整行开头的类?
class Ingredient {
// add getters and setters for those
int amount;
String name;
}
然后您可以为每一行创建其中一种成分。由于这是您的原始问题,也许您可以使用
static Pattern ingredientPattern = Pattern.compile("([0-9]+) (.*)");
public static Ingredient fromLine(String line) {
Ingredient result = new Ingredient();
Matcher matcher = ingredientPattern.matcher(line);
if (matcher.matches()) {
result.setAmount(Integer.parseInt(matcher.group(1)));
result.setName(Integer.parseInt(matcher.group(2)));
} // else throw exception or something
return result;
}
该模式是一个包含两组的正则表达式,第一个包含数字(“[0-9]+”,+ 表示“1 或更多”),第二个包含字符串的其余部分。
>你应该能够解析整个事情
List<Ingredient> ingredients = new ArrayList<>();
Scanner sc = new Scanner(input);
while(sc.hasNext()) {
ingredients.add(fromLine(sc.nextLine()));
}
或者,对于给定的文件名
List<Ingredient> ingredients =
Files.lines(filename)
.map(MyClass::fromLine)
.collect(Collectors.toList());