使用 Scanner 读取输入文件时如何跳过几个字符?

问题描述

如何在使用 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);
                    }
                }
            }

        }

解决方法

有几种方法可以做到这一点,但这一切都取决于数据。以下是少数可能的方法中的两种,

  1. 获取仅包含项目名称的新子字符串。

如果你的例子中提到的模式是一致的,并且数量总是小于10,那么你可以使用这种方法,这样项目名称的起始索引是固定的。因此,在代码片段的最后一个 for 循环中,您可以执行以下操作,

for (String j: i) {
    int startingIndex = 2
    j = j.substring(startingIndex)
}

然而,缺点是如果数量超过 9 或更多,则起始索引会发生变化,因此您的子字符串将错过第一个字符。

  1. 使用正则表达式替换(删除)数字字符。

在这种情况下,即使数量超过一位数(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());