I'm reading multiple string and adding them to Vector which looks like this.
public void readCode(){
BufferedReader abc;
try {
abc = new BufferedReader(new FileReader("code.txt"));
String line;
while((line = abc.readLine()) != null) {
lines.add(line);
}
abc.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
for(int i = 0;i<lines.size();i++){
String x=lines.get(i);
String[] split = x.split("#");
vkCode.add(split[0]);
vkName.add(split[1]);
}
}
And then i'm using this code to find the item code of certain item name.
String cmpre="";
banding = sc.nextLine();
int target = -1;
for(int p = 0;p<vkName.size();p++){
if(vkName.get(p).toString().toLowerCase().contains(cmpre)){
target=p;
break;
}
}
if(target==-1){
System.out.println("Item does not exist!");
}
else{
System.out.println("Item Code is : "+vkCode.get(target));
}
So far the code works just fine , but there is a problem.
Let say the list of item looks like this.
Edit requested:
Data Sample
1213112#PT ABC Syariah Tbk
1212112#PT ABC Tbk
1241312#PT ABC Central Tbk
Case 1:
If we try to find ABC the expected result is PT ABC Tbk ID which is 1212112 but due to my code it will result in PT ABC Syariah Tbk ID instead
Case 2:
If we try to find Syariah ABC it will not return any code at all. Due to the textfile having ABC Syariah which is a problem too.
First generate a collection of fuzzy matches using .contains(). Then, from that collection, generate a second collection of exact matches using .equals(). Then return the first exact match if there is one, else return the first fuzzy match if there is one, else null.
Related
I am building a small Java utility (using Jackson) to catch errors in Java files, and one part of it is a text area, in which you might paste some JSON context and it will tell you the line and column where it's found it:
I am using the error message to take out the line and column as a string and print it out in the interface for someone using it.
This is the JSON sample I'm working with, and there is an intentional error beside "age", where it's missing a colon:
{
"name": "mkyong.com",
"messages": ["msg 1", "msg 2", "msg 3"],
"age" 100
}
What I want to do is also highlight the problematic area in a cyan color, and for that purpose, I have this code for the button that validates what's inserted in the text area:
cmdValidate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
functionsClass ops = new functionsClass();
String JSONcontent = JSONtextArea.getText();
Results obj = new Results();
ops.validate_JSON_text(JSONcontent, obj);
String result = obj.getResult();
String caret = obj.getCaret();
//String lineNum = obj.getLineNum();
//showStatus(result);
if(result==null) {
textAreaError.setText("JSON code is valid!");
} else {
textAreaError.setText(result);
Highlighter.HighlightPainter cyanPainter;
cyanPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.cyan);
int caretPosition = Integer.parseInt(caret);
int lineNumber = 0;
try {
lineNumber = JSONtextArea.getLineOfOffset(caretPosition);
} catch (BadLocationException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
try {
JSONtextArea.getHighlighter().addHighlight(lineNumber, caretPosition + 1, cyanPainter);
} catch (BadLocationException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
});
}
The "addHighlight" method works with a start range, end range and a color, which didn't become apparent to me immediately, thinking I had to get the reference line based on the column number. Some split functions to extract the numbers, I assigned 11 (in screenshot) to a caret value, not realizing that it only counts character positions from the beginning of the string and represents the end point of the range.
For reference, this is the class that does the work behind the scenes, and the error handling at the bottom is about extracting the line and column numbers. For the record, "x" is the error message that would generate out of an invalid file.
package parsingJSON;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class functionsClass extends JSONTextCompare {
public boolean validate_JSON_text(String JSONcontent, Results obj) {
boolean valid = false;
try {
ObjectMapper objMapper = new ObjectMapper();
JsonNode validation = objMapper.readTree(JSONcontent);
valid = true;
}
catch (JsonParseException jpe){
String x = jpe.getMessage();
printTextArea(x, obj);
//return part_3;
}
catch (IOException ioe) {
String x = ioe.getMessage();
printTextArea(x, obj);
//return part_3;
}
return valid;
}
public void printTextArea(String x, Results obj) {
// TODO Auto-generated method stub
System.out.println(x);
String err = x.substring(x.lastIndexOf("\n"));
String parts[] = err.split(";");
//String part 1 is the discarded leading edge that is the closing brackets of the JSON content
String part_2 = parts[1];
//split again to get rid of the closing square bracket
String parts2[] = part_2.split("]");
String part_3 = parts2[0];
//JSONTextCompare feedback = new JSONTextCompare();
//split the output to get the exact location of the error to communicate back and highlight it in the JSONTextCompare class
//first need to get the line number from the output
String[] parts_lineNum = part_3.split("line: ");
String[] parts_lineNum_final = parts_lineNum[1].split(", column:");
String lineNum = parts_lineNum_final[0];
String[] parts_caret = part_3.split("column: ");
String caret = parts_caret[1];
System.out.println(caret);
obj.setLineNum(lineNum);
obj.setCaret(caret);
obj.setResult(part_3);
System.out.println(part_3);
}
}
Screenshot for what the interface currently looks like:
Long story short - how do I turn the coordinates Line 4, Col 11 into a caret value (e.g. it's value 189, for the sake of argument) that I can use to get the highlighter to work properly. Some kind of custom parsing formula might be possible, but in general, is that even possible to do?
how do I turn the coordinates Line 4, Col 11 into a caret value (e.g. it's value 189,
Check out: Text Utilities for methods that might be helpful when working with text components. It has methods like:
centerLineInScrollPane
getColumnAtCaret
getLineAtCaret
getLines
gotoStartOfLine
gotoFirstWordOnLine
getWrappedLines
In particular the gotoStartOfLine() method contains code you can modify to get the offset of the specified row/column.offset.
The basic code would be:
int line = 4;
int column = 11;
Element root = textArea.getDocument().getDefaultRootElement();
int offset = root.getElement( line - 1 ).getStartOffset() + column;
System.out.println(offset);
The way it works is essentially counting the number of characters in each line, up until the line in which the error is occurring, and adding the caretPosition to that sum of characters, which is what the Highlighter needs to apply the marking to the correct location.
I've added the code for the Validate button for context.
functionsClass ops = new functionsClass();
String JSONcontent = JSONtextArea.getText();
Results obj = new Results();
ops.validate_JSON_text(JSONcontent, obj);
String result = obj.getResult();
String caret = obj.getCaret();
String lineNum = obj.getLineNum();
//showStatus(result);
if(result==null) {
textAreaError.setText("JSON code is valid!");
} else {
textAreaError.setText(result);
Highlighter.HighlightPainter cyanPainter;
cyanPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.cyan);
//the column number as per the location of the error
int caretPosition = Integer.parseInt(caret); //JSONtextArea.getCaretPosition();
//the line number as per the location of the error
int lineNumber = Integer.parseInt(lineNum);
//get the number of characters in the string up to the line in which the error is found
int totalChars = 0;
int counter = 0; //used to only go to the line above where the error is located
String[] lines = JSONcontent.split("\\r?\\n");
for (String line : lines) {
counter = counter + 1;
//as long as we're above the line of the error (lineNumber variable), keep counting characters
if (counter < lineNumber)
{
totalChars = totalChars + line.length();
}
//if we are at the line that contains the error, only add the caretPosition value to get the final position where the highlighting should go
if (counter == lineNumber)
{
totalChars = totalChars + caretPosition;
break;
}
}
//put down the highlighting in the area where the JSON file is having a problem
try {
JSONtextArea.getHighlighter().addHighlight(totalChars - 2, totalChars + 2, cyanPainter);
} catch (BadLocationException e1) {
// TODO Auto-generated catch block
e1.getMessage();
}
}
The contents of the JSON file is treated as a string, and that's why I'm also iterating through it in that fashion. There are certainly better ways to go through lines in the string, and I'll add some reference topics on SO:
What is the easiest/best/most correct way to iterate through the characters of a string in Java? - Link
Check if a string contains \n - Link
Split Java String by New Line - Link
What is the best way to iterate over the lines of a Java String? - Link
Generally a combination of these led to this solution, and I am also not targeting it for use on very large JSON files.
A screenshot of the output, with the interface highlighting the same area that Notepad++ would complain about, if it could debug code:
I'll post the project on GitHub after I clean it up and comment it some, and will give a link to that later, but for now, hopefully this helps the next dev in a similar situation.
i'm new with java and have some trouble with one task.
i have txt file which looks like this:
John Doe,01-01-1980,Development,Senior Developer
Susan Smith,07-12-1983,Development,Head of Development
Ane Key,06-06-1989,BA,Junior Analyst
Nina Simone,21-09-1979,BA,Head of BA
Tom Popa,23-02-1982,Development,Developer
Tyrion Lannyster,17-03-1988,BA,Analyst
and i want to to sort it by departments.
for example:
Members are :
[Employee Full Name] - [Employee Age] - [Employee Position] - [Employee Salary(default value x)]
Deparment : Development
Members are :
Susan Smith ......
John Doe ......
Tom Popa ......
Department : BA
Members are :
Nina Simone .......
Ane Key ...........
Tyrion Lannyster ........
at first read file and made 2d array but can't continue how to correctly sort it.
public static void main(String[] args) {
String csvFile = "C:\\Employees.txt";
BufferedReader br = null;
String line = "";
String SplitBy = ",";
String myArray[][] = new String[6][5];
int row = 0;
try {
br = new BufferedReader(new FileReader(csvFile));
while ((line = br.readLine()) != null) {
String nums[] = line.split(SplitBy);
for (int col = 0; col < nums.length; col++){
String n =nums[col];
myArray[row][col] = n;
// System.out.println(n);
}
row++;
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Providing the code solution here would not help you learn it. But I can give you hints on how to proceed. Using array is not really recommended.
The easy, but dirty way -
Instead of two dimensional array, use a TreeMap<String, String[]> where key is the department concatenated with name and value is the one dimensional array of the individual's details. As we're using TreeMap, the result is naturally sorted based on Department followed by Name of the person. Loop through the entrySet and print all the results.
Right way -
Define new object Person with all the members needed. Implement Comparable interface. Read all the input data, populate the same in Person object, add each such objects in an ArrayList and use Collections API's sort method to sort all the objects. Alternatively you can adapt the Comparator way.
The Java Collections APIallows you to Sort as well as util.Arrays.
You will need the arrays methods for you code, but consider moving to some sort of Collection. Perhaps a List to start with.
The easiest way would put the contents of the lines in Java Beans and then sort them using sort.
public User {
private String name;
// ... all the fields with getters and setters
}
Then adapt your code to something like this:
// create a nice List for the users.
List<User> userList = new ArrayList<>();
while ((line = br.readLine()) != null) {
User user = new User();
String nums[] = line.split(SplitBy);
user.setName(nums[0]);
// create nice method to convert String to Date
user.setDate(convertStringToDate(nums[1]));
// add the user to the list
userList.add(user);
}
// Then finally sort the data according to the desired field.
Arrays.sort(userList, (a,b) -> a.name.compareTo(b.name));
I'm getting results from a PHP, and parse them to a String array
ParseResults[0] is the ID returned from the database.
What I'm trying to do, is make a message box, which is only shown once (until the application is restarted of course).
My code looks something like this, but I can't figure out what stops it from working properly.
public void ShowNotification() {
try {
ArrayList<String> SearchGNArray = OverblikIntetSvar(Main.BrugerID);
// SearchGNArray = Gets undecoded rows of information from DB
for(int i=0; i<SearchGNArray.size(); i++){
String[] ParseTilArray = ParseResultater(SearchGNArray.get(i));
// ParseToArray = Parse results and decode to useable results
// ParseToArray[0] = the index containing the ID we'd like
// to keep track of, if it already had shown a popup about it
if (SearchPopUpArray.size() == 0) {
// No ID's yet in SearchPopUpArray
// SearchPopUpArray = Where we'd like to store our already shown ID's
SearchPopUpArray.add(ParseTilArray[0]);
// Create Messagebox
}
boolean match = false ;
for(int ii=0; ii<SearchPopUpArray.size(); ii++){
try {
match = SearchPopUpArray.get(ii).equals(ParseTilArray[0]);
} catch (Exception e) {
e.printStackTrace();
}
if(match){
// There is a match
break; // Break to not create a popup
} else {
// No match in MatchPopUpArray
SearchPopUpArray.add(ParseTilArray[0]);
// Create a Messagebox
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
As of now I have 2 rows, so there should be two ID's. There's 101 and 102. It shows 102 once, and then it just keeps creating messageboxes about 101.
You are not incrementing the right variable in the second for-loop:
for(int ii = 0; ii <SearchPopUpArray.size();i++){
/* ^
|
should be ii++
*/
}
It might be help to use more descriptive variable name like indexGN and indexPopup instead to avoid this sort of issue
I've deleted the second for loop:
for(int ii=0; ii<SearchPopUpArray.size(); ii++){
try {
match = SearchPopUpArray.get(ii).equals(ParseTilArray[0]);
} catch (Exception e) {
e.printStackTrace();
}
if(match){
// There is a match
} else {
// No match in MatchPopUpArray
SearchPopUpArray.add(ParseTilArray[0]);
// Create a Messagebox
}
}
And replaced with
if (SearchPopUpArray.contains(ParseTilArray[0])) {
// Match
} else {
// No match i MatchPopUpArray
SearchPopUpArray.add(ParseTilArray[0]);
// Create a Messagebox
}
Much more simple.
I have trouble splitting a name by a space, and I can't seem to figure out why. Could someone please provide me with a solution?
My code is like this:
public void getPlayerNames(int id){
try {
Document root = Jsoup.connect("http://www.altomfotball.no/element.do?cmd=team&teamId=" + id).get();
Element table = root.getElementById("sd_players_table");
Elements names = table.getElementsByTag("a");
for(Element name : names){
getPlayers().add(new Player(name.text()));
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
which returns the name of football players as a string. The names are retrieved such as Mario Balotelli, Steven Gerrard, and so on, and I assumed I could use string.split(" "); to get me the first and last names, but whenever I try to access the second space of the string array it gives me an index out of bounds exception. Here is the code trying to fetch me the first name
/**
* Method to get the first name of a player
*/
public static String getFirstName(String name){
String[] nameArray = name.split(" ");
return nameArray[0];
}
Thanks for answers!
Sindre M
EDIT ######
So I got it to work, but thanks for the effort. The problem was that even though I could not see it in a simple sysout statement, the names actually contained a " "; character, so I solved it by running a replaceAll("  ;" , " ") on the names for a better formatting.
If you're trying to write a screen-scraper you need to be more defensive in your code... Definitely test the length of the array first and log any unexpected inputs so you can incorporate them later...
public static String getFirstName(String name) {
String[] nameArray = name.split(" ");
if (nameArray.length >= 1) { // <== check length before you access nameArray[0]
return nameArray[0];
} else {
// log error
}
return null;
}
Additionally java.util.Optional in Java 8 provides a great alternative to returning null...
public static Optional<String> getFirstName(String name) {
String[] nameArray = name.split(" ");
if (nameArray.length >= 1) {
return Optional.of(nameArray[0]);
} else {
// log error
}
return Optional.empty();
}
You might be getting in the actual string as you are retrieving from html page. try to debug and check.
package com.appkart.examples;
public class SplitProgram {
public void firstNameArray(String nameString) {
String strArr[] = nameString.split(",");
for (String name : strArr) {
String playerName = name.trim();
String firstName = playerName.substring(0, playerName.indexOf(" "));
System.out.println(firstName);
}
}
public static void main(String[] args) {
String nameString = "Mario Balotelli, Steven Gerrard";
SplitProgram program = new SplitProgram();
program.firstNameArray(nameString);
}
}
I think that the correct answer should be:
String[] nameArray = name.split("\\s+");
But to be honest, there are couple of answers at stackoverflow.
Eg.
How to split a String by space
How do I split a string with any whitespace chars as delimiters?
First try to replace white space as
string.replace(" ","");
then try to split with [,] as
String strAr[] = string.split(",");
I must be doing my regex wrong.
In the console I do
db.triples.find({sub_uri: /.*pdf.*/ }); and get the desired result.
My Java class looks like this, (I have set input="pdf"):
public static List<Triple> search(String input){
DB db=null;
try {
db = Dao.getDB();
}
catch (UnknownHostException e1) { e1.printStackTrace(); }
catch (MongoException e1) { e1.printStackTrace(); }
String pattern = "/.*"+input+".*/";
System.out.println(input);
List<Triple> triples = new ArrayList<Triple>();
DBCollection triplesColl = null;
try {
triplesColl = db.getCollection("triples"); } catch (MongoException e) { e.printStackTrace();}
{
Pattern match = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
BasicDBObject query = new BasicDBObject("sub_uri", match);
// finds all people with "name" matching /joh?n/i
DBCursor cursor = triplesColl.find(query);
if(cursor.hasNext()){
DBObject tripleAsBSON = cursor.next();
Triple t = new Triple();
t.setSubject(new Resource((String)tripleAsBSON.get("sub_uri")));
System.out.println(t.getSubject().getUri());
triples.add(t);
}
}
return triples;
}
From the console I get 12 results as I should, from the Java code I get no results.
Java doesn't need/understand regex delimiters (/ around the regex). You need to remove them:
String pattern = ".*"+input+".*";
I'm also not sure if that regex is really what you want. At least you should anchor it:
String pattern = "^.*"+input+".*$";
and compile it using the Pattern.MULTILINE option. This avoids a severe performance penalty if a line doesn't contain your sub-regex input. You are aware that input is a regex, not a verbatim string, right?