Convert String to double in Java

0

I'm reading data from an external file with the CSV format. But this data is coming in String format. There is a price field that I need to convert to double for manipulation purposes.

Class Catalogs

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;


public class Catalog {

private ArrayList<Product> products = new ArrayList<Product>();

public ArrayList<Product> getProducts() {
    return products;
}

public void setProducts(Product p) {
    products.add(p);
}


public ArrayList<Product> showProducts(){
    for(Product prod : products){
        System.out.println("id:"+ prod.getId());
        System.out.println("Price:"+ prod.getPrice());
    }

    return getProducts();
}
public static void main(String[] args){
    File file = new File("C:\Users\casa\Desktop\catalog.csv");
    String line = new String();
    Product p = new Product();
    Catalog c = new Catalog();

    try {
        Scanner reader = new Scanner(file);
        while(reader.hasNext()){
            line = reader.nextLine();

            String[] value = line.split(",");

            p.setId(value[0]);
            p.setPrice(value[1]);

            c.setProducts(p);

        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    c.showProducts();
}

}

Class Products

public class Product {
private String id;
private double price;
public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}
public double getPrice() {
    return price;
}
public void setPrice(String p) {
    double price = Double.parseDouble(p);
    this.price = price;
}
}

I tried to use the parseDouble() method to transform the attribute when it was set by the setPrice method, but the following error occurred:

Exception in thread "main" java.lang.NumberFormatException: For input 
string: ""price""
at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
at sun.misc.FloatingDecimal.parseDouble(Unknown Source)
at java.lang.Double.parseDouble(Unknown Source)
at Product.setPrice(Product.java:16)
at Catalog.main(Catalog.java:41)
    
asked by anonymous 17.03.2018 / 05:04

3 answers

2

The function is correct. You can use both Double.parseDouble , and Double.valueOf , but both methods will return the exception NumberFormatException if the string is invalid, for example, using a comma instead of a floating point.

For example:

┌─────────────────────────────┬──────────┐
│ Double.valueOf("2");        │ Válido   │
├─────────────────────────────┼──────────┤
│ Double.valueOf("2.5");      │ Válido   │
├─────────────────────────────┼──────────┤
│ Double.valueOf("2.59");     │ Válido   │
├─────────────────────────────┼──────────┤
│ Double.valueOf("2.599");    │ Válido   │
├─────────────────────────────┼──────────┤
│ Double.valueOf("2,599");    │ Inválido │
├─────────────────────────────┼──────────┤
│ Double.valueOf("2.599,00"); │ Inválido │
├─────────────────────────────┼──────────┤
│ Double.valueOf("259:900");  │ Inválido │
├─────────────────────────────┼──────────┤
│ Double.valueOf("R$259");    │ Inválido │
└─────────────────────────────┴──────────┘
  

The table also holds for the Double.parseDouble () method

If you have invalid characters in your string , you must treat it before trying to convert to double . For this you can use RegEx or a simple String.replace , for example:

String preco1 = "2,599"
    .replace("(?:[^\d\,])", "") //Remove todos os caracteres não numerais e nem a vírgula
    .replace(",", "");            // Substitui a vírgula pelo ponto

String preco2 = "2.599,12"
    .replace("(?:[^\d\,])", "")
    .replace(",", "");

System.out.println( Double.valueOf(preco1) );
System.out.println( Double.valueOf(preco2) );

In your case, you are trying to convert the value "price" , and since this is not a numeric value (with or without floating point), the algorithm can not convert it.

    
17.03.2018 / 09:37
1

Let's go to the problems of this code:

  • The product should not be priced as String by default. You may even have an auxiliary method that does this for convenience, it is questionable whether it should be in the Product class, but can be done as something extra.
  • Do not use a price like double , this type is not accurate . Use a BigDecimal .
  • Exception capture in% with% does not do anything useful, so remove it.
  • You add a product to the catalog and not arrow products on it. It seems silly, but if you conceive a thing wrong, it will conceptualize several other things. And make the code less intuitive.
  • Catalog should not be in this class.
  • This Main() is very gambiarra, but I will not touch it.
  • Usually what makes interaction with the user is also usually out, so split() should be in another class, and maybe have another name. And it's weird and show and return the products.
  • If you are going to register a new product, create a new product, which you did not produce the result you expect.
  • Your main problem is being able to validate data entry. In another language I would adopt a different strategy , but the culture of Java is handles exceptions. Do not try to fix the dice, this is risky, if the person typed wrong show her that this is happening and teaches it to be right, besides being a better usability the risk of something going wrong is less.

More or less like this:

while(reader.hasNext()){
    String line = reader.nextLine();
    String[] value = line.split(",");
    Product p = new Product();
    p.setId(value[0]);
    try {
        p.setPrice(value[1]);
    } catch (NumberFormatException e) {
        System.out.println("valor digitado não é válido, tente novamente");
        continue;
    }
    c.addProduct(p);
}

private BigDecimal price;
public void setPrice(String p) {
    this.price = new BigDecimal(p);
}
    
17.03.2018 / 14:19
0

I was able to solve it! I added this line of code line = line.replaceAll("[\"R$ ]", ""); shortly after reading a line from the file to remove all special characters.

    
17.03.2018 / 15:24