Find a pair of string at integer and subtract, java - 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();
}

Related

Reading from a CSV file parsing error/problem

Hello I am having issues reading from csv file which contains 3 columns per row. I cant seem to parse the last cell (3) to an integer even though it is always a "parsable" string:
Berlin,Buenos Aires,7402 I can't seem to get 7402 all the compiler throws is:
"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
at java.base/java.lang.Integer.parseInt(Integer.java:658)
at java.base/java.lang.Integer.parseInt(Integer.java:776)
This is the code I have:
Scanner scan = new Scanner("worldcities.csv");
scan.useDelimiter("[,\\n]"); // get everything before a comma or a newline
while(scan.hasNext()) { // while this file has something then we
edge.v1 = scan.next(); // take vertice1 ----> city 1
edge.v2 = scan.next(); //take vertice2 ----> city 2
edge.e = Integer.parseInt(scan.next()); // parse the third value as int(distance between city1 and city2)
minheap.add(edge);
}
scan.close();
I seem to be able to get the first 2 values fine in the debugger.
the console just shows "
You can iterate throught file lines with the nextLine() method, as in this example:
Scanner scanner = new Scanner(new File("worldcities.csv"));
while (scanner.hasNextLine()) {
String columns[] = scanner.nextLine().split(",");
edge.v1 = columns[0]; // take vertice1 ----> city 1
edge.v2 = columns[1]; //take vertice2 ----> city 2
edge.e = Integer.parseInt(columns[2]); // parse the third value as int(distance between city1 and city2)
minheap.add(edge);
}
scanner.close();
or with using the Files class without the Scanner:
List<String> rows = Files.readAllLines(Paths.get("worldcities.csv"));
for (String row : rows) {
String columns[] = row.split(",");
edge.v1 = columns[0]; // take vertice1 ----> city 1
edge.v2 = columns[1]; //take vertice2 ----> city 2
edge.e = Integer.parseInt(columns[2]); // parse the third value as int(distance between city1 and city2)
minheap.add(edge);
}
Also you can use a special library for working with CVS files, for example look at Apache Commons CSV library.

What is wrong in my file reading with Scanner class?

Every time I run it, gives this message (( InputMismatchException )) where is the problem from ?
File f = new File("nameList.txt");
try {
PrintWriter out;
out = new PrintWriter(f);
for (int i = 0; i < 4; i++) {
out.printf("Name : %s Age : %d ", "Rezaee-Hadi", 19);
out.println("");
}
out.close();
} catch (IOException ex) {
System.out.println("Exception thrown : " + ex);
}
try {
Scanner in = new Scanner(f);
String name = in.nextLine();
int age = in.nextInt();
for (int i = 0; i < 4; i++) {
System.out.println(name);
System.out.println(age);
}
in.close();
} catch (FileNotFoundException ex) {
System.out.println("Exception thrown : " + ex);
}
You are creating your data file in the following data format:
Name : Rezaee-Hadi Age : 19
Now, it really doesn't matter (to some extent) how you format your data file as long as you realize that you may need to parse that data later on. You really don't need to maintain a header with your data on each file line. We already know that the first piece of data on any file line is to be a Name and the second piece of data on any file line is to be the Age of the person the Name relates to. So, the following is sufficient:
Rezaee-Hadi, 19
If you want, you can place a header as the very first line of the data file so that it can easily be determined what each piece of data on each line relates to, for example:
Name, Age
Rezaee-Hadi, 19
Fred Flintstone, 32
Tom Jones, 66
John Smith, 54
This is actually a typical format for CSV data files.
Keeping with the file data format you are already using:
There is nothing wrong with using the Scanner#nextLine() method. It's a good way to go but you should be iterating through the file line by line using a while loop because you may not always know exactly how many actual data lines are contained within the file, for example:
Scanner in = new Scanner(f);
String dataLine;
while (in.hasNextLine()) {
dataLine = in.nextLine().trim();
// Skip Blank Lines
if (dataLine.equals("")) {
continue;
}
System.out.println(dataLine);
}
This will print all the data lines contained within your file. But this is not what you really want is it. You want to separate the name and age from each line which means then that you need to parse the data from each line. One way (in your case) would be something like this:
String dataLine;
Scanner in = new Scanner(f);
while (in.hasNextLine()) {
dataLine = in.nextLine().trim();
// Skip Blank Lines
if (dataLine.equals("")) {
continue;
}
String[] dataParts = dataLine.replace("Name : " , "").split(" Age : ");
System.out.println("The Person's Name: " + dataParts[0] + System.lineSeparator()
+ "The Person's Age: " + dataParts[1] + System.lineSeparator());
}
In the above code we iterate through the entire data file one line at a time using a while loop. As each line is read into the dataLine string variable it is also trimmed of any leading or trailing whitespaces. Normally we don't want these. We then check to make sure the line is not blank. We don't normally want these either and here we skip past those blank lines by issuing a continue to the while loop so as to immediately initiate another iteration. If the file line line actually contains data then it is held within the dataLine variable.
Now we want to parse that data so as to retrieve the Name and the Age and place them into a String Array. We do this by using the String#split() method but first we get rid of the "Name : " portion of the line using the String#replace() method since we don't want to deal with this text while we parse the line. In the String#split() method we supply a string delimiter to split by and that delimiter is " Age : ".
String[] dataParts = dataLine.replace("Name : " , "").split(" Age : ");
Now when each line is parsed, the Name and Age will be contained within the dataParts[] string array as elements located at index 0 and index 1. We now use these array elements to display the results to console window.
At this point the Age is a string located in the dataParts[] array at index 1 but you may want to convert this age to a Integer (int) type value. To do this you can utilize the Integer.parseInt() or Integer.valueOf() methods but before you do that you should validate the fact the the string you are about to pass to either of these methods is indeed a string numerical integer value. To do this you would utilize the String#matches() method along with a simple little Regular Expression (RegEx):
int age = 0;
if (dataParts[1].matches("\\d+")) {
age = Integer.parseInt(dataParts[1]);
// OR age = Integer.valueOf(dataParts[1]);
System.out.println("Age = " + age);
}
else {
System.out.println("Age is not a numerical value!");
}
The regular expression "\\d+" placed within the String#matches() method basically means, "Is the supplied string a string representation of a integer numerical value?". If the method finds that it is not then boolean false is returned. If it finds that the value supplied is a string integer numerical value then boolean true is returned. Doing things this way will prevent any NumberFormatException's from occurring.
Replace this:
int age=0;
while (in.hasNext()) {
// if the next is a Int,
// print found and the Int
if (in.hasNextInt()) {
age = in.nextInt();
System.out.println("Found Int value :"
+ age);
}
}
in place of this:
int age = in.nextInt();
Then you will not get "InputMismatchException" anymore..

