How to parse my log.txt in this format in java - java

I am trying to parse this certain log entry
"[Zone] ZoneChangeList.ProcessChanges() - processing index=9
change=powerTask=[power=[type=TAG_CHANGE entity=[id=78 cardId=FP1_007t
name=Nerubian] tag=IGNORE_DAMAGE_OFF value=1] complete=False]
entity=[name=Nerubian id=78 zone=GRAVEYARD zonePos=1 cardId=FP1_007t
player=2] srcZoneTag=INVALID srcPos= dstZoneTag=INVALID dstPos=";
I am using a scanner delimiter in Java but the problem is that the change field
which has multiple values enclosed in a bracket.
I would also want to put the parsed record on a bean having their values
So far, here is what I have coded:
public class HearthstoneParser {
public void zoneParser(String line) {
Scanner scanner = new Scanner(line);
scanner.useDelimiter(" ");
while (scanner.hasNext()) {
System.out.println(scanner.next());
}
}
public static void main(String args[]) {
String zoneString = "[Zone] ZoneChangeList.ProcessChanges() - processing index=9 change=powerTask=[power=[type=TAG_CHANGE entity=[id=78 cardId=FP1_007t name=Nerubian] tag=IGNORE_DAMAGE_OFF value=1] complete=False] entity=[name=Nerubian id=78 zone=GRAVEYARD zonePos=1 cardId=FP1_007t player=2] srcZoneTag=INVALID srcPos= dstZoneTag=INVALID dstPos=";
HearthstoneParser parser = new HearthstoneParser();
parser.zoneParser(zoneString);
}
}
I would want to keep them organized that they are group with their brackets respectively
sample output would be:
Zone
event = ZoneChangeList.ProcessChanges()
index = 9
change
powerTask
power
type = TAG_CHANGE
entity
id = 78
cardID=Fp1_007t
name Nerubian
tag=IGNORE_DAMAGE_OFF
value=1
complete=False
entity
name=nerubian
id=78
zone=GRAVEYARD
zonePos=1
cardId=FP1_007t
player=2
srcZoneTag=INVALID
srcPos=
dstZoneTag=INVALID
dstPos=

Related

Evaluating String in java Using ScriptEnging

