解析文本文件,将其拆分为行,return 列表并映射到对象

Parse a text file, split it into lines, return a list and map into objects

所以我有两种类型的文件,一种用于关卡定义,另一种用于块结构定义。

我需要将它们都解析为包含行的字符串列表,然后遍历列表和每一行,拆分并解析并将它们映射到 java 个对象中。

我不知道如何去做,我已经阅读了关于 java io reader 但我确实对在哪里以及如何使用它感到困惑。

了解单个级别的级别规范内容:这将遍历字符串,拆分和解析它们,并将它们映射到java个对象,从而得到一个LevelInformation对象。

P.S 我已经编写并构建了 LevelInformation 接口(如果我手动编写一个实现该接口的关卡,它就可以工作),它包含文本文件中的所有内容(关卡名称、速度、背景)等等..) 所以基本上我只需要解析那些文本文件并将它们映射到这个界面。

    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

所以我需要创建一个列表并获得一个 reader 并以某种方式解析它。 我很乐意为此获得一些提示、想法和帮助。 谢谢。

public class LevelSpecificationReader {

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

我认为我需要:

这是我失败的尝试:

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;
}

此代码带来错误,因为我 return 一个字符串列表,但我需要一个 LevelInformation 列表。

也许你想要的是先把它分解成碎片,这样你就不需要一次担心所有的事情,而专注于解析字符串。您需要做的就是创建一个接受字符串的构造函数,然后在构造函数中解析它

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
       }
}

这不是一个完整的解决方案,因为您问题中的代码不是 reproducible example,因为它不完整。 classes Block and Sprite and 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;
    }
}

Class LevelDtl 实现了你的接口:LevelInformation.
就个人而言,我认为不需要界面。我觉得应该是 class.

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() 仅用于调试目的,因为我在最后的 class 中使用了它,也就是您命名的方法:LevelSpecificationReader。它逐行读取文件 level_definition.txt ,假定您的问题中显示的格式并构建和配置 class 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 中直到并包括这一行的行:

paddle_width:160

祝你好运,添加代码来处理文件的其余内容。