Data evaluation from text file - java

I need some help. I dont know how to solve my problem.
I have text file in this format:
personx 25
personz 2
persony 5
persony 7
personi 55
personx 25
I need to count the numbers for every person. The output should be "personx = 50" etc.
I can not use my old system where I knew there is 10 people. So I had 10 variables and I just went through the file with scanner and checked if line starts with "personx" then count the number to variable personx etc. I dont want to use these variables now. I dont want to change code after every new person.
How to solve this? I want to have this output sorted from highest to lowest:
personi = 55
personx = 50
persony = 12
personz = 2
Is that possible without using variables personi, personx, persony, personz ? My idea was to go through the file and scan the names. Save the name into an array and add another name into an array if that name is not in the array yet. So I will have the names.
Next I will scan the file again and check for the name and number. Check name + number and then save the number into another array on the same possition as the name in the first array. So I will have
Names[0] = "personi";
Count[0] = 55;
Names[1] = "personx";
Count[1] = 50;
And then I will just print these two arrays with for cycle.
I dont think that it is the best solution. How would you do it? Is there something better/faster/easier ? And how to solve that Sorting?
Thank you for your time.

You can us Map<String,Integer>
In this case i used TreeMap which will sort everything for you. If you dont need sorting then just use HashMap instead of TreeMap.
Map<String, Integer> map = new TreeMap();
try {
BufferedReader reader = new BufferedReader(new FileReader(new File("C:/iPhone/persons.txt")));
String line = "";
String [] person = new String[2];
while ((line = reader.readLine()) != null) {
person = line.split(" ");
String name = person[0];
int number = Integer.parseInt(person[1]);
map.put(name,map.getOrDefault(name,0)+number);
}
reader.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
map.forEach((k,v)->System.out.println(k + " = " + v));
}
persons.txt:
personx 25
personz 2
persony 5
persony 7
personi 55
personx 25
Output:
personi = 55
personx = 50
persony = 12
personz = 2
1) Can I use this on file where line is not in my format but it has for example.. this format ? "personx bla bla 25" ? Is it possible to convert it too? how?
Yes you can create method which will do it for you. You can use either string splits or some regex.
2) Why is there String [] person = new String[2]; ?
Mistake, it should be String[1]. Corrected now
3) what is String line = ""; ?
It is just new String where i'm storing every line that i read from file. As you can see, im assigning reder.readLine() in while loop. After that im just splitting it.
EDIT:
Changed code so person can have multiple params but will take only first as name and last as number.
public static void main(String[] args) {
Map<String, Integer> map = new TreeMap();
try {
BufferedReader reader = new BufferedReader(new FileReader(new File("C:/iPhone/persons.txt")));
String line = "";
String [] person;
while ((line = reader.readLine()) != null) {
person = line.split(" ");
String name = person[0];
int number = Integer.parseInt(person[person.length-1]);
map.put(name,map.getOrDefault(name,0)+number);
}
reader.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
map.forEach((k,v)->System.out.println(k + " = " + v));
}
persons.txt:
personx asdasdas dasd asd a 25
personz 2
persony asd asd asd a 5
persony 7
personi 55
personx 25
output:
personi = 55
personx = 50
persony = 12
personz = 2

Related

Java scanner delimiter causes my integer to not be read properly

So I'm creating a scanner to read off of a simple text file:
import java.io.*;
import java.util.Scanner;
public class Weather {
public static void main(String[] args) throws FileNotFoundException {
int a;
File weatherData = new File("C:\\Users\\taddi\\eclipse-workspace\\COS_160_ASSIGNMENT_10\\src\\PortlandWeather1941to2018.txt");
Scanner scnr = new Scanner(weatherData);
scnr.useDelimiter("//");
int totalCount = scnr.nextInt();// this reads the number at the beginning and uses it so I know how many times to run the loop
String throwAway1 = scnr.nextLine();//these statement are used to throw a way the rest of line 1, and all of line 2 and 3
String throwAway2 = scnr.nextLine();
String throwAway3 = scnr.nextLine();
int[] month = new int[totalCount];
int[] day = new int[totalCount];
int[] year = new int[totalCount];
int[] tmax = new int[totalCount];
int[] tmin = new int[totalCount];
for(a = 0; a < totalCount; a ++) {
month[a] = scnr.nextInt();
System.out.println(month[a]);
day[a] = scnr.nextInt();
System.out.println(day[a]);
year[a] = scnr.nextInt();
tmax[a] = scnr.nextInt();
tmin[a] = scnr.nextInt();
}
}
}
The first part of the text file is an integer I'm trying to read. For some reason, it only reads that integer when I comment out the scnr.useDelimiter("//"); line, otherwise I get an InputMismatchException
I'd love to just get rid of all the unnecessary words and slashes in the text file but that wouldn't satisfy the assignment. What's going wrong with the delimiter? How do I read the integer?
Your delimiter is a string, and it will not work in your use case the way you want.
I assume your sample data is like this (ignoring the header lines) ...
01/01/1941 38 25
01/02/1941 32 20
... so you are looking to get each number - the date elements and the tmax/tmin values - so a single delimiter character of '/' would only break up the date.
For example:
final String data =
"01/01/1941 38 25 \n"+
"01/02/1941 32 20 \n";
Scanner scnr = new Scanner(data);
scnr.useDelimiter("/");
while(scnr.hasNext()) {
System.out.println(scnr.next());
}
scnr.close();
outputs the following ...
01
01
1941 38 25
01
02
1941 32 20
showing that it splits on the date d/m/y slashes, but the year and tmax and tmin are bundled together.
Adjusting the scanner to use a Pattern delimiter allows us to split on the slashes and the spaces.
final String data =
"01/01/1941 38 25 \n"+
"01/02/1941 32 20 \n";
Scanner scnr = new Scanner(data);
scnr.useDelimiter(Pattern.compile("[/ ]+"));
while(scnr.hasNext()) {
System.out.println(scnr.next());
}
scnr.close();
}
giving the output I think you want:
01
01
1941
38
25
01
02
1941
32
20
However, note that in my example data I have trailing whitespace on each line and they are thus also returned as empty String tokens. If I was scanning for nextInt() I would get an java.util.InputMismatchException error. Depending on the exact formatting of your input you may need to cater for that.