Below is my code to take a somewhat simple user input of hello or mouse and search a String(I will later use this on much larger text files).
I use it to create a Java line of code that uses the contains method. After, I need to evaluate it. I found some help using the Script engine, but I keep getting this error: Exception in thread "main" javax.script.ScriptException: ReferenceError: "name" is not defined in <eval> at line number 1 The output that comes from the code that I want to evaluate is name.contains("hello") || name.contains("mouse").
Any help would be great. Thanks
public static void main(String args[]) throws ScriptException {
String searchString = "name";
String terms = "(hello) || (mouse)";
String command = "";
//multiple commands
if(terms.contains("(") && terms.contains(")") && terms.contains("[") && terms.contains("]")){
command = terms.replace(")","\")");
command=command.replace("(", searchString + ".contains(\"");
command = command.replace("[","(");
command = command.replace("]",")");
}
//only ands/ only ors
else {
command = terms.replace("(", searchString + ".contains(\"");
command = command.replace(")", "\")");
}
System.out.println(command);
String name = "mousehellonamepe";
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
Object result = engine.eval(command);
System.out.println(result);
What are you trying to do exactly ?
======= Update ======
First, String terms should be a list.
Make it:
ArrayList<String> searchTerms = new ArrayList();
Add as many words as you like to that list as follows:
// using add() to initialize values
arr.add("Hello");
arr.add("Mouse");
arr.add("Bike");
arr.add("House");
// use contains() to check if the element
// 2 exits or not
boolean mouseExists = arr.contains("Mouse");
if (ans)
System.out.println("Our list contains the word mouse");
else
System.out.println("Our list does not contain the word mouse");
This should output this:
Our list contains the word mouse
Code should look like this:
public static void main(String args[]) throws ScriptException {
ArrayList<String> searchTerms = new ArrayList();
arr.add("Hello");
arr.add("Mouse");
arr.add("Bike");
arr.add("House");
boolean mouseExists = arr.contains("Mouse");
if (ans)
System.out.println("Our list contains the word mouse");
else
System.out.println("Our list does not contain the word mouse");
}
Interpreter i = new Interpreter();
i.set("searchThis", searchString);
i.set("answer", i.eval(command));
Boolean answer2 = (Boolean) (i.get("answer"));
http://www.beanshell.org/manual/quickstart.html#Calling_BeanShell_From_Your_Application
I used this to evaluate the command.
the link above provides all the explanation!

Parsing input from file, delimiters, loops, java

The overall project is creating a system manager for airports. It keeps track of airports, flights, seating sections, seats and other relevent info for each of those catagories. The initial system is set up by importing from a file that's formatted a certain way. I'm having problems parsing the file properly to set up the initial system. the data is parsed from the file and used as method parameters to create the objects: Airport, Airline, Flight, FlightSection, and Seat.
the formatting is:
[list-of-airport-codes] {list-of-airlines}
list-of-airport-codes ::= comma-separated strings
list-of-airlines ::= airline-name1[flightinfo-list1], airline-name2[flightinfo-list2], airlinename3[flightinfo-list3], …
flightinfo-list ::= flightID1|flightdate1|originAirportCode1|destinationAirportCode1[flightsectionlist1], flightID2|flightdate2|originAirportCode2|destinationAirportCode2[flightsection-list2], …
flightdate ::= year, month, day-of-month, hours, minutes
flightsection-list ::= sectionclass: seat-price: layout: number-of-rows, …
sectionclass ::= F, B, E (for first class, business class, economy class)
layout ::= S, M, W (different known seating layouts)
example:
[DEN,NYC,SEA,LAX]{AMER[AA1|2018,10,8,16,30|DEN|LAX[E:200:S:4,F:500:S:2],
AA2|2018,8,9,7,30|LAX|DEN[E:200:S:5,F:500:S:3], …], UNTD[UA21|2018,11,8,12,30|NYC|SEA[E:300:S:6,F:800:S:3], UA12|2018,8,9,7,30|SEA|DEN[B:700:S:5, F:1200:S:2], …], FRONT[…], USAIR[…]}
I tried brute forcing it using a combination of delimiters and while loops. The code successfully creates the Airports, first Airline and Flighsections, but when it gets to creating the second airline it crashes, because i'm not looping properly, and having a hard time getting it right. My code for it as of now, is a mess, and if you're willing to look at it, I would appreciate any constructive input. My question is what would be a better way to approach this? A different design approach? Maybe a smarter way to use the delimiters?
Thanks in advance for your help!!
here's what i've tried.
private void readFile(File file){
System.out.println("reading file");
Scanner tempScan;
String result;
String temp = "";
scan.useDelimiter("\\[|\\{");
try{
// AIRPORTS
result = scan.next();
tempScan = new Scanner(result);
tempScan.useDelimiter(",|\\]");
while(tempScan.hasNext()){
temp = tempScan.next();
sysMan.createAirport(temp);
}
tempScan.close();
/* AIRLINE
* FLIGHT
* FLIGHTSECTION
*/
do{
// AIRLINE (loop<flight & fsection>)
result = scan.next();
sysMan.createAirline(result);
// FLIGHT
result = scan.next();
tempScan = new Scanner(result);
do{
tempScan.useDelimiter(",|\\|");
ArrayList flightInfo = new ArrayList();
while(tempScan.hasNext()){
if(tempScan.hasNextInt()){
flightInfo.add(tempScan.nextInt());
} else {
flightInfo.add(tempScan.next());
}
}
tempScan.close();
sysMan.createFlight(sysMan.getLastAddedAirline(),(String)flightInfo.get(0), (int)flightInfo.get(1), (int)flightInfo.get(2), (int)flightInfo.get(3), (int)flightInfo.get(4), (int)flightInfo.get(5), (String)flightInfo.get(6), (String)flightInfo.get(7));
// FLIGHTSECTION (loop<itself>)
result = scan.next();
tempScan = new Scanner(result);
tempScan.useDelimiter(",|:|\\]");
ArrayList sectInfo = new ArrayList();
int i = 1;
while(!temp.contains("|")){
if(tempScan.hasNextInt()){
sectInfo.add(tempScan.nextInt());
} else {
temp = tempScan.next();
if(temp.equals(""))
break;
char c = temp.charAt(0);
sectInfo.add(c);
}
if(i == 4){
sysMan.createSection(sysMan.getLastAddedAirline(), sysMan.getLastAddedFlightID(), (char)sectInfo.get(0), (int)sectInfo.get(1), (char)sectInfo.get(2), (int)sectInfo.get(3));
i = 1;
sectInfo = null;
sectInfo = new ArrayList();
continue;
}
i++;
}
}while(!temp.equals("\\s+"));
}while(!temp.contains("\\s+"));
}catch(NullPointerException e){
System.err.println(e);
}
}
I'd rather chunk it down by regexp mathing the outer bounds, have a look, I took it a couple of levels broken.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Tokeni {
static String yolo = "[DEN,NYC,SEA,LAX]{AMER["
+ "AA1|2018,10,8,16,30|DEN|LAX[E:200:S:4,F:500:S:2],"
+ "AA2|2018,8,9,7,30|LAX|DEN[E:200:S:5,F:500:S:3]],"
+ "UNTD[UA21|2018,11,8,12,30|NYC|SEA[E:300:S:6,F:800:S:3],"
+ "UA12|2018,8,9,7,30|SEA|DEN[B:700:S:5, F:1200:S:2]]}";
public static void main(String[] args) {
Matcher airportCodesMatcher = Pattern.compile("\\[(.*?)\\]").matcher(yolo);
airportCodesMatcher.find();
String[] airportCodes = airportCodesMatcher.group(1).split(",");
Matcher airLinesMatcher = Pattern.compile("\\{(.*?)\\}").matcher(yolo);
airLinesMatcher.find();
String airLinesStr = airLinesMatcher.group(1);
System.out.println(airLinesStr);
Pattern airLinePattern = Pattern.compile("\\D+\\[(.*?)\\]\\]");
Matcher airLineMatcher = airLinePattern.matcher(airLinesStr);
while( airLineMatcher.find() ) {
String airLineStr = airLineMatcher.group(0).trim();
if(airLineStr.startsWith(",")) {
airLineStr = airLineStr.substring(1, airLineStr.length()).trim();
}
System.out.println(airLineStr);
Matcher airLineNameMatcher = Pattern.compile("[A-Z]+").matcher(airLineStr);
airLineNameMatcher.find();
String airLineName = airLineNameMatcher.group(0).trim();
System.out.println(airLineName);
airLineStr = airLineStr.substring(airLineStr.indexOf("[")+1, airLineStr.length());
Matcher airLineInfoMatcher = Pattern.compile("\\D+(.*?)\\]").matcher(airLineStr);
while(airLineInfoMatcher.find()) {
String airLineInfoStr = airLineInfoMatcher.group(0).trim();
if(airLineInfoStr.startsWith(",")) {
airLineInfoStr = airLineInfoStr.substring(1, airLineInfoStr.length()).trim();
}
System.out.println(airLineInfoStr);
}
}
}
}

