读取文件——将字符串和 int 值配对——使用多条分割线

Reading a file -- pairing a String and int value -- with multiple split lines

我正在按照以下标准进行练习:

“输入由成对的标记组成,其中每对标记以该人购买的机票类型(“长途汽车”、“头等舱”或“折扣”,区分大小写)和后面是飞行的里程数。"

列表可以配对 -- coach 1500 firstclass 2000 discount 900 coach 3500 -- 目前效果很好。但是,当 String 和 int 值像这样拆分时:

firstclass        5000  coach         1500         coach
100 firstclass

2000    discount 300

它完全坏了。我几乎可以肯定跟我用这个格式有关系(不全)

while(fileScanner.hasNextLine())
{
    StringTokenizer token = new StringTokenizer(fileScanner.nextLine(), " ")
    while(token.hasMoreTokens())
    {
        String ticketClass = token.nextToken().toLowerCase();
        int count = Integer.parseInt(token.nextToken());
        ...
    }
}

因为它总是将第一个值读取为字符串,将第二个值读取为整数。我非常不知道如何在阅读下一行时跟踪一个或另一个。非常感谢任何帮助。

类似(我认为)的问题:

如果您有能力一次读取一个非常长的文本文件 String,只需使用 built-in String.split() 和正则表达式 \s+,像这样

String[] tokens = fileAsString.split("\s+"); 

这会将输入文件拆分为标记,假设标记由一个或多个 whitespace 字符分隔(白色 space 字符包括换行符、space、制表符和马车 return)。偶数和奇数标记分别是机票类型和里程数。

如果您绝对必须读入 line-by-line 并使用 StringTokenizer,一个解决方案是计算最后一行中的标记数。如果这个数字是奇数,则当前行中的第一个标记将是最后一行中第一个标记的不同类型。一旦知道当前行的起始类型,只需从那里交替类型。

int tokenCount = 0;
boolean startingType = true; // true for String, false for integer
boolean currentType;
while(fileScanner.hasNextLine())
{
    StringTokenizer token = new StringTokenizer(fileScanner.nextLine(), " ");
    startingType = startingType ^ (tokenCount % 2 == 1); // if tokenCount is odd, the XOR ^ operator will flip the starting type of this line
    tokenCount = 0;
    while(token.hasMoreTokens())
    {
        tokenCount++;
        currentType = startingType ^ (tokenCount % 2 == 0); // alternating between types in current line
        if (currentType) {
            String ticketClass = token.nextToken().toLowerCase();
            // do something with ticketClass here
        } else {
            int mileCount = Integer.parseInt(token.nextToken());
            // do something with mileCount here
        }
        ...
    }
}

我找到了另一种不使用 StringTokenizer 或正则表达式来解决这个问题的方法...诚然,我在使用正则表达式时遇到了麻烦哈哈。

我在 try-catch 块之外声明这些,因为我想在我的 finally 语句和 return 点中使用它们:

int points = 0;
ArrayList<String> classNames = new ArrayList<>();
ArrayList<Integer> classTickets = new ArrayList<>();

然后在我的 try-statement 中,我声明了 index 变量,因为我在这个块之外不需要它。每次读取新元素时,该变量都会增加。奇数元素被读取为票价classes,偶数元素被读取为票价:

try
{
    int index = 0;
    // read till the file is empty
    while(fileScanner.hasNext())
    {
        // first entry is the ticket type
        if(index % 2 == 0)
            classNames.add(fileScanner.next());
        // second entry is the number of points
        else
            classTickets.add(Integer.parseInt(fileScanner.next()));
        index++;
    }
}

您可以像这样在此处捕获它,也可以在您的方法声明中使用 throws NoSuchElementException -- 只要您在方法调用时捕获它

catch(NoSuchElementException noElement)
{
    System.out.println("<###-NoSuchElementException-###>");
}

然后到这里,遍历元素的数量。查看是哪个航班 class 并分别乘以票数和 return 街区外的点数:

finally
{
    for(int i = 0; i < classNames.size(); i++)
    {
        switch(classNames.get(i).toLowerCase())
        {
            case "firstclass":    // 2 points for first
                points += 2 * classTickets.get(i);
                break;
            case "coach":         // 1 point for coach
                points += classTickets.get(i);
                break;
            default:
                // budget gets nothing
        }
    }
}
return points;

正则表达式似乎是最方便的方式,但出于某种原因,这对我来说更直观。不管怎样,希望综艺能有所帮助。

simply use the built-in String.split() - @bui

我终于能够理解正则表达式了,但是 \s+ 由于某种原因没有被识别。它一直给我这个错误信息:

Invalid escape sequence (valid ones are \b \t \n \f \r " ' \ )Java(1610612990)

因此,当我改用这些字符时,我可以这样写:

int points = 0, multiplier = 0, tracker = 0;
while(fileScanner.hasNext())
{
    String read = fileScanner.next().split(
            "[\b  \t  \n  \f  \r  \"  \'  \ ]")[0];
    if(tracker % 2 == 0)
    {
        if(read.toLowerCase().equals("firstclass"))
            multiplier = 2;
        else if(read.toLowerCase().equals("coach"))
            multiplier = 1;
        else
            multiplier = 0;
    }else
    {
        points += multiplier * Integer.parseInt(read);
    }
    tracker++;
}

此代码一次进入一个条目,而不是读取整个空白数组作为 work-around 我收到的错误消息。如果您能告诉我使用 String[] tokens = fileAsString.split("\s+"); 代码会是什么样子,我将不胜感激 :)

you need to add another "\" before "\s" to escape the slash before "s" itself – @bui