Я создаю небольшое приложение на Java, небольшую игровую механику, но ничего серьезного. У меня есть класс, целью которого является получение данных из файла. Но когда я объявляю два класса для чтения из него, программа просто игнорирует все и продолжает работу. В результате, когда я пытаюсь получить доступ к соответствующим спискам, я получаю исключение с нулевым указателем. Код метода, который извлекает данные, ниже:
public void getData(int l, player tmp, level le) {
String[] dataPlayer;
String[] dataLevel;
try {
//FileReader f = new FileReader(this.levelPath.concat(Integer.toString(l)));
File f = new File(this.levelPath.concat(Integer.toString(l)));
BufferedReader buff = new BufferedReader(new FileReader(f));
System.out.println("Reached");
boolean eof = false;
while (!eof) {
String b = buff.readLine();
if (b == null)
eof = true;
else {
if (b.contains("player")) {
dataPlayer = b.split("-");
for (int i = 0; i < dataPlayer.length; i++) {
if (i == 0)
continue;
items it = new items(dataPlayer[i]);
tmp.setInventory1(it);
}
}else if (b.contains("level")) {
dataLevel = b.split("-");
for (int i = 0; i < dataLevel.length; i++) {
if (i == 0)
continue;
items it = new items(dataLevel[i]);
le.setSpecific(it);
}
}
}
}
}catch (IOException i) {
i.getMessage();
}
}
Содержимое файла "levelData1":
player-hat
player-flashlight
level-flower
level-rock
player-adz
Проблема с этой конкретной проблемой заключалась в пути, ему нужен был абсолют вроде этого / home / toomlg4u / IdeaProjects / javaProject / src / Data / levelData.
@NiVeR Мне это нужно, потому что у меня есть 3 файла для 3 уровней и атрибут с именем levelpath, который равен «levelData», поэтому я объединяю аргумент l, который представляет собой число, которое пользователь дает, например, 1,2,3 (уровни), поэтому я открываю соответствующий файл для чтения. Но реально озадачен этим ...
вы пробовали отладку? вы можете остановиться в одном из циклов, где создаются элементы, чтобы проверить, попадает ли он внутрь.
Я пробовал это, он никогда не опускается ниже класса bufferedReader
Тогда у вас должно быть какое-то исключение, вы что-то видите?
Я должен добавить, потому что ничего не вижу. Я попробую это.
1) }catch (IOException i) { i.getMessage(); } Не уверен, что вы ожидать, чтобы произойти в этом коде, но ничего полезного будут не происходит. Измените его на }catch (IOException i) { i.printStackTrace(); } 2) Для более быстрого получения помощи отправьте минимальный воспроизводимый пример или Краткий, автономный, правильный пример.
@AndrewThompson Это помогло мне и доказало, что файл не существует, по крайней мере, согласно программе.
Прохладный. Да, трассировки стека могут быть очень информативными. Теперь, возможно, замените File f = new File(this.levelPath.concat(Integer.toString(l))); на File f = new File(this.levelPath.concat(Integer.toString(l))); System.out.println(f.getAbsolutPath());. Убедитесь, что он указывает на то, куда указывает считать.




