Save multiple strings into one string - java

I want to save multiple strings in one. Thing is, I don't know how many strings it may be.
I'm creating a program that reads calories from a text file and stores them in corresponding arrays.
Here are parts of the text:
Description of food Fat Food Energy Carbohydrate Protein Cholesterol Weight Saturated Fat
(Grams) (calories) (Grams) (Grams) (Milligrams) (Grams) (Grams)
APPLES, RAW, PEELED, SLICED 1 CUP 0 65 16 0 0 110 0.1
APPLES, RAW, UNPEELED,2 PER LB1 APPLE 1 125 32 0 0 212 0.1
APPLES, RAW, UNPEELED,3 PER LB1 APPLE 0 80 21 0 0 138 0.1
APRICOT NECTAR, NO ADDED VIT C1 CUP 0 140 36 1 0 251 0
Now for the food name, I have an array foodName. I will read the whole string until I reach an int which is the amount.
Here is what I've done so far:
Scanner input = new Scanner("Calories.txt");
while (input.hasNext()) {
String[] words = input.next().split(" ");
int lastI;
for (int i=0; i < words.length; i++) {
if (isNumeric(words[i])) {
lastI = i;
for(int j=lastI; j>=0; j++){
//What should I put here?
}
}
}
}
public static boolean isNumeric(String str) {
try {
double d = Double.parseDouble(str);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
for the inner most for loop, I kept track of the last index so I could start from it and go backwards.
Problem 1: If I go backwards in the second line, I will copy both lines.
Problem 2: How to save all the strings of the name in one index of foodName?
All help is appreciated :)

What you are looking for in Java is called a StringBuilder. You can use this essentially like a string and keep appending onto it.
File file = new File("output.txt");
Scanner input = new Scanner(file);
StringBuilder sb = new StringBuilder();
while (input.hasNextLine()) {
String[] words = input.nextLine().split(" ");
for (int i = 0; i < words.length; i++) {
if (isNumeric(words[i])) {
break;
}
sb.append(words[i] + " ");
}
System.out.println(sb);
sb = new StringBuilder();
}
input.close();
What this does is read the file line by line, creating an array of strings splitting the line on " ". Then, it iterates over each of the strings in the array and checks if it is a number, if it is, it will break the current loop and move onto the next line.
I had the StringBuilder print after each line, and then reset, you should replace this with whatever functionality that you want.
A couples suggestions also for you:
Use a CSV file. Separate everything with commas instead of spaces, it makes parsing extremely easy.
Use regex to check if the string is a number instead of catching exceptions, it is more elegant.
The output of this comes out a little funny because of how you formatted your file. You are parsing on " ", but you added a bunch of extra " " characters in the file to make the format look nice. This messes up your parsing very badly. BUT, this method will parse for you correctly when you fix the format of your flat file.
Output from this was: (note that each line is a separate string. You can see how the file formatting messed up the output)
Description of food Fat Food Energy Carbohydrate Protein Cholesterol Weight Saturated Fat
(Grams) (calories) (Grams) (Grams) (Milligrams) (Grams) (Grams)
APPLES, RAW, PEELED, SLICED
APPLES, RAW, UNPEELED,2 PER LB1 APPLE
APPLES, RAW, UNPEELED,3 PER LB1 APPLE
APRICOT NECTAR, NO ADDED VIT C1 CUP

Related

Why do I get NumberFormatException while converting String Array to int Array?

I do not get the Error when I run my code on IntelliJ. However, when I try to hand in my Code for the assignement Im working on, I get NFE for both test cases. I deleted all of my Code and let only the bellow code run through the test cases. Somewhere in here must be a NumberFormatException.
public class Search {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.nextLine();
int[] list = new int[n];
String [] tokens = sc.nextLine().trim().split(" ");
for (int i=0; i<tokens.length;i++){
list[i]=Integer.parseInt(tokens[i]);
}
}
}
I read about double spaces and checked this with: System.out.println(Arrays.asList(tokens).contains(""));
Output was false so this is not an option. As you can see I'm already using trim().
I'd appreciate your help.
Louis
Eddit:
Alright something is fishy here. I added
System.out.println(Arrays.asList(tokens).contains(""));
System.out.println(Arrays.toString(tokens));
To my Code and handed it in to the test cases. While IntelliJ would deliver false followed by an array of integers, the test case outputs:
true
[]
.
Therefore you all are right and I just falsely assumed that the input in my test cases would be similar to the example Input I was given in the assignment.
Edit2:
ALRIGHT!
I figured it out. The Input of the test cases was simply not the same format as the one in my test Input which looked a bit like this:
10
8 8 9 12 110 111 117 186 298 321
2
8 13
I assume that the sc.nextLine() that I included skipped integers that I needed to make my list.
So the actual problem was not that extra spaces or anything, it was simply that I advanced past the input I wanted through my usage of sc.nextLine().
The answer that gave me the hint I needed, even tho I dont think this was intended came from Andronicus.
Thanks to everybody else anyways.
If you know, that there is going to be an integer as an input and you're not worried about parsing, why not using this instead?
int input = sc.nextInt();
In your solution you would have to do:
Arrays.stream(sc.nextLine().trim().split(" ")).filter(s -> !s.matches("\\s")).toArray(String[]::new);
\\ or simplier
sc.nextLine().trim().split("\\s+")
There's a number of possible causes:
There's a non-number in tokens -- eg. 9 1! 3 x 3 ...
The tokens are split by more than one space -- eg 9 3
You should be able to tell by the text of the Number Format Exception. For example, in the case of multiple spaces, you'd get:
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
And for non-numbers (eg "a"), you'd get:
Exception in thread "main" java.lang.NumberFormatException: For input string: "a"
There are, of course, numerous possible solutions depending on what you want to do when you run into invalid input (do you ignore it? throw a special exception? try to strip out non-numbers?)
When you know your inputs are separated by whitespace, but don't know how much white-space, you can use a regular expression to target multiple whitespaces in your split command:
str.split("\\s+"); // splits on one or more whitespace including tabs, newlines, etc.
Then, to handle non-digits in your token list, you can add a check in your for-loop:
for(int i = 0; i < tokens.length; i++) {
if(tokens[i].matches("\\d+")) {
list[i] = Integer.parseInt(tokens[i]);
} else {
// Handle error case for non-digit input
}
}
It is likely due to the extra bunch of spaces between the numbers.
For Example,
9 8 7 9 1
^^ ^^
*Note: You have more than one spaces here.
This is how your array will look after splitting,
tokens = {"9", "", "", "", "8", "7", "9", "", "", "", "1"}
Above will throw the NumberFormatException because of extra spaces.
You can try trimming the contents again,
int i = 0;
for (String token : tokens){
token = token.trim();
if (!"".equals(token)) {
list[i++] = Integer.parseInt(token);
}
}
Please modify your code to this :
public class Example {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the size of the array : ");
int n = sc.nextInt();
sc.nextLine();
int[] list = new int[n];
System.out.println("Enter a string : ");
/** This regex will work for string having more than one space. */
String trimmedToken = sc.nextLine().replaceAll("\\s+", " ");
String[] tokens = trimmedToken.split(" ");
for (int i = 0; i < tokens.length; i++) {
list[i] = Integer.parseInt(tokens[i]);
System.out.println(list[i]);
}
sc.close();
}
}
Console Input :
Enter the size of the array :
5
Enter a string :
1 2 3 4 5
Output :
1
2
3
4
5