How do you send an array to an arraylist?

I am have trouble creating an array or object(with multiple fields) and sending it to an array-list. Any help would be greatly appreciated. I have spent hours looking through every video on YouTube with the words object and array-list in them and have been unable to find much help.
The program needs to prompt the user to pick a option (1. AddItem) then prompt the user for the name and format (dvd, vhs) and save multiple objects with these variables in an array-list. I either keep having the location where it is saved in memory returned to me or instead of multiple objects one large object is created.
Library:
import java.util.Scanner;
import java.util.ArrayList;
public class Library {
static ArrayList<Object> items = new ArrayList<Object>();
static int menuOption;
static Scanner scan = new Scanner(System.in);
public static void main(String args[]) {
String title, format;
boolean right = false;
do{
displayMenu();
if (menuOption == 1){
System.out.println("Enter Title: ");
title = scan.next();
System.out.println("Enter format: ");
format = scan.next();
addNewItem(title, format);
} else {System.out.println(items);
}
} while (!right);
}
static int displayMenu(){
System.out.println("Menu: ");
System.out.println("1. Add New Item");
menuOption = scan.nextInt();
return menuOption;
}
static void addNewItem(String title, String format){
MediaItem b = new MediaItem();
b.setTitle(title);
b.setFormat(format);
items.add(b);
}
}
MediaItem:
public class MediaItem {
String title;
String format;
MediaItem(){
title = null;
format = null
}
MediaItem(String title, String format){
title = new String();
format = new String();
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
}
The program will run if you:
1 - Change the line
static ArrayList<Object> items = new ArrayList<Object>();
to
static ArrayList<MediaItem> items = new ArrayList<MediaItem>();
2 - Change the line
System.out.println( items );
to
for ( MediaItem mi : items )
{
System.out.println( mi.getTitle() + ", " + mi.getFormat() );
}
3 - Insert a ";" at the end of the line
format = null
I did it here and it worked.
I either keep having the location where it is saved in memory returned to me
I am guessing you ran into this when you tried to either use System.out.println() to print a MediaItem, or you otherwise tried to automatically convert an object to a string. Whatever approach you took when you were seeing the memory addresses is probably the right way to do it, your problem was only in your displaying of the data.
Consider:
MediaItem item = ...;
System.out.println(item);
By default, Java doesn't know how to convert arbitrary objects to strings when you do stuff like that, and so it just spits out the class name and memory address. You either need to print the fields separately (e.g. Java knows how to display a String already), like:
System.out.println("Title: " + item.getTitle() + " Format: " + item.getFormat());
Or you can override toString() (declared in Object) to provide a custom string conversion:
class MediaItem {
...
#Override public String toString () {
return "Title: " + title + " Format: " + format;
}
}
And then you can print it directly:
System.out.println(item);
It is the default base implementation of Object.toString() that produces those strings with the memory address in them.
Based on your description, I'm guessing you had a roughly working implementation but ran into this issue and ended up changing around (and breaking) a bunch of other unrelated things to try and fix it.

