Разобрать текстовый файл, разбить его на строки, вернуть список и сопоставить с объектами - PullRequest
0 голосов
/ 19 июня 2020

Итак, у меня есть 2 типа файлов, один для определения уровня, а другой для определения структуры блоков.

Мне нужно проанализировать их оба в список строк, который содержит строки, и go сверх список и по каждой строке разделите, проанализируйте и сопоставьте их с объектами java.

У меня нет подсказки, как это сделать, я читал о java io reader, но я запутался здесь, где и как его использовать.

Понимание содержания спецификации уровня отдельного уровня: это будет go по строкам, разделить и проанализировать их и сопоставить их с java объектами, в результате Объект LevelInformation.

PS Я уже написал и построил интерфейс LevelInformation (который работает, если я вручную напишу уровень, реализующий этот интерфейс), который содержит все, что есть в текстовом файле (имя уровня, скорости, фон и др. c ..) Так что в основном мне просто нужно проанализировать эти текстовые файлы и сопоставить их с этим интерфейсом.

    public interface LevelInformation {
       int numberOfBalls();
       // The initial velocity of each ball
       // Note that initialBallVelocities().size() == numberOfBalls()
// velocities created by (a,s) format. a = angle, s = speed.
       List<Velocity> initialBallVelocities();
       int paddleSpeed();
       int paddleWidth();
       // the level name will be displayed at the top of the screen.
       String levelName();
       // Returns a sprite with the background of the level
       Sprite getBackground();
       // The Blocks that make up this level, each block contains
       // its size, color and location.
       List<Block> blocks();
       // Number of blocks that should be removed
       // before the level is considered to be "cleared".
       // This number should be <= blocks.size();
       int numberOfBlocksToRemove();
    }

Пример файлов:

level_definition.txt

START_LEVEL
level_name:Square Moon
ball_velocities:45,500
background:image(background_images/night.jpg)
paddle_speed:650
paddle_width:160
block_definitions:definitions/moon_block_definitions.txt
blocks_start_x:25
blocks_start_y:80
row_height:100
num_blocks:4
START_BLOCKS
--ll--
--ll--
END_BLOCKS
END_LEVEL

block_definitions.txt

    #block definitions
bdef symbol:l width:100 height:100 fill:color(RGB(154,157,84))

#spacers definitions
sdef symbol:- width:30

Итак Мне нужно создать список, получить читателя и как-то его разобрать. Буду рад получить несколько советов, идей и помощь в этом. Спасибо.

public class LevelSpecificationReader {

   public List<LevelInformation> fromReader(java.io.Reader reader) {
      // ...
   }
}

Думаю, мне нужно:

  • Разделить файл на строки и составить из них список строк. Это означает, что каждая строка попадет в список в виде строки.

  • Получите каждую строку, а также разделите ее на не знаю на что, но для получения информации и карты в в нужный объект. Например:
    level_name: что-то, что мне нужно будет добавить «что-то» в «имя уровня» в моем интерфейсе.

Это моя неудачная попытка:

public List<LevelInformation> fromReader(java.io.Reader reader) throws IOException {
    ArrayList<String> listOfLines = new ArrayList<>();
    BufferedReader bufReader = new BufferedReader(new FileReader("file.txt"));
    String line = bufReader.readLine();
    while (line != null) {
        listOfLines.add(line);
        line = bufReader.readLine();
    }
    return listOfLines;
}

Этот код вызывает ошибку, потому что я возвращаю список строк, но мне нужен список LevelInformation.

Ответы [ 2 ]

1 голос
/ 19 июня 2020

Это не полное решение, поскольку код в вашем вопросе не является воспроизводимым примером , поскольку он не является полным. Где определения классов Block и Sprite и Velocity? Я догадался об этом и составил для них минимальные определения.

Я надеюсь, что приведенного ниже кода будет достаточно, чтобы помочь вам завершить ваш проект. Он основан на опубликованных вами деталях, включая образец файла: level_definition.txt

Class Sprite

import java.awt.Image;

public class Sprite {
    private Image  image;

    public Sprite(Image image) {
        this.image = image;
    }
}

class Velocity

public class Velocity {
    private int  speed;

    public Velocity(int speed) {
        this.speed = speed;
    }
}

Класс LevelDtl, реализующий ваш интерфейс: LevelInformation.
Лично я не вижу необходимости в интерфейсе. Я думаю, это должен быть класс.

public class LevelDtl implements LevelInformation {
    private String  levelName;
    private List<Velocity>  ballVelocities;
    private Sprite  background;
    private int  paddleSpeed;
    private int  paddleWidth;
    private List<Block>  blocks;
    private int  numBlocks;

    @Override
    public int numberOfBalls() {
        return ballVelocities == null ? 0 : ballVelocities.size();
    }

    @Override
    public List<Velocity> initialBallVelocities() {
        return ballVelocities;
    }

    @Override
    public int paddleSpeed() {
        return paddleSpeed;
    }

    @Override
    public int paddleWidth() {
        return paddleWidth;
    }

    @Override
    public String levelName() {
        return levelName;
    }

    @Override
    public Sprite getBackground() {
        return background;
    }

    @Override
    public List<Block> blocks() {
        return blocks;
    }

    @Override
    public int numberOfBlocksToRemove() {
        return numBlocks;
    }

    public void setBackground(Sprite bg) {
        background = bg;
    }

    public void setBallVelocities(List<Velocity> velocities) {
        ballVelocities = velocities;
    }

    public void setLevelName(String name) {
        levelName = name;
    }

    public void setPaddleSpeed(int speed) {
        paddleSpeed = speed;
    }

    public void setPaddleWidth(int width) {
        paddleWidth = width;
    }

