Java 文件行处理(基础)

Java file line processing (basics)

我很难学习文件行处理。我了解如何使用 while 循环和 .hasNextLine 读取文件的行,如果它包含我正在搜索的值,我什至能够打印整行。我只是不明白如何在文本文件的特定行中获取单个值(字符串、整数、双精度)并对它们进行排序,然后按特定顺序打印出我想要的值。我的教授刚刚快速浏览了教科书的这一章,我们即将进行测试,如果能帮助解决这个问题,我们将不胜感激(甚至打开视频 lecture/tutorial 链接)

我将在下面拼凑一个练习题来举例说明我的意思。

一个文本文件列出了学生在最近 3 次测试中的分数,例如:

Nick 85 90 76 Hannah 86 91 66 Joe
           22 35 100
   Zak 100
 40 80

现在,假设我想按字母顺序输出每个孩子名字的前 2 名。我该怎么做呢?我将在本周晚些时候进行的测试将不允许数组或任何花哨的实用程序,我们将被期望真正只使用扫描仪和循环。

预期输出:

Hannah: 91, 86
Nick: 90, 85
Joe: 100, 35
Zak: 100, 80

我现在是如何解决这样的问题的:

    Scanner exampleFile = new Scanner(new File("file.txt"));
    String name;

    while(exampleFile.hasNextLine()){
        name = exampleFile.nextLine();
        Scanner linescan = new Scanner(name);
        if(linescan.hasNext()){
            int a = linescan.nextInt();
            int b = linescan.nextInt();
            int c = linescan.nextInt();
            int a1 = Math.max(a, b);
            int a2 = Math.max(a, c);

            System.out.println(linescan.next() + ": " + Math.max(a1, a2) + ", " + "middle value idk how to get");
        }
    }

我不确定我是否在正确的轨道上,或者我是否遗漏了一些非常明显的东西,这些东西会照亮一切并让我成为文件行处理神。所有社区智慧都受到赞赏。

试试下面的方法。它正确解析文件并能够打印所需的输出(未排序):

    Scanner exampleFile = new Scanner(new File("file"));
    while (exampleFile.hasNext()) {
        String name = exampleFile.next();
        int a = exampleFile.nextInt();
        int b = exampleFile.nextInt();
        int c = exampleFile.nextInt();
        int max = Math.max(a, b);
        max = Math.max(max, c);
        int min = Math.min(a, b);
        min = Math.min(min, c);
        System.out.println(name + ": " + max + ", " + (a > min && a < max ? a : (b > min && b < max ? b : c)));
    }
    exampleFile.close();

如果你想排序,那么你将不得不使用多个while循环。首先读取并存储到数组中,然后应用任何选择的排序算法,然后打印。现在您可以正确读取数据,您应该可以继续了。

"The test I'm taking later this week won't allow arrays or any fancy utilities, we will be expected to use only scanner and loops really. "

没有数据结构的排序会适得其反,我跑题了。

在这种情况下,我认为对数据进行排序的唯一方法是:一次读取一行数据,trim 该行,并将其附加到 String尾随 space。然后你将不得不想出一些算法来抓取 String 并比较和交换它的 sub-strings 直到它被排序。根据经验,这不是最令人愉快的 activity.

这是我刚刚输入的一个工作示例。它使用一个 Scanner 用于文件输入,并使用 Strings。 Strings 不是数组,所以很好。我试图通过代码中的注释来解释事情,但如果您需要更好的解释,请在此答案的注释中告诉我。

注意:这个例子只是对输入进行排序,它没有找到最高的2个等级,但是一旦输入被排序,这应该很容易。只需将排序后的 String 通过 Scanner,解析一些数据,然后就可以了。


Driver.java:

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;


public class Driver {

    public static void main(String[] args) {
        Scanner in = null;
        String inputStr = "";

        try {
            // open the file "xin.txt" to retrieve input
            in = new Scanner(new File("xin.txt"));
        } catch(FileNotFoundException e) {
            System.out.println(e.getMessage());
            System.exit(0);
        }

        // read the data into a one line string
        while(in.hasNext()) {
            inputStr += in.nextLine().trim() + " ";
        }
        System.out.println("[ORIGINAL]\n" + inputStr + "\n");

        System.out.println("[Start Sorting]");
        inputStr = sortString(inputStr);
        System.out.println("[Done Sorting]\n");

        System.out.println("[Sorted String]\n" + inputStr);
    }

