解析文本文件,将其拆分为行,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) {
// ...
}
}
我认为我需要:
将文件分成多行,并从中创建一个字符串列表。
这意味着每一行都将作为字符串进入列表。
获取每一行,也拆分成不知道是什么,但是按顺序
获取信息并映射到所需的对象中。例如:
level_name: 东西
我必须在我的界面中将 "something" 设置为 "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;
}
此代码带来错误,因为我 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
祝你好运,添加代码来处理文件的其余内容。
所以我有两种类型的文件,一种用于关卡定义,另一种用于块结构定义。
我需要将它们都解析为包含行的字符串列表,然后遍历列表和每一行,拆分并解析并将它们映射到 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) {
// ...
}
}
我认为我需要:
将文件分成多行,并从中创建一个字符串列表。 这意味着每一行都将作为字符串进入列表。
获取每一行,也拆分成不知道是什么,但是按顺序 获取信息并映射到所需的对象中。例如:
level_name: 东西 我必须在我的界面中将 "something" 设置为 "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;
}
此代码带来错误,因为我 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
祝你好运,添加代码来处理文件的其余内容。