Вы делаете много вещей внутри этого метода try / catch, которые могут не вызывать исключения IOException. Если вы получите другое исключение, его не поймают. В зависимости от того, какая другая обработка исключений у вас есть, это может вызвать странное поведение. Для отладки вы можете перехватить все исключения и посмотреть, получаете ли вы что-нибудь еще.
Теперь я убежден, что проблема в объекте BufferReader, после чего код не трогается.
Хорошо, теперь убеди меня в этом. =] В этой ситуации я всегда рекомендую сократить код до максимально простого, в том числе вырезать все ПОСЛЕ, когда вы думаете, что может произойти ошибка. Для вашего примера, поскольку есть код, который не достигается, избавьтесь от этого кода (закомментируйте его, создайте новый проект только с тем кодом, который, как вы знаете, работает, что угодно. Не выполняйте никаких вложенных вызовов функций, по одной операции на Установите точку останова перед тем местом, где, по вашему мнению, возникла ошибка, и переходите через код, проверяя все по ходу. Это должно указать вам на проблему.
Вот так должна выглядеть достойная программа на Java:
private Stream<Items> asStreamOfItems(String line){
return Stream.of(line.split("-")).skip(1).map(Items::new);
}
public void parseFile(String pathToTheFile) throws IOException {
List<String> lines = Files.readAllLines(Paths.get(pathToTheFile));
List<Items> players = lines.stream().filter(line -> line.contains("player")).flatMap(this::asStreamOfItems).collect(Collectors.toList());
List<Items> levels = lines.stream().filter(line -> line.contains("level")).flatMap(this::asStreamOfItems).collect(Collectors.toList());
........
}
В этом случае все ваши странные ошибки исчезнут.
После того, как вы отредактировали сообщение, я увидел содержимое вашего файла. В этом случае код должен выглядеть так:
class Items {
private final String name;
public Items(String name) {
this.name = name;
}
public String getName() {
return name;
}
public static Items parse(String line) {
return new Items(line.split("-")[1]);
}
}
public void parseFile(String pathToTheFile) throws IOException {
List<String> lines = Files.readAllLines(Paths.get(pathToTheFile));
List<Items> players = lines.stream().filter(line -> line.contains("player")).map(Items::parse).collect(Collectors.toList());
List<Items> levels = lines.stream().filter(line -> line.contains("level")).map(Items::parse).collect(Collectors.toList());
..............
}
Кстати, вы нарушили много правил Java и общих правил программирования, таких как:
tmp.setInventory1(it);) очень-очень-очень плохая практика«Вот как делается настоящий дом. Так что снести свой, потому что он старый и уродливый, кого волнует, есть ли у вас ресурсы».
Я новичок в Java, и этот метод есть в книге моего учителя. Конечно, не из лучших, но надо было с чего-то начинать. Кстати, ваш код может работать, но у меня есть многое, чтобы добраться до этого уровня, поэтому я пока буду придерживаться основ.
Не волнуйся, приятель, я постараюсь изо всех сил. Я бы хотел увидеть вас, когда вы в компании столкнетесь со своим первым унаследованным проектом, прокомментируете, что код отстой, и расскажите авторам, как нужно было его писать.
Если вы хотите остаться в коде цикла, вы можете реорганизовать свой код, чтобы он выглядел так:
public void getData(int l, player tmp, level le) {
try (BufferedReader buff = new BufferedReader(new FileReader(new File(this.levelPath + l)))) {
String b;
while ((b = buff.readLine()) != null) {
if (b.contains("player")) {
String[] dataPlayer = b.split("-");
items it = new items(dataPlayer[1]); //because you know that you will have an array with only 2 elements
tmp.setInventory1(it);
}else if (b.contains("level")) {
String[] dataLevel = b.split("-");
items it = new items(dataLevel[1]); //because you know that you will have an array with only 2 elements
le.setSpecific(it);
}
}
}catch (IOException e) {
e.printStackTrace();
}
}
Он немного лучше, чем у вас, его легче отлаживать и читать. Советую прочитать про попробуйте с ресурсами.
Как правило, каждый раз, когда вы открываете поток, вы должны его закрывать. Если вы не открываете его сами, не закрывайте его.
Это не сработает, по какой-то причине в моем исходном коде и в вашем теперь он не найдет файл. Я даже пробовал абсолютный путь.
как начать проект?
Я снова изменил путь, и это сработало. НО, снова остановившись в строке, я передаю новый элемент (его) в свой tmp.setInventory1. С исключением нулевого указателя.
Вы можете использовать эту строку, например: try (BufferedReader buff = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/game.txt")))), и в этом случае файл game.txt должен быть помещен в путь к классу. Если у вас все еще есть NPE, опубликуйте содержимое класса player, чтобы я мог видеть содержимое метода setInventory1.
Я предполагаю, что
buffимеет значение null, вычисление имени файла кажется немного сложным. Или файл пуст.