    private static String sortString(String orig) {
        String one = "";
        String two = "";
        int oneStart = 0; // starting index of string to compare with
        int twoStart = 0; // starting index of string to compare against
        int oneStop = 0; // ending index of string to compare with
        int twoStop = 0; // ending index of string to compare against
        int oneTot = 0; // length of string one plus the grades
        int twoTot = 0; // length of string two plus the grades

        int cp = 0; // current position (index)

        boolean onOne = false; // current position is on one
        boolean onTwo = false; // current position is on two
        boolean passOne = false; // passed string one
        boolean passTwo = false; // passed string two


        boolean notDone = true; // control boolean

        while(notDone) {
            if(cp >= orig.length() || isAtoZ(orig.charAt(cp))) {
                if(!onOne && !passOne) {
                    oneStart = cp;
                    onOne = true;
                } else if(passOne && (!onTwo && !passTwo)) {
                    twoStart = cp;
                    onTwo = true;

                    // total length of the first string is the current position
                    // minus the start of the first string
                    oneTot = cp - oneStart;
                } else if(passTwo) {
                    // total length of the second string is the current position
                    // minus the start of the second string
                    twoTot = cp - twoStart;

                    one = orig.substring(oneStart, oneStop);
                    two = orig.substring(twoStart, twoStop);

                    // output the results of the comparing
                    System.out.println(orig);
                    System.out.println("Comparing: " + one + " to " + two);
                    System.out.println("Result: " + one.compareTo(two) + "\n");



                    // if the first string is alphabetically larger, then swap
                    // and restart sort,else continue to the next comparison
                    if(one.compareTo(two) > 0) {
                        orig = rangeSwap(oneStart, oneStart + oneTot,
                        twoStart, twoStart + twoTot, orig);
                        onOne = false;
                        onTwo = false;
                        passOne = false;
                        passTwo = false;

                        cp = -1;
                    } else {
                        onOne = false;
                        onTwo = false;
                        passOne = false;
                        passTwo = false;

                        cp = twoStart - 1;
                    }

                }
            } else {
                if(onOne && !passOne) {
                    oneStop = cp;
                    passOne = true;
                    onOne = false;
                } else if(onTwo && !passTwo) {
                    twoStop = cp;
                    passTwo = true;
                    onTwo = false;
                }
            }

            // increment the current position by one
            cp = cp + 1;

            // the last string has no string to compare to so
            // set the control boolean
            if(cp >= (orig.length()-1) && (!passTwo)) {
                notDone = false;
            }
        }

        // return the sorted string
        return orig;
    }

    private static String rangeSwap(int ob, int oe, int tb, int te, String s) {
        String start = "";
        String x = "";
        String middle = "";
        String y = "";
        String end = "";

        start = s.substring(0, ob);
        x = s.substring(ob, oe);
        middle = s.substring(oe, tb);
        y = s.substring(tb, te);
        end = s.substring(te);

        return start + y + middle + x + end;
    }

    private static boolean isAtoZ(char what) {
        // ASCII character codes: A to Z = 65 to 90
        //                        a to z = 97 to 122
        return (((int)what >= 65 && (int)what <= 90) ||
        ((int)what >= 97 && (int)what <= 122 ));
    }

}

xin.txt:

Nick 85 90 76 Hannah 86 91 66 Joe
           22 35 100
   Zak 100
 40 80

输出:

[Original]
Nick 85 90 76 Hannah 86 91 66 Joe 22 35 100 Zak 100 40 80 

[Start Sorting]
Nick 85 90 76 Hannah 86 91 66 Joe 22 35 100 Zak 100 40 80 
Comparing: Nick to Hannah
Result: 6

Hannah 86 91 66 Nick 85 90 76 Joe 22 35 100 Zak 100 40 80 
Comparing: Hannah to Nick
Result: -6

Hannah 86 91 66 Nick 85 90 76 Joe 22 35 100 Zak 100 40 80 
Comparing: Nick to Joe
Result: 4

Hannah 86 91 66 Joe 22 35 100 Nick 85 90 76 Zak 100 40 80 
Comparing: Hannah to Joe
Result: -2

Hannah 86 91 66 Joe 22 35 100 Nick 85 90 76 Zak 100 40 80 
Comparing: Joe to Nick
Result: -4

Hannah 86 91 66 Joe 22 35 100 Nick 85 90 76 Zak 100 40 80 
Comparing: Nick to Zak
Result: -12

[Done Sorting]

[Sorted String]
Hannah 86 91 66 Joe 22 35 100 Nick 85 90 76 Zak 100 40 80