java csv file opening and editing

i have some marks for some students in my tutoring class...and also i'm trying to learn how to open and edit csv files as they're not like normal .txt files in Java so i thought this is the perfect opportunity.
i have a Students.csv file in this format:
132567 Amelia
123476 Charlie
123516 Emily
143456 George
123466 Harry
123457 Jack
125456 Joshua
132456 Lily
123456 Oliver
123459 Sophie
123486 Thomas
123518 William
The numbers are their student numbers followed by the students name.
and in a seperate .csv file i have their marks for modules alongside their student numbers in this format:
123456 51.2 57.3 68.2 72.1
123457 60.4 51.3 70 55
123459 45 60.1 62.7 43.2
123466 37.9 44 67.2 48.5
123476 52.7 78.2 73.3 69.8
123486 45.9 61.2 55.4 41.7
123516 61.2 66.4 72.3 57.8
123518 83.2 78.2 66.1 61.7
125456 69.8 60.3 72.1 64
132456 73.1 82.6 71.2 79.5
132567 56.3 48.8 45.7 61.2
143456 41.9 66.2 55.4 63.2
For each of the four modules, i want to create a new file that has all the students results in it. The names of these module report files can be anything for example IR101.txt, ..., IR104.txt. as i can change them later anyway.
i want the end result to be something like this:
Module: IR102
Mean: 62.88
00 - 39.9: 0
40 - 49.9: 2
50 - 59.9: 2
60 - 69.9: 5
70 - 100.0: 3
123466, Harry: 44.0
132567, Amelia: 48.8
123457, Jack: 51.3
123456, Oliver: 57.3
123459, Sophie: 60.1
125456, Joshua: 60.3
123486, Thomas: 61.2
143456, George: 66.2
123516, Emily: 66.4
123476, Charlie: 78.2
123518, William: 78.2
132456, Lily: 82.6
dont worry about doing the calculations for mean as i can implement that myself.
here is what i have so far, and all this does is open and print the students.csv file but i still cant figure out how to access each value and manipulate it as it's very different to python
public class excelfile {
public static final String students_file = "students.csv";
public static final String marks_file = "marks.csv";
public static String[] students() {
Scanner input = null;
try {
input = new Scanner(new File(students_file));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
String[] tmp = new String[14];
int c = 0;
while (input.hasNextLine()) {
tmp[c++] = input.nextLine();
}
input.close();
System.out.println(Arrays.deepToString(tmp));
return tmp;
}
public static void main(String[] args) {
students();
}
}
To point you the (basic/raw) way using regex to extract data :
String test = "123 John Maths 15.5";
Matcher matcher = Pattern.compile("(\\d+) (\\w+) (\\w+) (\\d+|\\d+\\.\\d+)").matcher(test);
if(matcher.matches()) {
System.out.println("ID = " + matcher.group(1));
System.out.println("Name = " + matcher.group(2));
System.out.println("Subject = " + matcher.group(3));
System.out.println("Mark = " + matcher.group(4));
}
The only condition for that to work is to have always the same format for CSV file.
The rest is up to you as it is easy to pars all files and just match each line from a file to a line from a second file.
Easiest way (without using classes, etc.) is to use simple Array or Map (Key will be the ID of student for example so yo ucan easily search for him).

java splitting a string by line \n not working

So I have a string which is from a text file, essentially the text file is just 5 lines which read:
x=1
y=15
z=128
topx=100
leftx=150
label= this is a test
I am able to get the split to work once which separates via the '=' sign, but when I try to split the string again by \n nothing works, I have tried using "\r?\n", line.Separator etc. but the string value always stays the same, basically the 5 lines without the characters before the = sign. How would I pull out the individual lines to assign variables to?
Here is the code I have, basically the println is to try and see if I can get the first value '1' to list separate from the rest of the lines.
public static void main(String[] a) {
15 draw d = new draw();
16 Read r = new Read();
17 String m = r.doRead("variables.txt");
18
19 String[] ss = new String[5];
20 ss = m.split("\n");
21
22 String[] kv= new String[5];
23 for (int i=0; i<ss.length; i++) {
24 kv = ss[i].split("=");
25 String eol = System.getProperty("line.seperator");
26 String test = kv[1];
27 String[] split = new String[5];
28 split = test.split("\n");
29
30
31
32
33 String first = split[0];
34 //String second = split[1];
35 //String third = split[2];
36 //String fourth = split[3];
37 //String fifth = split[4];
38 System.out.println(first);
39 }
When every line looks like
x=1 y=15 z=128 topx=100 leftx=150 label= this is a test
you should first split at a whitespace to get 5 parts (x=1, y=15, ...) and then at = to get the "key" and "value" part of each part.
check this out:
String s = "x=1\ny=15\nz=128\ntopx=100\nleftx=150\nlabel= this is a test";
String[] ss = s.split("\n");
System.err.println( Arrays.asList(ss[0].split("=")) );

Reading a file and displaying wanted results

I have a program that reads files like the one below.
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
From these files, the program should output a few things not everything.
The final results that I need should look like this:
0012.TXT
Sample#,Date,Time,Peak Name, Amount
9-62-1,10/2/2013,19:55,Fluoride,10.458
9-62-1,10/2/2013,19:55,Chloride,671.120
9-62-1,10/2/2013,19:55,Nitrite,403.430
9-62-1,10/2/2013,19:55,Sulfate,13.064
But, right now they look like this:
0012.TXT
Sample#,Date,Time,Peak Name, Amount
9-62-1,10/2/2013,19:55,Fluoride,10.458 ,
Chloride,671.120 ,
Nitrite,403.430 ,
n.a.,n.a.,
Sulfate,13.064 ,
,1098.073 ,
Here is my code and what I have done.
Scanner input = new Scanner(new FileReader(selectFile.getSelectedFile()));
System.out.println("Sample#,Date,Time,Peak Name,Amount");
int linesToSkip = 28;
BufferedReader br = new BufferedReader(new FileReader(selectFile.getSelectedFile()));
String line;
while ( (line = br.readLine()) != null) {
if (linesToSkip-- > 0) {
continue;
}
if (line.contains("n.a.")) {
continue;
}
if (line.contains("Total")) {
continue;
}
String[] values = line.split("\t");
int index = 0;
for (String value : values) {
/*System.out.println("values[" + index + "] = " + value);*/
index++;
}
while (input.hasNext()) {
String word = input.next();
Pattern pattern1 = Pattern.compile("Name:");
Pattern pattern2 = Pattern.compile("Time:");
Matcher matcher1 = pattern1.matcher(word);
Matcher matcher2 = pattern2.matcher(word);
Matcher matcher3 = pattern2.matcher(word);
if(matcher1.matches()){
System.out.print(input.next() + ",");
}
if(matcher2.matches()){
System.out.print(input.next() + ",");
}
if(matcher3.matches()){
System.out.print(input.next() + ",");
}
System.out.print("");
}
System.out.print(values[2]+",");
System.out.println(values[6]+"\b,");
}
br.close();
How can I make the output look like these with the sample#, Date and Time then followed by the peak name and amount and print them that way on each line?
Sample#,Date,Time,Peak Name, Amount
9-62-1,10/2/2013,19:55,Fluoride,10.458
9-62-1,10/2/2013,19:55,Chloride,671.120
9-62-1,10/2/2013,19:55,Nitrite,403.430
9-62-1,10/2/2013,19:55,Sulfate,13.064
Thanks!
Something like:
while ( (line = br.readLine()) != null) {
if (line.contains("n.a.")) {
continue;
}
//Your code
You can do the same in your inner while loop for specific table item for peak name value and the amount value. In that case you can use String#equales() method.
Edit for Comments:
You are over complicating your things while printing and reading your file content. Dont use Scanner as well as BufferedReader. One will do the work for you.
You have very specific format for your file. You really dont need to use regex for this purpose, which you are using in your inner while loop.
For sample name to match use String#equales() method and do you operations accordingly.
Get the values you needed from upper section of your file like Sample Name and Recording Time, keep them handy, so that you could use them later.
From you lower section get Peak Name and amount from each row.
While printing construct your String by making use of these collected values.
Another Edit for Comments:
the following code is not tested, so there could be some issues, but you can figure them out.
If you look at String Class then you will find many useful methods.
BufferedReader br = new BufferedReader(new FileReader(selectFile.getSelectedFile()));
String recTime, peakName, amount, sample ;
int linesToSkip = 28;
String line = br.readLine();
if(line != null){
String[] values = line.split("\t");
sample = values[1];
}
while ( (line = br.readLine()) != null) {
values = line.split("\t");
if (line.startsWith("Sample Name")) {
// Check here value[1] is equal to sample. If this is needed.
// You got your sample name here
} else if (line.startsWith("Recording Time")) {
recTime = values[1];
// You got your Recording Time here
} else if(values.length > 4 ){
// get Peak Name and recording time
peakName = values[2];
amount = values[6];
} else if (line.contains("n.a.") || line.contains("Total") || linesToSkip-- > 0) {
/* may not needed linesToSkip-- > 0 in above condition */
continue;
}
System.out.println(sample +" ," + recTime + " ," + peakName + " ," + amount);
}
I hope this helps. Good Luck.

Find a pair of string at integer and subtract, java

I have a string which contains a value:
12345 5
54321 4
98765 10
The first value is a number, the second value is a count. The string value is obtained by this code:
for(ClusterListBean bean : clusterList) {
line += bean.getMSISDN()+"\t"+bean.getRewardCount()+"\n";
}
Now I am reading a file which has same contents but different count value.
This is accomplished by:
BufferedReader ln = FileCreatorUtil.readFile(configFileUtil.prevFile().getFileDir()+prevFile.clusterPrevFile().getFileName());
Now what I want to do is to search for a number value, get the count paired with it, and subtract the count. Example:
BufferedReader ln contents:
12345 5
54321 4
98765 10
String line contents:
12345 7
54321 9
98765 15
Output should be:
12345 2
54321 5
98765 5
Put your data into a HashMap where MSISDN is key and count is value. Reading second file consult that map and subtract the value.
Why don't you put your "Strings" in a hashmap?
Map<String,Integer> map = new HashMap<String,Integer>();
for(ClusterListBean bean : clusterList) {
map.put(bean.getMSISDN(),bean.getRewardCount());
}
then read your file:
BufferedRead ln = null;
try{
ln = new BufferedReader(new FileReader(configFileUtil.prevFile().getFileDir()+prevFile.clusterPrevFile().getFileName()));
String line;
while((line=br.readLine())!=null){
String[] linesplit = line.split("\\t");
if (map.containsKey(linesplit[0])){
//do whatever you need with something like:
System.out.println(map.get(linesplit[0])-Integer.parseInt(linesplit[1]));
}
}
ln.close();
}catch(IOException e){
e.printStackTrace();
}

Categories