如何阅读和排序文本文件?

时间:2014-03-06 19:59:18

标签: java

//我使用java程序读取文本文件(athlete.txt)并将内容输出到
在屏幕上,我现在需要编写一个java程序,按运动员编号读取Athle.txt并对其进行排序(然后在屏幕上打印数据。输出可以按升序或降序排列。

    import java.io.*;
    import java.util.Scanner;


    public class AthleteRecords {
    public static void main(String[] args) throws Exception
    {
      Scanner in = new Scanner(new FileReader("athlete.txt"));
        while (in.hasNextLine())
         {
           System.out.println(in.nextLine());
          }
      }
    }



    //Output file

    Athlete Number: 4233
    First Name: Peter
    Family Name: Brown
    Class 1 
    Position and points awarded for 100m race: 3  50
    Position and points awarded for 200m race: 2  80
    Position and points awarded for 400m race: 1  100
    Class 2
    Position and points awarded for 100m race: 3  50
    Position and points awarded for 200m race: 4  20
    Position and points awarded for 400m race: 2  80

    Athlete Number: 1235
    First Name: Robert
    Family Name: Anderson
    Class 1 
    Position and points awarded for 100m race: 4  20
    Position and points awarded for 200m race: 1  100
    Position and points awarded for 400m race: 2  80

    Class 2
    Position and points awarded for 100m race: 2  80
    Position and points awarded for 200m race: 1  100
    Position and points awarded for 400m race: 3  50

    Athlete Number: 3248
    First Name: Sean
    Family Name: Thompson
    Class 1 
    Position and points awarded for 100m race: 4  20
    Position and points awarded for 200m race: 1  100
    Position and points awarded for 400m race: 2  80
    Class 2
    Position and points awarded for 100m race: 2  80
    Position and points awarded for 200m race: 1  100
    Position and points awarded for 400m race: 3  50

1 个答案:

答案 0 :(得分:0)

首先,我创建一个Athlete类,其中包含您需要的所有信息,如下所示:

public class Athlete {
    private int id;
    private String firstName;
    private String lastName;
    private List<Race> class1Races;
    private List<Race> class2Races;

    public Athlete() {
        class1Races = new ArrayList<>(4);
        class2Races = new ArrayList<>(4);
    }

    public int getId() {
        return id;
    }

    //...probably more getters, if you need them elsewhere.

    @Override
    public String toString() {
        String idString = Integer.toString(id);
        StringBuilder result = new StringBuilder(60 + idString.length() + firstName.length() + lastName.length() + 52*class1Races.size() + 52*class2Races.size());
        result.append("Athlete Number: ");
        result.append(idString);
        result.append("\nFirst Name: ");
        result.append(firstName);
        result.append("\nFamily Name: ");
        result.append(lastName);
        result.append("\nClass1\n");
        for(Race race : class1Races) {
            result.append(race.toString());
            result.append("\n");
        }
        result.append("Class2\n");
        for(Race race : class2Races) {
            result.append(race.toString());
            result.append("\n");
        }
        return result.toString();
    }

    void setId(int id) {
        this.id = id;
    }

    void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    void setLastName(String lastName) {
        this.lastName = lastName;
    }

    void addRaceClass1(Race race) {
        class1Races.add(race);
    }

    void addRaceClass2(Race race) {
        class2Races.add(race);
    }
}

public class Race { //And accompanying Race class to hold information about a race.
    private String name;
    private int position;
    private int points;

    public Race(String name,int position,int points) {
        this.name = name;
        this.position = position;
        this.points = points;
    }

    @Override
    public String toString() {
        String positionString = Integer.toString(position);
        String pointsString = Integer.toString(points);
        StringBuilder result = new StringBuilder(42 + name.length() + positionString.length() + pointsString.length());
        result.append("Position and points awarded for ");
        result.append(name);
        result.append(" race: ");
        result.append(positionString);
        result.append("  ");
        result.append(pointsString);
        return result.toString();
    }

    //...probably some getters, if you need them elsewhere.
}

接下来,您将需要解析该文件。我不知道完整的文件规范,但通过你的例子,我猜:

private List<Athlete> parseAthletes(String filename) throws IOException {
    List<Athlete> result = new ArrayList<>(12);
    BufferedReader br = new BufferedReader(new FileReader(filename));
    Athlete athlete = null;
    int currentClass = 0;
    String line = null; //Loop as long as there are input lines.
    while((line = br.readLine()) != null) { //Sets the line variable and reads it all at once!
        if(line.startsWith("Athlete Number: ")) {
            athlete = new Athlete();
            result.add(athlete);
            athlete.setId(Integer.parseInt(line.substring(16))); //Throws NumberFormatException if not a number.
            currentClass = 0;
        } else if(line.startsWith("First Name: ")) {
            if(athlete == null) //No Athlete Number was seen yet.
                throw new IOException("Wrong format!");
            athlete.setFirstName(line.substring(12));
        } else if(line.startsWith("Family Name: ")) {
            if(athlete == null)
                throw new IOException("Wrong format!");
            athlete.setLastName(line.substring(13));
        } else if(line.startsWith("Class ")) {
            if(athlete == null)
                throw new IOException("Wrong format!");
            currentClass = Integer.parseInt(line.substring(6)); //Throws NumberFormatException if not a number.
        } else if(line.startsWith("Position and points awarded for ") && line.contains(" race: ")) {
            if(athlete == null || (currentClass != 1 && currentClass != 2))
                throw new IOException("Wrong format!"); //Need to have seen an athlete as well as a class number.
            String raceName = line.substring(32,line.indexOf(" race: ",32));
            line = line.substring(line.indexOf(" race: ",32) + 7); //Trim off the start.
            int position = Integer.parseInt(line.substring(0,line.indexOf("  ")));
            int points = Integer.parseInt(line.substring(line.indexOf("  ") + 2));
            Race race = new Race(raceName,position,points);
            if(currentClass == 1)
                athlete.addRaceClass1(race);
            else //We already know class must be 2.
                athlete.addRaceClass2(race);
        }
    }
    return result;
}

如果类号可能不仅仅是1和2,您可能需要列出比赛列表。通过缓存indexOf查询也可以提高效率。但通常性能不是真正的问题这些文件解析器;如果这是一个问题,你最好不要试图并行完成阅读并使用二进制格式。

最后,要按ID对列表进行排序,您可以使用Comparator。您甚至不需要为它创建一个全新的类,您只需匿名定义Comparator的实例:

List<Athlete> athletes = parseAthletes("athlete.txt");
Comparator<Athlete> athletesById = new Comparator<Athlete>() {
    @Override
    public int compare(Athlete a,Athlete b) {
        return Integer.compare(a.getId(),b.getId());
    }
}
Collections.sort(athletes,athletesById);
for(Athlete athlete : athletes) {
    System.out.println(athlete.toString());
}

该比较器定义了比较两个Athlete,只需要比较ID。

我可能在这里或那里犯了一个错字,或者出现了逻辑错误,所以请彻底测试这段代码,或者更好的是,受它启发,然后自己编写代码。