I am trying to get a class to read my txt file with a few lines, for example:
Facial Lotion, 1 , 2, 0.1
Moisturiser Lotion, 2, 3, 0.2
Toner Lotion, 3, 4, 0.3
Aloe Vera Lotion, 4, 5, 0.4
I created a class call Lotion with attributes name(string), productNo(int), productRating(int), and productDiscount(double, and I create another class call ListOfLotion and add in an arraylist of Lotion.
my problem is how do i get my ListOfLotion class to use the values in txt file and put it in my arraylist.
I tried to use indexOf for name till the next one but i got error,
java.lang.StringIndexOutOfBoundsException: begin 0, end -1, length 17
also is there anyway i could separate all four value and make sure they are store properly for example, Facial Lotion is store as the name and 1 is store as prodcuctNo.
public void addListOfLotion(){
ArrayList<Lotion> lotion = new ArrayList<Lotion>();
Scanner scanner = new Scanner("Desktop/Lotion.txt");
while(scanner.hasNext()){
String readLine = scanner.nextLine();
int indexProductNo = readLine.indexOf(',');
int indexOfProductRating = readLine.indexOf(',');
double indexOfProductDiscount = readLine.indexOf(',');
lotion.add(new Lotion(readLine.substring(0, indexOfProductNo),0,0,0));
}scanner.close();
}
Got this error as result:
java.lang.StringIndexOutOfBoundsException: begin 0, end -1, length 17
at java.base/java.lang.String.checkBoundsBeginEnd(String.java:3319)
at java.base/java.lang.String.substring(String.java:1874)
at ListOfVenues.addListOfLotion(ListOfLotion.java:42)
Is it beccause I put readLine,indexOf(',') as every readLine, it just stop at the first ','? Anyway I could effectively let java know that between this and this index is for name, and between this and this index is for productNo?
thanks guys really appreciate it.
Since the lines are comma-separated lists you could use split() to split the line into the single variables.
Another thing to consider is that Scanner("file.txt") doesn't read the indicated text file but just the given String. You have to create a File object first.
File input = new File("Desktop/Lotion.txt");
Scanner scanner;
scanner = new Scanner(input);
while(scanner.hasNext()){
String readLine = scanner.nextLine();
String[] strArray = readLine.split(",");
int indexOfProductNo = Integer.parseInt(strArray[1].trim());
int indexOfProductRating = Integer.parseInt(strArray[2].trim());
double indexOfProductDiscount = Double.parseDouble(strArray[3].trim());
lotion.add(new Lotion(strArray[0],indexOfProductNo,indexOfProductRating,indexOfProductDiscount));
}
You could use a regex (Demo):
([\w\s]+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+(?:\.\d+))
Which you could define as a constant in your class:
private static final Pattern LOTION_ENTRY =
Pattern.compile("([\\w\\s]+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+(?:\\.\\d+))");
Then you can just create a Matcher for every entry and extract the groups:
Matcher matcher = LOTION_ENTRY.matcher(readLine);
if(matcher.matches()) {
String name = matcher.group(1);
int no = Integer.parseInt(matcher.group(2));
int rating = Integer.parseInt(matcher.group(3));
double discount = Double.parseDouble(matcher.group(4));
// do something
} else {
// line doesn't match pattern, throw error or log
}
A note though: the parseInt() and parseDouble can throw a NumberFormatException if the input is not valid. So you'd have to catch those and act accordingly.
Related
im trying to compare a String, which is a part of read file(the file:
Example of read file
1.Dog
2.Cat
3.Bird
4), to a given input by a user, using .equals.
It always returns false, even when i copypaste the printed String.
The code:
File TF = new File("Textfile.txt");Scanner read = new Scanner(TF);
String text="";
while(read.hasNextLine()) {
text = text.concat(read.nextLine()+"\n");
}
int x;
int y;
char a;
char b;
Random dice = new Random();
x=dice.nextInt(3)+1;
y=x+1;
a=(char)(x+48);
b=(char)(y+48);
int first = text.indexOf(a);
int second = text.indexOf(b);
String some=text.substring(first,second);
Scanner write = new Scanner(System.in);
String writein=write.nextLine();
System.out.println(writein.equals(some))
text.substring(first,second) returns a string which contains a trailing line break, e.g. "1.Dog\n", while the string entered will not. To fix it, you could trim the line read from the file:
String some=text.substring(first,second).trim();
The variable some ends with \n (or possibly \r\n on Windows). writein on the other has no trailing newline. When comparing strings, every character has to be equal (which is not the case).
You have multiple possible solutions to solve your problem. One of which is to call stripTrailing() on your string (Java >= 11).
System.out.println(writein.equals(some.stripTrailing()))
Or you could manually reduce the length of the string
String some=text.substring(first, second - 1);
I am working on a project which involves making a "worker" in java which receives instructions from an input string. In the input string normally should be first four numbers and then afterwards a number and a letter right after being N,S,W, or E. The first 2 numbers in the list are used to determine the size of the area this worker can walk. the next two numbers are the starting point for the worker. The number with the letter determines what direction the worker walks and how many paces. The problem I am having is I don't understand how to get the first four digits out of the string and separate them into what they each should be.
import java.util.*;
import java.io.*;
public class Worker {
private int height;
public void readInstructions(String inputFileName, String outputFileName) throws InvalidWorkerInstructionException{
try{
Scanner in = new Scanner(inputFileName);
PrintWriter wrt;
wrt = new PrintWriter(outputFileName);
if(inputFileName.startsWith("i")){
System.out.println("Input file not found.");
//wrt.println("Input file not found.");
}
while(in.hasNext()){
String s = in.nextLine();
if(Integer.parseInt(s)<= 9){
}
}
}catch(InvalidWorkerInstructionException e){
}catch(FileNotFoundException e){
}
While I would love to ask for a straight up answer, this is a project so I would prefer nobody gives me a fixed code. Please if you can give me advice for what I am doing wrong and where I should be going to solve the problem.
Ok I realized one other thing because I tried the advice given. So I am receiving a string that gives me the name of an input txt. Inside that input txt is the numbers and directions. How can i access this text file? Also how do I determine if it can be opened?
Okay, so you already know how to read the file using a Scanner. All you need to do next is split the String and extract the first four inputs out of it.
Here is the code snippet:
String s = in.nextLine();
int i = 0, digits[] = new int[4];
for(String inp : s.splits(" ")) {
if(i == 4) break;
digits[i++] = Integer.parseInt(inp);
}
Note: I'm assuming that the inputs in your file is space separated. If not then you can replace the space in the split() with the correct delimiter.
If input format is fixed than you can use substring method to get different parts of string. Refer documentation for more detail:
https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#substring(int,%20int)
Example code:
String s = "12345E";
s.substring(0, 2); /* 12 */
s.substring(2, 4); /* 34 */
s.substring(4, 5); /* 5 */
s.substring(5, 6); /* E */
You can use the method .getChars() to accomplish this. Here is what the javadoc says about this method:
public void getChars(int srcBegin,
int srcEnd,
char[] dst,
int dstBegin)
Copies characters from this string into the destination character array.
The first character to be copied is at index srcBegin; the last character to be copied is at index srcEnd-1 (thus the total number of characters to be copied is srcEnd-srcBegin). The characters are copied into the subarray of dst starting at index dstBegin and ending at index:
dstbegin + (srcEnd-srcBegin) - 1
Parameters:
srcBegin - index of the first character in the string to copy.
srcEnd - index after the last character in the string to copy.
dst - the destination array.
dstBegin - the start offset in the destination array.
Throws:
IndexOutOfBoundsException - If any of the following is true:
srcBegin is negative.
srcBegin is greater than srcEnd
srcEnd is greater than the length of this string
dstBegin is negative
dstBegin+(srcEnd-srcBegin) is larger than dst.lengt....
Here is what you could do...
You read in the string - grab its length (You want to make sure that it has all the chars you need)
Read in to a separate array discarding any extraneous chars that are not needed for this functionality..
You can make your own pseudo code to work out the problem once the string is split into an array. Very easy to work with since you know what each location of the array is supposed to do.
This is not a hard problem to solve at all..
Good luck on your project.
So I'm trying to validate data in a text file using Java. The text file looks like this (ignore the bullet points):
51673 0 98.85
19438 5 95.00
00483 3 73.16
P1905 1 85.61
80463 2 73.16
76049 4 63.48
34086 7 90.23
13157 0 54.34
24937 2 81.03
26511 1 74.16
20034 4 103.90
The first column of numbers needs to be within the range of 00000-99999 and with not letters, the second column needs to be within the range of 0-5, and the third column needs to be within the range of 0.00-100.00. So how I would be able to validate each of these columns in the text file separately to meet the requirements? I already know how to read the text file, I'm just trying to figure out how to validate the data.
So you have a line, String line = "20034 4 103.90";.
You can break it into its consituent parts using .split().
Then inspect/validate each of them individually before repeating the same for the next line.
So, it would be splitting by the delimiter " ", since it separates the columns.
String[] parts = line.split(" ");
String part1 = parts[0]; // 20034
String part2 = parts[1]; // 4
String part3 = parts[2]; // 203.90
You can play around here http://ideone.com/LcNYQ9
Validation
Regarding validation, it's quite easy.
For column 1, you can do something like if (i > 0 && i < 100000)
Same for column 2, if (i > 0 && i < 6)
To check if the column 1 doesn't contain any letters, you can use this:
part1.contains("[a-zA-Z]+") == false inside an if statement.
Instead of checking if it doesn't have letters, check that it only contains digits or decimal points. I've provided the appropriate regular expressions for doing the same.
Step 1: Put each line in the file into a List<String>:
List<String> list = Files.readAllLines(Paths.get("filepath"));
Step 2: Split each line into its components and validate them individually:
for(String str : list)
{
String[] arr = list.split(" ");
if(arr[0].matches("\\d+")) // Check to see if it only contains digits
int part1 = Integer.valueOf(arr[0]);
else
//throw appropriate exception
validate(part1, minAcceptedValue, maxAcceptedValue);
if(arr[1].matches("\\d+")) // Check to see if it only contains digits
int part2 = Integer.valueOf(arr[1]);
else
//throw appropriate exception
validate(part2, minAcceptedValue, maxAcceptedValue);
if(arr[2].matches("[0-9]{1,4}(\\.[0-9]*)?")) // Check to see if it is a Double that has maximum 4 digits before decimal point. You can change this to any value you like.
int part2 = Integer.valueOf(arr[2]);
else
//throw appropriate exception
validate(part3, minAcceptedValue, maxAcceptedValue);
}
void validate(int x, int min, int max)
{
if(x < min || x > max)
//throw appropriate exception
}
You can use Scanner (javadocs) to help you parse the input. It's similar to the regular expressions solution but it's tailored for these situations where you read a series of values from a potentially enormous text file.
try (Scanner sc = new Scanner(new File(...))) {
while (sc.hasNext()) {
int first = sc.nextInt();
int second = sc.nextInt();
float third = sc.nextFloat();
String tail = sc.nextLine();
// validate ranges
// validate tail is empty
}
}
Off course you may catch any potential exceptions and consider them as validation failures.
I have 3 String fields per line within my text file. There are 4 lines in total. The first 2 fields (field[0] and field[1]) are already filled in but field 3 (field[2]) is yet to be generated so it shall remain empty. Is there any way I can read in this text file line by line without getting a java.lang.ArrayIndexOutOfBoundsException: 1 error? I have included my code used for reading in the file.
import java.io.*;
public class PassGen {
public static void main(String args[]) throws Exception{
BufferedReader inKb = new BufferedReader(new InputStreamReader(System.in));
BufferedReader inF = new BufferedReader(new FileReader(new File("students.txt")));
String line = inF.readLine();
int cnt = 0;
Student pupil[] = new Student[6];
while(line != null) {
String field[] = line.split("//s");
pupil[cnt] = new Student(field[0], field[1], field[2]);
cnt++;
inF.readLine();
}
}
}
You can simply add a check on the number of fields:
if(field.length > 2) {
pupil[cnt] = new Student(field[0], field[1], field[2]);
} else {
pupil[cnt] = new Student(field[0], field[1], null);
}
Alternatively, you can use the overloaded split method that takes a limit parameter and set that to -1 to include the empty field. From the documentation of String#split(String regex, int limit):
The limit parameter controls the number of times the pattern is applied and therefore affects the length of the resulting array. If the limit n is greater than zero then the pattern will be applied at most n - 1 times, the array's length will be no greater than n, and the array's last entry will contain all input beyond the last matched delimiter. If n is non-positive then the pattern will be applied as many times as possible and the array can have any length. If n is zero then the pattern will be applied as many times as possible, the array can have any length, and trailing empty strings will be discarded.
Note that you need to use \\s instead of //s for the whitespace regex (this needs to be corrected either way).
String field[] = line.split("\\s", -1);
I think you problem lies in the way you are managing your data, but you can have something like this to read from any array and not getting any exceptions:
public static String getIfExists(final String[] values, final int position) {
return (values != null) && (values.length > position) ? values[position] : null;
}
Then you can fill every field like new Student(getIfExists(field, 0), getIfExists(field, 1), getIfExists(field, 2));
Of course you can optimize this a little bit more...but that would make the trick without having to think on how many fields you might get in the future or having a lot of if/case conditions.
I'm trying to parse a String from a file that looks something like this:
Mark Henry, Tiger Woods, James the Golfer, Bob,
3, 4, 5, 1,
1, 2, 3, 5,
6, 2, 1, 4,
For ease of use, I'd like to split off the first line of the String, because it will be the only one that cannot be converted into integer values (the rest will be stored in a double array of integers[line][value]);
I tried to use String.split("\\\n") to divide out each line into its own String, which works. However, I am unable to divide the new strings into substrings with String.split("\\,"). I am not sure what is going on:
String[] firstsplit = fileOne.split("\\\n");
System.out.println("file split into " + firstsplit.length + " parts");
for (int i = 0; i < firstsplit.length; i++){
System.out.println(firstsplit[i]); // prints values to verify it works
}
String firstLine = firstsplit[0];
String[] secondSplit = firstLine.split("\\,");
System.out.println(secondSplit[0]); // prints nothing for some reason
I've tried a variety of different things with this, and nothing seems to work (copying over to a new String is an attempt to get it to work even). Any suggestions?
EDIT: I have changed it to String.split(",") and also tried String.split(", ") but I still get nothing to print afterwards.
It occurs to me now that maybe the first location is a blank one....after testing I found this to be true and everything works for firstsplit[1];
You're trying to split \\,, which translates to the actual value \,. You want to escape only ,.
Comma , doesn't need \ before it as it isn't a special character. Try using , instead of \\,, which is translated to \, (not only a comma, also a backslash).
Not only do you not need to escape a comma, but you also don't need three backslashes for the newline character:
String[] firstSplit = fileOne.split("\n");
That will work just fine. I tested your code with the string you specified, and it actually worked just fine, and it also worked just fine splitting without the extraneous escapes...
Have you actually tested it with the String data you provided in the question, or perhaps is the actual data something else. I was worried about the carriage return (\r\n in e.g. Windows files), but that didn't matter in my test, either. If you can scrub the String data you're actually parsing, and provide a sample output of the original String (fileOne), that would help significantly.
You could just load the file into a list of lines:
fin = new FileInputStream(filename);
bin = new BufferedReader(new InputStreamReader(fin));
String line = null;
List<String> lines = new ArrayList<>();
while (( line = bin.readLine()) != null ) {
lines.add( line );
}
fin.close();
Of course you have to include this stuff into some try catch block which fits into your exception handling. Then parse the lines starting with the second one like this:
for ( int i = 1; i < lines.size(); i++ ) {
String[] values = lines.get( i ).split( "," );
}