How to replace words with Parallel arrays

Hello i am new to this forum. I am fairly new to Java. I am trying to convert USA to UK words so that when i input a sentence containing any of the USA words, the output will be will be the sentence but replaced with UK words. This is my attempt:
import javax.swing.JOptionPane;
public class PArraystest
{
public static void main(String [] arg)
{
String[] wordUSA = {"Cell", "Elevator", "Fries", "Gasoline", "Faucet"};
String[] wordUK = {"Mobile", "Lift", "Chips", "Petrol", "Tap"};
String changeUK = "";
String sent;
sent = JOptionPane.showInputDialog("What name do you want to search for?");
for (int i = 0; i < wordUSA.length; i++)
{
if (sent.contains(wordUSA[i]))
{
sent.replace((wordUK)[i],(wordUSA)[i]);
//break;
}
}
//if (changeUK.equals(""))
//System.out.println(" was not found.");
//else
System.out.println(sent);
}
}
Two things:
You need to use assign the string returned from replace to sent again, or sent will be unchanged`.
The replace method is public String replace(char oldChar, char newChar), so the oldChar US word should come first, followed by the UK word.
This is the correct line: sent = sent.replace(wordUSA[i],wordUK[i]);
The replace method returns a new String with the replaced text:
//sent.replace((wordUK)[i],(wordUSA)[i]);
sent = sent.replace((wordUK)[i],(wordUSA)[i]);
Two problems:
First, you should assign the replaced string back to sent.
Second, you should use replaceAll instead of replace.
There's a whole framework of functionality devoted to this in Java called internationalizaion (i18n)
While the sample below is primarily for generation origianlly I thought I'd point it out because you could probably devise how to run it in reverse as well.
Here's a snippet that shows the proper way to go about this:
http://docs.oracle.com/javase/tutorial/i18n/intro/after.html
(all code below is theirs and not my own)
Note that to run this you'll need the resource files from the site or the versions I have provided below from the site
import java.util.*;
public class I18NSample {
static public void main(String[] args) {
String language;
String country;
if (args.length != 2) {
language = new String("en");
country = new String("US");
} else {
language = new String(args[0]);
country = new String(args[1]);
}
Locale currentLocale;
ResourceBundle messages;
currentLocale = new Locale(language, country);
messages = ResourceBundle.getBundle("MessagesBundle", currentLocale);
System.out.println(messages.getString("greetings"));
System.out.println(messages.getString("inquiry"));
System.out.println(messages.getString("farewell"));
}
}
MessagesBundle.properties:
greetings = Hello.
farewell = Goodbye.
inquiry = How are you?
MessagesBundle_en_US.properties:
greetings = Hello.
farewell = Goodbye.
inquiry = How are you?
MessagesBundle_fr_FR.properties:
greetings = Bonjour.
farewell = Au revoir.
inquiry = Comment allez-vous?

Extracting data from a collection in Java

I have a csv dataset like this:
A, 10, USA
B,30, UK
C,4,IT
A,20,UK
B,10,USA
I want to read this csv lines and provide the following output:
A has ran 30 miles with average of 15.
B has ran 30 miles with average of 20.
C has ran 4 miles with average of 4.
I want to achieve this in Java. I have done this in C# by using Linq:
var readlines = File.ReadAllLines(filename);
var query = from lines in readlines
let data = lines.Split(',')
select new
{
Name = data[0],
Miles = data[1],
};
var values = query.GroupBy(x => new {x.Name}).Select(group => new { Person = group.Key, Events = group.Sum(g =>Convert.ToDouble(g.Miles)) ,Count = group.Count() });
I am looking to do this in Java, and I am not sure if I can do this without using any third party library or not? Any ideas?
So far, my code looks like this in Java:
CSVReader reader = new CSVReader(new FileReader(filename));
java.util.List<String[]> content = reader.readAll();
String[] row = null;
for(Object object:content)
{
row = (String[]) object;
String Name = row[0];
String Miles = row[1];
System.out.printf("%s has ran %s miles %n",Name,Miles);
}
reader.close();
}
I am looking for a nice way to get the total milage value for each name to calculate for the average.
As a C# developer, it is hard sometimes not to miss the features of linq. But as Farlan suggested you could do something like this:
CSVReader reader = new CSVReader(new FileReader(filename));
java.util.List<String[]> content = reader.readAll();
Map<String, Group> groups = new HashMap<>();
for(String[] row : content)
{
String Name = row[0];
String Miles = row[1];
System.out.printf("%s has ran %s miles %n", Name, Miles);
if (groups.containsKey(Name)){
groups.get(Name).Add(Double.valueOf(Miles));
} else {
Group g = new Group();
g.Add(Double.valueOf(Miles));
groups.put(Name, g);
}
}
reader.close();
for (String name : groups.keySet())
{
System.out.println(name + " ran " + groups.get(name).total() + " with avg of " + groups.get(name).average());
}
}
class Group {
private List<Double> miles;
public Group()
{
miles = new ArrayList<>();
}
public Double total(){
double sum = 0;
for (Double mile : miles)
{
sum += mile;
}
return sum;
}
public Double average(){
if (miles.size() == 0)
return 0d;
return total() / miles.size();
}
public void Add(Double m){
miles.add(m);
}
}
Use Java's BufferedReader class:
BufferedReader in = new BufferedReader(new FileReader("your.csv"));
String line;
while ( (line = in.readLine()) != null) {
String [] fields = line.split(",");
System.out.println(fields[0] + " has ran " + fields[1] + " miles with average " + fields[2]);
}
There are quite a few ways to do this, some long-winded approaches, some shorter. The issue is that Java can be very verbose for doing simple tasks, so the better approaches can be a bit uglier.
The example below shows you exactly how to achieve this, par the printing. Bear in mind however, it might not be the best approach but I feel its more of the easier ones to read and comprehend.
final File csvFile = new File("filename.csv");
final Scanner reader = new Scanner(csvFile);
final Map<String, Integer> info = new HashMap<>(); //Store the data
//Until there is are no more lines, continue
while (reader.hasNextLine()) {
final String[] data = reader.nextLine().split(","); // data[0] = A. [1] = 10. [2] = USA
final String alpha = data[0];
if (!info.containsKey(alpha)) {
info.put(alpha, Integer.parseInt(data[1]));
} else {
int miles = info.get(alpha);
info.put(alpha, miles + Integer.parseInt(data[1]));
}
}
reader.close();
The steps involved are simple:
Step 1 - Read the file.
By passing a File into the Scanner object, you set the target parsing to the File and not the console. Using the very neat hasNextLine() method, you can continually read each line until no more exist. Each line is then split by a comma, and stored in a String array for reference.
Step 2 - Associating the data.
As you want to cumulatively add the integers together, you need a way to associate already passed in letters with the numbers. A heavyweight but clean way of doing this is to use a HashMap. The Key which it takes is going to be a String, specifically A B or C. By taking advantage of the fact the Key is unique, we can use the O(1) containsKey(String) method to check if we've already read in the letter. If its new, add it to the HashMap and save the number with it. If however, the letter has been seen before, we find the old value, add it with the new one and overwrite the data inside the HashMap.
All you need to do now is print out the data. Feel free to take a different approach, but I hope this is a clear example of how you CAN do it in Java.
Maybe you could try this Java library: https://code.google.com/p/qood/
It handles data without any getter/setters, so it's more flexible than LINQ.
in your case, file "D:/input.csv" has 3 columns:
NAME,MILES,COUNTRY
A, 10, USA
B,30, UK
C,4,IT
A,20,UK
B,10,USA
the query code would be:
final QModel raw = QNew.modelCSV("D:/input.csv")
.debug(-1);//print out what read from CSV
raw.query()
.selectAs("OUTPUT",
"CONCAT(NAME,' has ran ',SUM(MILES),' miles with average of ',MEAN(MILES),'.')")
.groupBy("NAME")
.result().debug(-1)//print out the result
.to().fileCSV("D:/output.csv", "UTF-8");//write to another CSV file

Categories

Resources