    public String toString() {
        return String.format("Level: %s , Paddle: [speed = %d , width = %d]",
                             levelName,
                             paddleSpeed,
                             paddleWidth);
    }
}

Все методы с аннотацией @Override являются реализациями методов в интерфейсе LevelInformation. Также обратите внимание, что метод toString() предназначен только для целей отладки, поскольку я использую его в последнем классе, который вы назвали: LevelSpecificationReader. Он считывает файл level_definition.txt построчно, принимая формат, указанный в вашем вопросе, и строит и настраивает экземпляр класса LevelDtl, который затем добавляет к List. Наконец, приведенный ниже код печатает содержимое файла List. Конечно, используя образцы данных, которые вы указали в своем вопросе, List содержит только один элемент.

import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import javax.imageio.ImageIO;

public class LevelSpecificationReader {
    private static final String  BACKGROUND = "background:";
    private static final String  BALL_VELOCITIES = "ball_velocities:";
    private static final String  END_BLOCKS = "END_BLOCKS";
    private static final String  END_LEVEL = "END_LEVEL";
    private static final String  IMAGE = "image(";
    private static final String  LEVEL_NAME = "level_name:";
    private static final String  PADDLE_SPEED = "paddle_speed:";
    private static final String  PADDLE_WIDTH = "paddle_width:";
    private static final String  START_BLOCKS = "START_BLOCKS";
    private static final String  START_LEVEL = "START_LEVEL";

    private static void setBackground(LevelDtl level, String data) throws IOException {
        Objects.requireNonNull(level, "Null level.");
        if (data != null  &&  !data.isEmpty()) {
            // image(background_images/night.jpg)
            if (data.startsWith(IMAGE)) {
                String path = data.substring(IMAGE.length(), data.length() - 1);
                BufferedImage image = ImageIO.read(new File(path));
                level.setBackground(new Sprite(image));
            }
        }
    }

    private static void setInitialBallVelocities(LevelDtl level, String data) {
        Objects.requireNonNull(level, "Null level.");
        if (data != null  &&  !data.isEmpty()) {
            String[] numbers = data.split(",");
            if (numbers.length > 0) {
                List<Velocity> velocities = new ArrayList<>();
                for (String number : numbers) {
                    try {
                        int speed = Integer.parseInt(number);
                        Velocity velocity = new Velocity(speed);
                        velocities.add(velocity);
                    }
                    catch (NumberFormatException xNUmberFormat) {
                        // Ignore.
                    }
                }
                level.setBallVelocities(velocities);
            }
        }
    }

    private static void setPaddleSpeed(LevelDtl level, String data) {
        Objects.requireNonNull(level, "Null level.");
        if (data != null  &&  !data.isEmpty()) {
            int speed;
            try {
                speed = Integer.parseInt(data);
            }
            catch (NumberFormatException xNumberFormat) {
                speed = 0;
            }
            level.setPaddleSpeed(speed);
        }
    }

    private static void setPaddleWidth(LevelDtl level, String data) {
        Objects.requireNonNull(level, "Null level.");
        if (data != null  &&  !data.isEmpty()) {
            int width;
            try {
                width = Integer.parseInt(data);
            }
            catch (NumberFormatException xNumberFormat) {
                width = 0;
            }
            level.setPaddleWidth(width);
        }
    }

    /**
     * Start here.
     */
    public static void main(String[] args) {
        try (FileReader fr = new FileReader("level_definition.txt");
             BufferedReader br = new BufferedReader(fr)) {
               List<LevelInformation> levels = new ArrayList<>();
               LevelDtl level = null;
               String line = br.readLine();
               while (line != null) {
                   if (START_LEVEL.equals(line)) {
                       // End current level.
                       if (level != null) {
                           levels.add(level);
                       }
                       // Start next level.
                       level = new LevelDtl();
                   }
                   else if (line.startsWith(LEVEL_NAME)) {
                       level.setLevelName(line.substring(LEVEL_NAME.length()));
                   }
                   else if (line.startsWith(BALL_VELOCITIES)) {
                       setInitialBallVelocities(level, line.substring(BALL_VELOCITIES.length()));
                   }
                   else if (line.startsWith(BACKGROUND)) {
                       setBackground(level, line.substring(BACKGROUND.length()));
                   }
                   else if (line.startsWith(PADDLE_SPEED)) {
                       setPaddleSpeed(level, line.substring(PADDLE_SPEED.length()));
                   }
                   else if (line.startsWith(PADDLE_WIDTH)) {
                       setPaddleWidth(level, line.substring(PADDLE_WIDTH.length()));
                   }
                   line = br.readLine();
               }
               if (level != null) {
                   levels.add(level);
               }
               System.out.println(levels);
        }
        catch (IOException xIo) {
            xIo.printStackTrace();
        }
    }
}

Приведенный выше код обрабатывает только строки в файле level_definition.txt up в эту строку включительно:

paddle_width:160

Удачи с добавлением кода для обработки остального содержимого файла.

0 голосов
/ 19 июня 2020

Может быть, вы хотите сначала разбить его на части, чтобы вам не нужно было беспокоиться обо всех вещах сразу и сосредоточиться на синтаксическом анализе строк. Все, что вам нужно сделать, это создать конструктор, который принимает строку, а затем анализировать ее в конструкторе

public List<LevelInformation> fromReader(java.io.Reader reader) throws IOException {
ArrayList<LevelInformation> listOfLines = new ArrayList<>();
BufferedReader bufReader = new BufferedReader(new FileReader("file.txt"));
String line = bufReader.readLine();
while (line != null) {
    listOfLines.add(new LevelInformation(line));
    line = bufReader.readLine();
}
return listOfLines;

}

public class LevelInformation {

       LevelInformation (String text) {
           parseText(text);
       }

       private void parseText(String text) {

           //do something here
       }
}
...