What does String[ ]s = t.split(" ") mean/do?

Im working on programming for class, and we are looking at the sample code provided that takes the daily earnings for 4 weeks and prints out the day with the highest earnings. The program uses a dat file to read in the information and print the results. What I would like to understand is what exactly does String[ ]s = t.split(" ") do? It doesn't seem to be an array..
Data File
4
1300 1500 1200 1600 1800 900 1400
1200 1400 1500 1600 1100 1450 1475
1745 2534 2000 2100 2400 1975 1823
2231 1992 2000 2345 2435 1982 2500
The first number in the data file lists the number of lines (Weeks) to follow. Each line after that contains 7 numbers each correlating to a day of the week Sunday - Saturday.
Main Code from practice set. I added comments for each line, to fully explain my problem.
The line I dont understand is String []s = t.split(" ");
import java.io.*;
import java.util.*;
import static java.lang.System.*;
public class BestDay {
public static void main(String args[]) throws IOException
{
Scanner kb = new Scanner(new File("bestday.dat")); //Imports File
int count = 0; //Basic Counter for While loop
int totalWeeks = Integer.parseInt(kb.nextLine().trim()); //Number of Weeks from First Line of Data File (4)
while(count < totalWeeks) { //Runs While loop as long as times is greater than count
count++; //Increments Count
String t = kb.nextLine().trim(); // pulls in the next line as a string and trims blank spaces
String []s = t.split(" "); //Not Sure what is happening here) Someone Explain pls.
int most = Integer.parseInt(s[0]); //Takes each number and registers it as Int
int day = 0; //Sets an int for later comparison
for(int i=1; i<7; i++) { //for loop runs 7 times one for each day of the week for every 1 while loop run
int next = Integer.parseInt(s[i]); //brings in each other integer.
if (next > most) {// compares it
most=next; //If next is more than most then sets most to next
day=i; //sets day to i basically telling which day was the highest value on
}
}
switch (day) {
case 0: out.println("SUNDAY"); break; //looks at each case with Day and prints out the right case.
case 1: out.println("MONDAY"); break;
case 2: out.println("TUESDAY"); break;
case 3: out.println("WEDNESDAY"); break;
case 4: out.println("THURSDAY"); break;
case 5: out.println("FRIDAY"); break;
case 6: out.println("SATURDAY"); break;
}
}
}
}
Expected Output
THURSDAY
WEDNESDAY
MONDAY
SATURDAY
From the Javadocs for String.split(String):
Splits this string around matches of the given regular expression.
Essentially, it tokenizes the target string into separate strings which were joined by the argument regular expression.
For example:
"foo bar gah".split(" "); // => { "foo", "bar", "gah" }
"Mississipian".split("i"); // => { "M", "ss", "ss", "pp", "an" }
See the documentation for String.split: it splits a string using a regular expression. Specifically (as per the docs):
Splits this string around matches of the given regular expression.
This method works as if by invoking the two-argument split method with the given expression and a limit argument of zero. Trailing empty strings are therefore not included in the resulting array.
In this case it simply splits a line from your file (such as 1300 1500 1200 1600 1800 900 1400) on the specified pattern (in this case a " ") and returns an array of the individual strings. e.g.
{"1300", "1500", "1200", "1600", "1800", "900", "1400"}
Your first port of call for any "what does this java function do" question should be the java documentation at http://docs.oracle.com/javase/7/docs/api/overview-summary.html
String.split splits the given string using a delimiter and stores it in an array. In your case, its space. So using it on the 2nd line would provide you this array s[] = { 1300, 1500, 1200, 1600, 1800, 900, 1400 }
From javadoc
String.split(String regex)
Splits this string around matches of the given regular expression.
(Next time read the docs)
Take a look at official java documentation here.
Small snipped:
String[] parts = "123 156";
String[] parts = string.split(" ");
parts will be an array of 2 elements containing "123" and "456" string respectively. The argument passed as input is used by split method to match the given regular expression (in my example a simple token string).

