Jonathan S.
Jonathan S.

Reputation: 21

How to create a method which returns objects read from txt.file?

This is my attempt to read the file. If anyone has any comments about how to perform this in a better way, I am all ears.

public class Program {
    public void readFromFile() throws FileNotFoundException {
        File equipment = new File("equipment.txt");
        Scanner reader = new Scanner(equipment);
        while (reader.hasNextLine()){

        }
    }
}

This is my first Equipment class. The equipment from the txt file have some common properties. I only use this as an abstract class since that's what I think I have to do according to my task (test-Exam). If I am wrong, please let me know :)

public abstract class Equipment {
    private Integer id;
    private String locker;
    private Integer year;

    public Equipment(Integer id, String locker, Integer year) {
        this.id = id;
        this.locker = locker;
        this.year = year;
    }

Child equipment class drill. The drill only occurs three times within the txt file and I struggle to figure out how to read the content from the txt file when the drill and saw have some different properties.

public class Drill extends Equipment{
    private String equipmentName;
    private Boolean batteryPowered;
    private Boolean needsNewBit;

    public Drill(String equipmentName, Integer id, String locker, Integer year,  Boolean batteryPowered, Boolean needsNewBit) {
        super(id, locker, year);
        this.equipmentName = equipmentName;
        this.batteryPowered = batteryPowered;
        this.needsNewBit = needsNewBit;
    }

Child equipment class saw

public class Saw extends Equipment{
    private String equipmentName;
    private String sawType;
    private Boolean needsGrinding;

    public Saw(String equipmentName, Integer id, String locker, Integer year, String sawType, Boolean needsGrinding) {
        super(id, locker, year);
        this.equipmentName = equipmentName;
        this.sawType = sawType;
        this.needsGrinding = needsGrinding;
    }

Equipment.txt file format. I have separated the objects so it's easier to read. The txt file is originally without spaces in between the objects.

Saw
12
Locker 1
2012
Hand
true

Saw
15
Locker 2
2012
Hack
true

Saw
14
Locker 2
2014
Japanese
true

Saw
1
Locker 3
2014
Coping
false

Saw
2
Locker 3
2014
Coping
true

Saw
12
Locker 1
2016
Japanese
false

Saw
3
Locker 1
2016
Hack
true

Saw
5
Locker 4
2016
Hand
true

Saw
6
Locker 4
2019
Hand
true

Drill
16
Locker 5
2019
false
true

Drill
17
Locker 5
2019
false
true

Drill
18
Locker 5
2001
true
false

Saw
20
Locker 6
2001
Hack
false

Saw
21
Locker 6
2001
Hack
true

Saw
31
Locker 7
2021
Japanese
false

Saw
32
Locker 7
2021
Japanese
false

Saw
33
Locker 7
2021
Japanese
true

Saw
34
Locker 7
2018
Coping
false

Upvotes: 1

Views: 494

Answers (1)

Abra
Abra

Reputation: 20914

First the code.
(Explanations after.)

public abstract class Equipment {
    private Integer id;
    private String locker;
    private Integer year;
    private String equipmentName;

    public Equipment(Integer id, String locker, Integer year, String name) {
        this.id = id;
        this.locker = locker;
        this.year = year;
        equipmentName = name;
    }

    public String toString() {
        return String.format("%s %s %s %s", equipmentName, id, locker, year);
    }
}

public class Drill extends Equipment {
    private Boolean batteryPowered;
    private Boolean needsNewBit;

    public Drill(String equipmentName, Integer id, String locker, Integer year,  Boolean batteryPowered, Boolean needsNewBit) {
        super(id, locker, year, equipmentName);
        this.batteryPowered = batteryPowered;
        this.needsNewBit = needsNewBit;
    }

    public String toString() {
        return String.format("%s %s %s", super.toString(), batteryPowered, needsNewBit);
    }
}

public class Saw extends Equipment {
    private String sawType;
    private Boolean needsGrinding;

    public Saw(String equipmentName, Integer id, String locker, Integer year, String sawType, Boolean needsGrinding) {
        super(id, locker, year, equipmentName);
        this.sawType = sawType;
        this.needsGrinding = needsGrinding;
    }

