Olá a todos! Venho me deparando com erros estranhos no java desde que mudei de sistema operacional. Antes eu usava windows 7 e não tinha os mesmos problemas.
Veja, já estou a 1 ano programando em java e esses métodos que estou usando já utilizei em diversos outros problemas parecidos e consegui executar.
Agora, estava fazendo o código do curso do Nélio alvez, usando a mesma versão java que ele, entretanto encontrei o erro dentro do while, aparentemente o while executa a condição mas ele está deixando passar mesmo se a condição não for satisfeita. Cheguei a esta conclusão tentando captar o dado que não deveria entrar e consegui com exito!
package genericoDelimitado.application;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import genericoDelimitado.entities.Product;
import genericoDelimitado.services.*;
public class Program {
public static void main(String[] args) {
List<Product> list = new ArrayList<>();
String path = "/home/washington/Documentos/produtos.txt";
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
String line = br.readLine();
while (line != null) {
String[] fields = line.split(",");
if(fields.length == 0 || fields.length <= 1) {
Product x = CalculationService.max(list);
System.out.println("Max:");
System.out.println(x);
}else {
System.out.println(fields[0].toString() + fields[1].toString());
list.add(new Product(fields[0], Double.parseDouble(fields[1])));
line = br.readLine();
}
}
Product x = CalculationService.max(list);
System.out.println("Max:");
System.out.println(x);
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
Veja que dentro do if, eu coloquei o código que seria executado após while, mas ele nunca chegou a ser executado por conta que a linha vazia do arquivo estava entrando mesmo não sendo permitido pela condição. Com esse if consegui capturar o erro e identificar que era realmente isto que estava acontecendo.
Logo quando o código é executado, ele entra em um loop infinito uma vez que assim que ele lê todos os caracteres, ele entra nas linhas vazias e conseqüentemente no if, fazendo com que o código dentro do bloco seja executado até você forçar parada na ide. Detalhe, estou usando eclipse(primeira vez que uso, sempre usei netBeans)
Alguém tem uma ideia do que possa ser e como resolver este problema??
Aquele readLine
dentro do else
deveria estar fora dele.
Então, ao invés de deixar assim:
} else {
System.out.println(fields[0].toString() + fields[1].toString());
list.add(new Product(fields[0], Double.parseDouble(fields[1])));
line = br.readLine();
}
}
Deixa assim:
} else {
System.out.println(fields[0].toString() + fields[1].toString());
list.add(new Product(fields[0], Double.parseDouble(fields[1])));
}
line = br.readLine();
}
1 curtida
Qualquer computador, seja ele físico (o que vc usa), ou a máquina virtual Java, é uma máquina determinística. Não existe mágica ou exoterismo. É impossível um algoritmo que funcionava ontem ou há um milhão de anos parar de funcionar ou começar a funcionar errado para as mesmas entradas. Tenha certeza, em 99,99999999999999999999% das vezes é o programador que está errando, no caso você. É claro, existem falhas sistêmicas que podem existir, ou seja, um problema físico no processador ou na JVM, mas se esse for o caso, provavelmente o computador como um todo não vai funcionar direito, se é que vai funcionar.
1 curtida
Dessa maneira funcionou, porem, como estava dando erro no caso da condição do while aparentemente ser desconsiderada?
No código é visivel que dentro do while eu coloco um if parfa captar exatamente a condição que o while não deveria deixar passar, ou seja, enquanto não fosse nulo executasse. Porém, mesmo com essa condição ele lê diversas vezes linhas vazias.
O valor que sua condição depende só está sendo atualizado no else como o @wldomiciano já indicou. Vc tem um problema na lógica do seu algoritmo, ou seja, vc errou. Como você quer quer o while se comporte da forma que vc quer se o seu código está errado? Talvez se vc identar direito seu código isso já te ajude a entender melhor seu problema. Será que não é um pouco de exagero vc estar convencido que para algo tão trivial e simples a JVM esteja se comportando erroneamente? Sei que é meio pedante usar o argumento da autoridade, mas mesmo assim vou usar. Pode acreditar na gente, os poucos que ainda respondem aqui no GUJ sabem o que estão falando
1 curtida
Sim, nesse código específico a variável pega certinho quando você tira o a leitura do buffer do Else. O problema é que o algoritmo não tem if e nem Else. Isso eu usei apenas para captar a condição que não satisfaz o while. E sim, essa condição ainda está sendo captada. Mesmo eu usando a leitura do buffer depois do Else, ela capta a linha null. A diferença é que agora ela apenas capta uma vez e para, mas usando o algoritmo original mesmo, ele da um erro logo de início na captura desse null. Eu apenas coloquei o if para poder indentificar se realmente a condição que não satisfaz o while estava entrando dentro do bloco de execução e sim, ele está entrando.
O que o nosso amigo mostrou no algoritmo dele satisfaz o que eu queria, ele devolve o produto mais caro, entretanto, o while ainda deixa passar as linhas vazias do null.
Linhas vazias do null? Uma linha vazia não é nula, é uma string vazia. O BufferedReader retorna null quando chega no fim do arquivo. Talvez seja isso que vc não está entendendo e está misturando as coisas.
Pow, pode ser. Vou mudar a condição do while para ver se funciona. Eu achei que como uma linha vazia da um erro de null exception era entendida como tal. Vou fazer isso e ver o resultado. De qualquer forma obrigado por tudo.
Sem ver como está o arquivo, fica difícil adivinhar. Mas enfim, o que pode ter acontecido é que chegou em uma linha que não tem nenhuma vírgula, por isso o split
retornou um array com tamanho 1 e entrou no if
. E como dentro do if
vc não lê mais nenhuma linha (pois o readLine
está dentro do else
), o programa entra em loop.
Aproveitando, geralmente costuma-se ler as linhas de um BufferedReader
assim:
String line;
while ((line = br.readLine()) != null) { // lê a próxima linha e já vê se é null
String[] fields = line.split(",");
if (fields.length <= 1) { // testar se é igual a zero é redundante, pois se for zero, então será menor que 1
Product x = CalculationService.max(list);
System.out.println("Max:");
System.out.println(x);
} else {
System.out.println(fields[0] + fields[1]); // não precisa chamar toString()
list.add(new Product(fields[0], Double.parseDouble(fields[1])));
}
}
Ou seja, (line = br.readLine()) != null
lê a próxima linha, guarda o resultado em line
e já testa se é nulo. Assim, vc não precisa mais chamar readLine
dentro do loop, e garante que a cada iteração uma nova linha será lida.
Também mudei a condição para somente fields.length <= 1
. Não precisa testar se é zero, pois se for zero, então será menor que 1 (e o length
nunca é negativo, então só esse teste já basta).