Verifying unexpected empty lines in a file

Aside: I am using the penn.txt file for the problem. The link here is to my Dropbox but it is also available in other places such as here. However, I've not checked whether they are exactly the same.
Problem statement: I would like to do some word processing on each line of the penn.txt file which contains some words and syntactic categories. The details are not relevant.
Actual "problem" faced: I suspect that the file has some consecutive blank lines (which should ideally not be present), which I think the code verifies but I have not verified it by eye, because the number of lines is somewhat large (~1,300,000). So I would like my Java code and conclusions checked for correctness.
I've used slightly modified version of the code for converting file to String and counting number of lines in a string. I'm not sure about efficiency of splitting but it works well enough for this case.
File file = new File("final_project/penn.txt"); //location
System.out.println(file.exists());
//converting file to String
byte[] encoded = null;
try {
encoded = Files.readAllBytes(Paths.get("final_project/penn.txt"));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String mystr = new String(encoded, StandardCharsets.UTF_8);
//splitting and checking "consecutiveness" of \n
for(int j=1; ; j++){
String split = new String();
for(int i=0; i<j; i++){
split = split + "\n";
}
if(mystr.split(split).length==1) break;
System.out.print("("+mystr.split(split).length + "," + j + ") ");
}
//counting using Scanner
int count=0;
try {
Scanner reader = new Scanner(new FileInputStream(file));
while(reader.hasNext()){
count++;
String entry = reader.next();
//some word processing here
}
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println(count);
The number of lines in Gedit--if I understand correctly--matched the number of \n characters found at 1,283,169. I have verified (separately) that the number of \r and \r\n (combined) characters is 0 using the same splitting idea. The total splitting output is shown below:
(1283169,1) (176,2) (18,3) (13,4) (11,5) (9,6) (8,7) (7,8) (6,9) (6,10) (5,11) (5,12) (4,13) (4,14) (4,15) (4,16) (3,17) (3,18) (3,19) (3,20) (3,21) (3,22) (3,23) (3,24) (3,25) (2,26) (2,27) (2,28) (2,29) (2,30) (2,31) (2,32) (2,33) (2,34) (2,35) (2,36) (2,37) (2,38) (2,39) (2,40) (2,41) (2,42) (2,43) (2,44) (2,45) (2,46) (2,47) (2,48) (2,49) (2,50)
Please answer whether the following statements are correct or not:
From this, what I understand is that there is one instance of 50 consecutive \n characters and because of that there are exactly two instances of 25 consecutive \n characters and so on.
The last count (using Scanner) reading gives 1,282,969 which is an exact difference of 200. In my opinion, what this means is that there are exactly 200 (or 199?) empty lines floating about somewhere in the file.
Is there any way to separately verify this "discrepancy" of 200? (something like a set-theoretic counting of intersections maybe)
A partial answer to question (the last part) is as follows:
(Assuming the two statements in the question are true)
If instead of printing number of split parts, if you print no. of occurrences of \n j times, you'll get (simply doing a -1):
(1283168,1) (175,2) (17,3) (12,4) (10,5) (8,6) (7,7) (6,8) (5,9) (5,10) (4,11) (4,12) (3,13) (3,14) (3,15) (3,16) (2,17) (2,18) (2,19) (2,20) (2,21) (2,22) (2,23) (2,24) (2,25) (1,26) (1,27) (1,28) (1,29) (1,30) (1,31) (1,32) (1,33) (1,34) (1,35) (1,36) (1,37) (1,38) (1,39) (1,40) (1,41) (1,42) (1,43) (1,44) (1,45) (1,46) (1,47) (1,48) (1,49) (1,50)
Note that for j>3, product of both numbers is <=50, which is your maximum. What this means is that there is a place with 50 consecutive \n characters and all the hits you are getting from 4 to 49 are actually part of the same.
However for 3, the maximum multiple of 3 less than 50 is 48 which gives 16 while you have 17 occurrences here. So there is an extra \n\n\n somewhere with non-\n character on both its 'sides'.
Now for 2 (\n\n), we can subtract 25 (coming from the 50 \ns) and 1 (coming from the separate \n\n\n) to obtain 175-26 = 149.
Counting for the discrepancy, we should sum (2-1)*149 + (3-1)*1 + (50-1)*1, the -1 coming because first \n in each of these is accounted for in the Scanner counting. This sum is 200.

Printing and matching values in java

I have a program that will read a text file starting on line number 29. If the line contains the words "n.a" or "Total" the program will skip those lines.
The program will get the elements [2] and [6] from the array.
I need to get element [6] of the array and print it underneath its corresponding value.
Element[2] of the array is where all the analytes are and element[6] contains the amount of each analyte.
The files that the program will read look like this:
12 9-62-1
Sample Name: 9-62-1 Injection Volume: 25.0
Vial Number: 37 Channel: ECD_1
Sample Type: unknown Wavelength: n.a.
Control Program: Anions Run Bandwidth: n.a.
Quantif. Method: Anions Method Dilution Factor: 1.0000
Recording Time: 10/2/2013 19:55 Sample Weight: 1.0000
Run Time (min): 14.00 Sample Amount: 1.0000
No. Ret.Time Peak Name Height Area Rel.Area Amount Type
min µS µS*min % mG/L
1 2.99 Fluoride 7.341 1.989 0.87 10.458 BMB
2 3.88 Chloride 425.633 108.551 47.72 671.120 BMb
3 4.54 Nitrite 397.537 115.237 50.66 403.430 bMB
4 5.39 n.a. 0.470 0.140 0.06 n.a. BMB
5 11.22 Sulfate 4.232 1.564 0.69 13.064 BMB
Total: 835.213 227.482 100.00 1098.073
The program needs to read that type of files and stores the element[6] of the array under a heading in a separate file in a folder. That file will have a heading like this:
Fluoride,Chloride,Nitrite,Sulfate,
The amount of fluoride should go under fluoride, the amount of chloride should go under chloride and so on and if there isn`t Nitrite or any other analyte it should put a zero for each analyte.
I just need to know how to match that and then I know I have to make write to the file which I will do later, but for know I need help matching.
The final output should looe like this.
The first line will be written in the textfile and then the second line will be values that will be match under its corresponding analyte like this:
Sample#,Date,Time,Fluoride,Chloride,Nitrite,Sulfate,9-62-1,10/2/2013,19:55,10.458,671.120,403.430,13.064,
Also again if an analyte isnt present on the file or it is null it should put a 0.
Here is my code:
//Get the sample#, Date and time.
String line2;
while ((line2 = br2.readLine()) != null) {
if (--linesToSkip2 > 0) {
continue;
}
if (line2.isEmpty() || line2.trim().equals("") || line2.trim().equals("\n")) {
continue;
}
if (line2.contains("n.a.")) {
continue;
}
if (line2.contains("Total")) {
continue;
}
String[] values2 = line2.split("\t");
String v = values2[2];//Stored element 2 in a string.
String v2 = values2[6];//Stored element 6 in a string.
String analytes = "Fluoride,Chloride,Nitrite,Sulfate";//Stored the analytes into an array.
if (analytes.contains(v)) {
System.out.println(v2);
}
int index2 = 0;
for (String value2 : values2) {
/*System.out.println("values[" + index + "] = " + value);*/
index2++;
}
System.out.print(values2[6] + "\b,");
/*System.out.println(values[6]+"\b,");*/
br.close();
}
Thanks in advance!
So if i understand your task right and every element is in new line.
Where is a lot of ways how to solve this, but with your code simpliest way to solve it in my opinion would be with StringBuffer.
//In your code i saw you have to arrays one of them with element name
//other with element code or smth
StringBuffer firstLine = new StringBuffer();
StringBuffer secondLine = new StringBuffer();
public static void printResult(String[] Name, String[] Code){
//First we gona make first line
//Here we are adding data before Names
firstLine.append("Stuff before Names");
for(int i =0;i<name.length;i++){
//Here we gona add all names in the list which is good
//Dont forget spaces
firstLine.append(name[i]+ " ");
}
//And same goes for second line just change loop array and data added before loop.
//And in the end this should print out your result
System.out.println(firstLine+"\n" + secondLine);
}
Call this method after all file reading is done.
Hope it helps!

Sorting info from a txt file into two different arrays

For a uni assignment, I have to take input from a text file and sort it into two separate arrays. The text file is a football league table, arranged as such:
Barcelona 34
Real Madrid 32
I have written a piece of code like this:
holdingString = fileInput.readLine ();
StringTokenizer sort = new StringTokenizer (holdingString + " ");
countOfTokens = sort.countTokens();
System.out.println (countOfTokens + " tokens: " + holdingString);
This prints out the number of tokens and what the tokens are for each line, so it gives output of
Two tokens: Barcelona 34
Three tokens: Real Madrid 32
I've then written this piece of code:
for (int i = 0; i < countOfTokens; i++)
{
String temp = sort.nextToken ();
System.out.println(temp);
}
This reads just the next token and prints it out.
However, rather than printing the next token out, I want to check if it is a word or a number, and separate it into a different array accordingly, so it will be like this:
ArrayTeam Zero Element Barcelona
ArrayTeam First Element Real Madrid
ArrayPoints Zero Element 34
ArrayPoints First Element 32
What's the easiest way to do this? I've tried using a try/catch, but didn't get it right. I've also tried using an if statement with \d, but that's not worked either.
Like AmitD, I agree that using split is more appropriate in this case, but if you still like to use a StringTokenizer you do something like:
StringBuilder teamName=new StringBuilder();
for (int i = 0; i < countOfTokens-1; i++)
{
if (i>0) teamName.append(' ');
teamName.append(sort.nextToken());
}
teamNames[k]=teamName.toString(); //add the new team to your teamNames array
points[k]=Integer.parseInt(sort.nextToken()); //if your points array is of int type
you could use java.util.Scanner class to read data from the file. it has methods such as nextInt(), nextDouble ...whhich might be useful in your case.
Scanner scan = new Scanner(file);
int number;
if(scan.hasNextInt()){
number = scan.nextInt();
}
check Scanner API
String readLine = "Real Madrib 40";
String[] team = readLine.split( "\\d" );
System.out.println(team[0]);
String score = readLine.replace( team[0],"" );
System.out.println(score);
Output :
team[0] : Real Madrib
score : 40
You can save all that trouble using split
String strs[] = holdingString.split("\\s");
E.g.
"Barcelona 34".split("\\s"); will return you Array of Strings where
array[0]=Barcelona array[1]=34
From Javadoc of StringTokenizer
StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the split method of String or the java.util.regex package instead.
Update
As #madhairsilence pointed out
You need another deliminator. You can use = like property files
"Real Madrid =34".split("=");//will return you Array of Strings where
array[0]=Real Madrid, array[1]=34
You can use Scanner as you are reading from file.

Categories

Resources