    public String toString() {
        return String.format("%s %s %s", super.toString(), sawType, needsGrinding);
    }
}

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Program {
    private static final String  DRILL = "Drill";
    private static final String  SAW = "Saw";

    public List<Equipment> readFromFile() throws IOException {
        File equipment = new File("equipment.txt");
        List<Equipment> equipmentList = new ArrayList<>();
        List<String> fields = new ArrayList<>();
        String line;
        String type = null;
        Equipment equip = null;
        try (Scanner reader = new Scanner(equipment)) {
            while (reader.hasNextLine()) {
                line = reader.nextLine();
                if (isTypeLine(line)) {
                    if (type != null) {
                        switch (type) {
                            case DRILL:
                                equip = createDrill(fields);
                                break;
                            case SAW:
                                equip = createSaw(fields);
                                break;
                            default:
                                equip = null;
                        }
                        if (equip != null) {
                            equipmentList.add(equip);
                        }
                    }
                    fields.clear();
                    type = line;
                }
                else {
                    fields.add(line);
                }
            }
            if (type != null) {
                switch (type) {
                    case DRILL:
                        equip = createDrill(fields);
                        break;
                    case SAW:
                        equip = createSaw(fields);
                        break;
                    default:
                        equip = null;
                }
                if (equip != null) {
                    equipmentList.add(equip);
                }
            }
            return equipmentList;
        }
    }

    private Drill createDrill(List<String> fields) {
        Integer id = Integer.valueOf(fields.get(0));
        String locker = fields.get(1);
        Integer year = Integer.valueOf(fields.get(2));
        Boolean batteryPowered = Boolean.valueOf(fields.get(3));
        Boolean needsNewBit = Boolean.valueOf(fields.get(4));
        Drill drill = new Drill(DRILL, id, locker, year, batteryPowered, needsNewBit);
        return drill;
    }

    private Saw createSaw(List<String> fields) {
        Integer id = Integer.valueOf(fields.get(0));
        String locker = fields.get(1);
        Integer year = Integer.valueOf(fields.get(2));
        String sawType = fields.get(3);
        Boolean needsGrinding = Boolean.valueOf(fields.get(4));
        Saw saw = new Saw(SAW, id, locker, year, sawType, needsGrinding);
        return saw;
    }

    private boolean isTypeLine(String line) {
        return DRILL.equals(line)  ||  SAW.equals(line);
    }

    public static void main(String[] args) {
        Program prog = new Program();
        try {
            List<Equipment> list = prog.readFromFile();
            list.forEach(System.out::println);
        }
        catch (IOException xIo) {
            xIo.printStackTrace();
        }
    }
}
  • I moved member equipmentName from the subclasses, i.e. Drill and Saw, to the superclass Equipment since one of the purposes of a base class is to contain members that are common to all subclasses. Hence better to have one equipmentName member in the superclass rather than have a separate member in each of the subclasses.
  • I added method toString to each of the classes Equipment, Drill and Saw only for debugging purposes.
  • In the text file, a group of lines, where the first line is either Drill or Saw defines a piece of equipment. Hence in the code (of method readFromFile, in class Program), whenever a line contains Drill or Saw, I save that in local variable type. I also know that we are starting a new definition. That means that either it is the first definition or that I have read all the lines that define the equipment. In the case of the latter, i.e. I have just read all the lines defining the equipment, I create an instance according to the value of type. I initialize type to null. This lets me know whether I am reading the first definition in the file.
  • After creating the appropriate instance, i.e. Drill or Saw, I add it to the list.
  • I use try-with-resources in method readFromFile to ensure that the file, equipment.txt, is closed.
  • Also in method readFromFile, when the while loop terminates, there may be values in fields which I have not yet converted to an instance of either Drill or Saw. Hence the if statement that comes after the while loop.
  • The following line (from method main in class Program) is known as a method reference. It just saves me some typing and it is only to display the value returned by method readFromFile to check that I got the expected result.
list.forEach(System.out::println);

The contents of file equipment.txt

Saw
12
Locker 1
2012
Hand
true
Saw
15
Locker 2
2012
Hack
true
Saw
14
Locker 2
2014
Japanese
true
Saw
1
Locker 3
2014
Coping
false
Saw
2
Locker 3
2014
Coping
true
Saw
12
Locker 1
2016
Japanese
false
Saw
3
Locker 1
2016
Hack
true
Saw
5
Locker 4
2016
Hand
true
Saw
6
Locker 4
2019
Hand
true
Drill
16
Locker 5
2019
false
true
Drill
17
Locker 5
2019
false
true
Drill
18
Locker 5
2001
true
false
Saw
20
Locker 6
2001
Hack
false
Saw
21
Locker 6
2001
Hack
true
Saw
31
Locker 7
2021
Japanese
false
Saw
32
Locker 7
2021
Japanese
false
Saw
33
Locker 7
2021
Japanese
true
Saw
34
Locker 7
2018
Coping
false

Output from running Program

Saw 12 Locker 1 2012 Hand true
Saw 15 Locker 2 2012 Hack true
Saw 14 Locker 2 2014 Japanese true
Saw 1 Locker 3 2014 Coping false
Saw 2 Locker 3 2014 Coping true
Saw 12 Locker 1 2016 Japanese false
Saw 3 Locker 1 2016 Hack true
Saw 5 Locker 4 2016 Hand true
Saw 6 Locker 4 2019 Hand true
Drill 16 Locker 5 2019 false true
Drill 17 Locker 5 2019 false true
Drill 18 Locker 5 2001 true false
Saw 20 Locker 6 2001 Hack false
Saw 21 Locker 6 2001 Hack true
Saw 31 Locker 7 2021 Japanese false
Saw 32 Locker 7 2021 Japanese false
Saw 33 Locker 7 2021 Japanese true
Saw 34 Locker 7 2018 Coping false

Upvotes: 2

Related Questions