Data evaluation from text file

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

Buffered Reader: Reset won't reset

I'm currently learing about the mark() and reset() methods of the BufferedReader and want to do the following:
I parse a CSV, set up like this (spaces as delimiter):
555 value1
555 value2
600 foobar
700 whatever
Each line, one object (adress) is created with the first number as its ID. When the ID is used multiple times, I want to compare the values in the second column and proceed afterwards.
With the data above, my code does compare the two values with ID 555, but fails to create an object with the third line (ID 600).
Mistake found: splitted the first line after parsing the new one. Simple mix up of variables.
My setup is similar to this:
br = new BufferedReader(new FileReader(csvFile));
while ((line = br.readLine()) != null) {
br.mark(1000); //save current line
List<String> list = new ArrayList<String>(Arrays.asList(line.split(delimiter)));
Adress a = new Adress(Long.parseLong(list.get(0)); //create object
while (((checkLine = br.readLine()) != null) && exit == false){
List<String> nextLine = new ArrayList<String>(Arrays.asList(line.split(delimiter)));
long nextId = Long.parseLong(nextLine.get(0));
if( nextId == a.getId() ){
System.out.println(nextId + " vs. " + a.getId());
br.mark(1000); //mark the next line if it has the same ID
//[...] do more stuff
} else{
exit = true;
}
}
br.reset(); //reset to the last line with the ID
}
Sysout:
555 vs. 555
555 vs. 555
555 vs. 555
I see a couple of issues in the code:
Inside the second while() loop you are still splitting the string "line", but the while loop assigns the input to "checkLine".
You don't reset "exit" to false - this should probably happen after the br.reset().
if your addresses are separated by spaces , and the different elements of your address are also separated by spaces , then this line does not give you addresses , it gives you elements .
List < String > list = new ArrayList < String > ( Arrays . asList ( line . split ( delimiter ) ) ) ;
The mistake was the following variable-mixup (solely my stupidity was the mistake!):
while (((checkLine = br.readLine()) != null) && exit == false){
List<String> nextLine = new ArrayList<String>(Arrays.asList(line.split(delimiter)));
[...]
The List nextLine has to be changed from line.split to checkline.split:
List<String> nextLine = new ArrayList<String>(Arrays.asList(checkLine.split(delimiter)));
Thanks to everybody helping!

cutting column from file in java

I've searched and can't find my question.
I've saved file with linux output ls -l which content is:
drwxr-xr-x 2 usr usr 4096 Jan 20 17:49 file1
drwxrwxr-x 4 usr usr 4096 Jan 20 18:00 file2
drwx------ 2 usr usr 4096 Feb 3 08:48 catalog1
And I want to leave for example only eighth column with hour, and cut off rest of it. What should I do? I'm very beginner with java and programming.
You can use a regular expression to match the timestamp (since it's guaranteed that a time-like value will not appear in any of the other fields). Something like:
// Populate this with the output of the ls -l command
String input;
// Create a regular expression pattern to match.
Pattern pattern = Pattern.compile("\\d{2}:\\d{2}");
// Create a matcher for this pattern on the input string.
Matcher matcher = pattern.matcher(input);
// Try to find instances of the given regular expression in the input string.
while (matcher.find()){
System.out.println(matcher.group());
}
To retrieve any arbitrary column, you can opt to write a regular expression for whichever column you're trying to retrieve, or you may wish to just split each row on the space character, then select by index. For example, to get all of the filesizes:
String input;
String[] inputLines = input.split("\n");
for (String inputLine : inputLines) {
String[] columns = inputLine.split(" ");
System.out.println(columns[4]); // Where 4 indicates the filesize column
}
You need to use StringTokenizer to extract out the exact information that you are looking for. Try the following code:
String value = "drwxr-xr-x 2 usr usr 4096 Jan 20 17:49 file1\n"+
"drwxrwxr-x 4 usr usr 4096 Jan 20 18:00 file2\n"+
"drwx------ 2 usr usr 4096 Feb 3 08:48 catalog1";
StringBuffer sBuffer = new StringBuffer(10);
StringTokenizer sTokenizer = new StringTokenizer(value,"\n");
while (sTokenizer.hasMoreTokens())
{
String sValue = sTokenizer.nextToken();
StringTokenizer sToken = new StringTokenizer(sValue," ");
int counter = 0;
while (sToken.hasMoreTokens())
{
String token = sToken.nextToken();
counter++;
if (counter == 8)//8 is the column that you want to leave.
{
sBuffer.append(token+"\n");
break;
}
}
}
System.out.println(sBuffer.toString());

Categories