I'm trying to tokenize a String and save it to a binary file, but when I run the program, I get a NumberFormatException. Here is my stack trace:
Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: " 1"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:481)
at java.lang.Integer.parseInt(Integer.java:527)
at Project6.saveBSAFile(Project6.java:187)
Here is my code, which is trying to tokenize a String and save it to a binary file:
public void saveBSAFile() throws FileNotFoundException, IOException
{
jfc.setDialogTitle("Specify a file to save");
int userSelection = jfc.showSaveDialog(this);
if (userSelection == jfc.APPROVE_OPTION)
{
File filename = jfc.getSelectedFile();
JOptionPane.showMessageDialog(null, "File to save " + filename,
"Save Review", JOptionPane.INFORMATION_MESSAGE);
FileOutputStream FOStream1 = new FileOutputStream(filename, true);
DataOutputStream DOStream1 = new DataOutputStream(FOStream1);
}
else if (userSelection == jfc.CANCEL_OPTION)
{
return;
}
int index = 0;
while (tools.getNumberOfItems() <= 10 && processRec.getToolRecords(index) != null)
{
StringTokenizer tokens = new StringTokenizer(processRec.getToolRecords(index), "|:");
toolStrTok = tokens.nextToken();
toolNameTok = tokens.nextToken();
idStrTok = tokens.nextToken();
idTok = tokens.nextToken();
qualStrTok = tokens.nextToken();
qualTok = tokens.nextToken();
stockStrTok = tokens.nextToken();
stockTok = tokens.nextToken();
priceStrTok = tokens.nextToken();
priceTok = tokens.nextToken();
idTok.trim();
qualTok.trim();
stockTok.trim();
priceTok.trim();
id = Integer.parseInt(idTok);
quality = Integer.parseInt(qualTok);
numInStock = Integer.parseInt(stockTok);
price = Double.parseDouble(priceTok);
FileOutputStream FOStream2 = new FileOutputStream(filename, true);
DataOutputStream DOStream2 = new DataOutputStream(FOStream2);
DOStream2.writeUTF(toolStrTok);
DOStream2.writeUTF(" " + toolNameTok);
DOStream2.writeUTF(" " + idStrTok + " ");
DOStream2.writeInt(id);
DOStream2.writeUTF(" " + qualStrTok + " ");
DOStream2.writeInt(quality);
DOStream2.writeUTF(" " + stockStrTok + " ");
DOStream2.writeInt(numInStock);
DOStream2.writeUTF(" " + priceStrTok + " ");
DOStream2.writeDouble(price);
DOStream2.close();
index++;
}//end loop
}//end saveBSAFile
And here is the String i'm attempting to tokenize, which is being pulled from a method in another class file(which is being referenced by a call to processRec):
public String getRecord(int index)
{
return "Tool Name: " + toolArray[index].getName()
+ "| Tool ID: " + toolArray[index].getToolID()
+ "| Tool Quality: " + toolArray[index].getQuality()
+ "| Number in Stock: " + toolArray[index].getNumberInStock()
+ "| Tool Price: " + toolArray[index].getPrice();
}//end getRecord
I've tried a few different things, such as trimming the Strings using trim() i'm attempting to tokenize, but that didnt seem to work :( I also tried reworking the code a bit but that hasn't netted me much luck, either. I'm very much a novice when it comes to exceptions and stack traces, so I was hoping someone may be able to point out any obvious(or not so obvious) mistakes I may be making. Thanks so much in advance :)
The trim() method doesn't change the original String; it's immutable.
Returns a string whose value is this string, with any leading and trailing whitespace removed.
(emphasis mine)
The trim method returns the trimmed String, but you discard the returned String. idTok is still " 1", with spaces.
Change
idTok.trim();
to
idTok = idTok.trim();
and likewise with the other tokens. Then parseInt will see the trimmed string (e.g. "1") and parse the integers correctly.
Related
I need a quick help with my code. I think it all works fine, but I have just one problem. I need to split every line of text file and add each of them to array. This assignment is about using RandomAccessFile class. And problem is - I can't split these lines from text file. It only says that each array is null.
I was typing any regex that I found online into String.split. Nothing works. I was also trying to use Scanner, but it went much worse.
try(RandomAccessFile raf = new RandomAccessFile("domy.txt", "rw")){
while((str = raf.readLine()) != null){
String[] data = new String[100];
data = str.split("\n");
String name = data[0];
String floors = data[1];
String price = data[2];
String location = data[3];
System.out.println(data[0] + " " + data[1] + " " + data[2] + " " + data[3]);
if(floors.equals("1") && location.equals("Wies")){
var floorsInt = Integer.parseInt(floors);
var priceDouble = Double.parseDouble(price);
raf.seek(raf.getFilePointer() - str.length());
raf.writeBytes(name + "\n" + floorsInt + "\n" + df.format(priceDouble * 0.9) + "\n" + location);
}
}
}
catch(FileNotFoundException e){
e.printStackTrace();
The most common errors are "Index 1 out of bounds for length 1" and "floors is empty"
Willa
3
1000000.00
Miasto
Chata
1
99999.99
Wies
Here is what I have in a text file
I'm writing a method that edits a record in a CSV file, which should print everything except for the line im editing, then print the edited version onto a new file.
while((line = br.readLine()) != null) {
if(line.contains("PATRON")) {
pw.println(line);
}
if(!line.contains("PATRON")) {
String[] str = line.split(",", 7);
if(str[1].equals(ID)) {
pw.println(str[0] + "," + ID + "," + str[2] + "," + "false" + "," + "0" + "," + str[5] + "," + "0");
}else {
pw.println(line);
}
}
}
When i try to run this and enter a valid ID, it gives me this exception
java.lang.ArrayIndexOutOfBoundsException: 1
at myproject.Materials.returnmat(Materials.java:296)
at myproject.Library.mmenu(Library.java:121)
at myproject.Library.mainmenu(Library.java:143)
at myproject.Library.main(Library.java:11)
However after running some tests,
for(int x=0;x<str.length;x++) {
System.out.println(x+ ": " +str[x]);
}
It outputs exactly what id expect, 1: 101, 1:102, etc..
So this shows me that the ID is definitely at the str[1] index.
Why is it throwing me the exception?
EDIT: If its relevant, here's how im calling it.
case "7":
System.out.println("Enter material ID: ");
String matsid = scan.nextLine();
mats.returnmat(matsid);
scan.nextLine();
break;
Check your string length before doing if(str[1].equals(ID)) {
Something like :
if(str.length<1) {
System.out.println("line no good="+line);
} else ...
It's likely you have a bad line in the CSV or maybe this is the last blank line.
Here
String[] str = line.split(",", 7);
if(str[1].equals(ID)) {
the splitting line must have had return array of length=1 thus maximum index would be 0 - but you are exceeding it using str[1];
Part of the program I am creating requires a check to see if the same string (Indicating a product's ID code) has already been written into a text file. This is to stop the same ID being written in twice.
I am using a Boolean method which passes in a string from the GUI user input, and then compares it to every already existing line in the file.
The method is below.
public boolean hasIDAlreadyBeenUsed(String IDBeingTested) {
boolean Decision = false;
String ID = "Product ID: "+IDBeingTested;
BufferedReader theBR;
Scanner scanner;
String scannedString;
try {
theBR = new BufferedReader(new FileReader("ProductData.txt"));
scanner = new Scanner(new File("ProductData.txt"));
while (scanner.hasNextLine()) {
scannedString = scanner.nextLine();
String character = scanner.findInLine(ID);
if ((character) == (ID)) {
Decision = true;
System.out.println("they are a match: " + ID);
} else {
Decision = false;
}
}
theBR.close();
theBR = null;
} catch (IOException ioe) {
Decision = false;
System.out.println(ioe);
}
return Decision;
}
if the boolean returns a false, the data will be written into the file, if it returns a true an error message will appear and no data is written.
Below is the code that relies upon the boolean output.
private void jAddProductToDatabseButtonActionPerformed(java.awt.event.ActionEvent evt) {
if (!product.hasIDAlreadyBeenUsed(jProductIDTextField.getText())) {
try {
BufferedWriter ProductFileWriter = new BufferedWriter(new FileWriter("ProductData.txt", true));
ProductFileWriter.write("Product Name: " + jProductNameTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product ID: " + jProductIDTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Weight: " + jProductWeightTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Selling Price (£): " + jProductSellingPriceTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Image File Name: " + jNameOfImageFileTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Manufacturer Address: " + jManufacturerAddressTextArea.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Type: " + jProductTypeTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Unit Cost: " + jProductUnitCostTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Delivery Time: " + jProductDeliveryTimeTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Shelf Life: " + jProductShelfLifeTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("Product Stock Level: " + jInitialStockLevelTextField.getText() + System.getProperty("line.separator"));
ProductFileWriter.write("==============================" + System.getProperty("line.separator"));
ProductFileWriter.flush();
ProductFileWriter.close();
ProductFileWriter = null;
}
catch (IOException ioe) {}
}
else {
JOptionPane.showMessageDialog(null, "Cannot input, ID HAS ALREADY BEEN USED", "Incorrect ID", JOptionPane.ERROR_MESSAGE);
}
}
However the else statement is never executed, even if the same number e.g 44 has been entered as ID multiple times.
I even used this inside to show that the strings were the same. and the same string is produced twice.
while (scanner.hasNextLine()) {
scannedString = scanner.nextLine();
String character = scanner.findInLine(ID);
System.out.println(scannedString);
System.out.println("Product ID: " + ID);
You have to break loop once you found match, otherwise Decision value being overwritten for next line.
public static boolean hasIDAlreadyBeenUsed(String IDBeingTested) {
boolean Decision = false;
String ID = "Product ID:" + IDBeingTested;
Scanner scanner;
String scannedString;
try {
scanner = new Scanner(new File("src/ProductData.txt"));
while (scanner.hasNextLine()) {
scannedString = scanner.nextLine();
if (scannedString.equalsIgnoreCase(ID)) {
Decision = true;
System.out.println("they are a match: " + ID);
break;
}
}
} catch (IOException ioe) {
Decision = false;
System.out.println(ioe);
}
return Decision;
}
Also i don't think you need findInLine method here. I hove this will solve your problem. Use file path according to your project structure.
Note:: It is good if we follow naming conventions in code.
It seems that the error is coming from this statement:
if ((character) == (ID)) {
This compares if the String objects are the same.
Using the following:
if (character.equals(ID)){
should compare the value of the Strings instead.
First of all you are using Scanner and BufferedReader, in your case either can be used but both are not required to solve your issue.
You can try something snippet like.
public static boolean hasIDAlreadyBeenUsed(String IDBeingTested) throws IOException {
boolean Decision = false;
String ID = "Product ID: "+IDBeingTested;
BufferedReader theBR = null;
String scannedString;
try {
theBR = new BufferedReader(new FileReader("ProductData.txt"));
while ((scannedString=theBR.readLine())!=null) {
if(!Decision)
Decision = scannedString.contains(ID);
else
break;
}
} finally {
theBR.close();
}
return Decision;
}
Also a tip I would like to give, Don't start the variable name with Capital letter(Usually Classes have the first letter in capital). You can refer some online tutorial for good programming practices.
Cheers,
Change your comparison code to the following in hasIDAlreadyBeenUsed() method:
String character = scanner.findInLine(ID);
if ((character.trim().equals(ID)) { // by trimming I'm removing the line separator and then use equals to do a string comparision.
Decision = true;
System.out.println("they are a match: " + ID);
} else {
Decision = false;
}
I have a text file, and I want to find the middle word of the whole file and print the number of characters it has. I can do this for one line:
System.out.println("'" + str[tok / 2] + "'");
But I don't know how to point to a certain line. Here is all of my code:
import java.io.*;
import java.text.*;
import java.util.*;
public class AmendClassify {
public static void main(String[] args) {
try {
System.out.println("Please enter the file name:");
Scanner sc = new Scanner(System.in);
String file = sc.next();
file = file + ".txt";
Scanner s = new Scanner(new FileReader(file));
System.out.println("You are scanning '" + file + "'");
PrintWriter output = new PrintWriter(new FileOutputStream("output.txt"));
double lineNum = 0;
double wordCount = 0;
double charCount = 0;
int tok = 0;
String str[] = null;
DecimalFormat df = new DecimalFormat("#.#");
String line = null;
while (s.hasNextLine()) {
line = s.nextLine();
lineNum++;
str = line.split((" "));
tok = str.length;
for (int i = 0; i < str.length; i++) {
if (str[i].length() > 0) {
wordCount++;
}
}
charCount += (line.length());
}
double density = (charCount / wordCount);
System.out.println("'" + str[tok / 2] + "'"); // middle word of the 1st/last line
gap();
System.out.println("Number of lines: " + lineNum);
System.out.println("Number of words: " + wordCount);
System.out.println("Number of characters: " + charCount);
gap();
System.out.println("The DENSITY of the text is: " + df.format(density));
System.out.println();
int critical;
System.out.println("Do you want to alter the critical value(Y/N)");
String answer = sc.next();
if (answer.equals("y") || answer.equals("Y")) {
System.out.println("Please enter a value: ");
critical = sc.nextInt();
} else {
critical = 6;
}
//So...
if (density > critical) {
System.out.println("NAME: '" + file + "'" + ", DENSITY: " + df.format(density) + ", TYPE: " + "Heavy");
} else {
System.out.println("NAME: '" + file + "'" + ", DENSITY: " + df.format(density) + ", TYPE: " + "Light");
}
System.out.print("--FINISHED--");
s.close();
output.close();
sc.close();
} //end of try
catch (FileNotFoundException e) {
System.out.println("Please enter a valid file name");
}
} // end of main
public static void gap() {
System.out.println("------------------------------");
}
}
A text file I have used to test is
Hello my name is Harry. This line contains 83 characters, 15 words, and 1 line(s).
This is the second line.
This is the third line.
This is the fourth line.
Since this looks like a homework assignment I'd recommend reading the entire file into a String and then removing all new-line characters with replaceAll() if need be (depending how you read the entire file into a String). You then would effectively have a single line ... so your existing code would work (taking into account that the middle word would actually be the word to the left of the middle if the file has an even number of words).
Note that this is not an optimal solution though. Don't use it at work.
I'm trying to wrap my head around this problem and any help would be appreciated. I am trying to get the user to enter a string, beginning with a single digit (1-9). When the string is entered I need to print a substring, but only up to the number that was entered. For example, if the user was to type "4 big houses", my output should be "4 bi". I have it displaying correctly, however my code is very long winded with a lot of else if statements.
What would an alternative method be to reduce the amount of line of code?
Also, as is, I get a "string index out of range" exception if the user does not enter enough characters, ie if the string starts with a 4, but only contains 3 characters...
else if (text.substring(0,1).matches("[0-9]"))
{
if (text.substring(0,1).matches("1"))
{
String text2 = text.substring(0, 1);
System.out.println("The decoded string is: " + text2 + ", and starts with a 1!");
}
else if (text.substring(0,1).matches("2"))
{
String text2 = text.substring(0, 2);
System.out.println("The decoded string is: " + text2 + ", and starts with a 2!");
}
else if (text.substring(0,1).matches("3"))
{
String text2 = text.substring(0, 3);
System.out.println("The decoded string is: " + text2 + ", and starts with a 3!");
}
else if (text.substring(0,1).matches("4"))
{
String text2 = text.substring(0, 4);
System.out.println("The decoded string is: " + text2 + ", and starts with a 4!");
}
else if (text.substring(0,1).matches("5"))
{
String text2 = text.substring(0, 5);
System.out.println("The decoded string is: " + text2 + ", and starts with a 5!");
}
else if (text.substring(0,1).matches("6"))
{
String text2 = text.substring(0, 6);
System.out.println("The decoded string is: " + text2 + ", and starts with a 6!");
}
else if (text.substring(0,1).matches("7"))
{
String text2 = text.substring(0, 7);
System.out.println("The decoded string is: " + text2 + ", and starts with a 7!");
}
else if (text.substring(0,1).matches("8"))
{
String text2 = text.substring(0, 8);
System.out.println("The decoded string is: " + text2 + ", and starts with a 8!");
}
else if (text.substring(0,1).matches("9"))
{
String text2 = text.substring(0, 9);
System.out.println("The decoded string is: " + text2 + ", and starts with a 9!");
}
}
You can convert the first character of your string to an int, and then collapse all your variants for 1 - 9 into one using that int value. To prevent the "string index out of bounds" message, just check the string is long enough:
if (text.substring(0,1).matches("[0-9]")) {
int charCount = Integer.parseInt(text.substring(0, 1));
String text2 = text;
if (text.length() > charCount) {
text2 = text.substring(0, charCount);
}
System.out.println(text2);
}
You need to grab the first character in the string and convert it to a number.
So:
int number = Integer.parseInt(text.substring(0,1));
String text2 = text.substring(0,number);
System.out.println("The decoded string is: " + text2 + ", and starts with a " + number +"!");
parseInt() can throw a NumberFormatException if the first character isn't a number, so maybe use a try/catch block.
don't use if/else for this. Store the number entered in a variable and use it in the substring() method
NOTE: not totally correct syntax-example ONLY
if(text[0].matches([0-9]){
var endPoint= parseInt(text[0]);//parseInt means parseInteger
String text2 = text.substring(0, endPoint);
System.out.println("The decoded string is: " + text2 + ", and starts with a"+endPoint+"!");
}
Try this:
String sub = text.substring(0,1);
if(sub.matches("[0-9]")) {
try{
System.out.println("The decoded string is: "
+ text.substring(0, Integer.parseInt(sub))
+ "and starts with a " + sub + "!");
} catch(Exception e) {
System.out.println(text);
}
}
The try-catch is in case your String is too short.
A "hack" sort of an example, if you need a really short version :-)
int len = text.charAt(0)-0x30;
if( len > 0 && len < 10 ) {
System.out.printf("The decoded string is: %s, and starts with a %d!\n",
s.substring(0, len), len);
}
String sourceText = "4 test";
// Validate input first
if (sourceText == null || sourceText.isEmpty() || !Character.isDigit(sourceText.charAt(0))) {
System.out.println("The string must start with a digit.");
return;
}
// Use getNumericValue instead of Integer.parseInt
int count = Character.getNumericValue(sourceText.charAt(0));
String resultText = count < sourceText.length() ? sourceText.substring(0, count) : sourceText;
// Use String.format
System.out.println(String.format("The decoded string is \"%s\" and starts with a %d!", resultText, count));