I am working on a simple project in which a tab delimited text file is read into a program.
My problem:
When reading the text file there are regularly empty data spaces. This lack of data is causing an unexpected output. For lines that do not have data in the token[4] position all data read is ignored and "4" is displayed when I run a System.out.println(Just a test that the data is being read properly). When I incorporate a value in the token[4] position the data reads fine. It is not acceptable that I input a value in the token[4] position. See below for file and code.
2014 Employee Edward Rodrigo 6500
2014 Salesman Patricia Capola 5600 5000000
2014 Executive Suzy Allen 10000 55
2015 Executive James McHale 12500 49
2015 Employee Bernie Johnson 5500
2014 Salesman David Branch 6700 2000000
2015 Salesman Jonathan Stein 4600 300000
2014 Executive Michael Largo 17000 50
2015 Employee Kevin Bolden 9200
2015 Employee Thomas Sullivan 6250
My code is:
// Imports are here
import java.io.*;
import java.util.*;
public class EmployeeData {
public static void main(String[] args) throws IOException {
// Initialize variables
String FILE = "employees.txt"; // Constant for file name to be read
ArrayList<Employee> emp2014; // Array list for 2014 employees
ArrayList<Employee> emp2015; // Array list for 2015 employees
Scanner scan;
// Try statement for error handling
try {
scan = new Scanner(new BufferedReader(new FileReader(FILE)));
emp2014 = new ArrayList();
emp2015 = new ArrayList();
// While loop to read FILE
while (scan.hasNextLine()) {
String l = scan.nextLine();
String[] token = l.split("\t");
try {
String year = token[0];
String type = token[1];
String name = token[2];
String monthly = token[3];
String bonus = token[4];
System.out.println(year + " " + type + " " + name + " " + monthly + " " + bonus);
} catch (Exception a) {
System.out.println(a.getMessage());
}
}
} catch(Exception b) {
System.out.println(b.getMessage());
}
}
}
The output I receive for lines with "Employee" returns in an unexpected way.
Output:
run:
4
2014 Salesman Patricia Capola 5600 5000000
2014 Executive Suzy Allen 10000 55
2015 Executive James McHale 12500 49
4
2014 Salesman David Branch 6700 2000000
2015 Salesman Jonathan Stein 4600 300000
2014 Executive Michael Largo 17000 50
4
4
BUILD SUCCESSFUL (total time: 0 seconds)
I tried to use an if-then to test for null value in token[4] position but that didn't really help me. I've done quite a bit of searching with no success.
I am still very new to the programming world, so please pardon my coding inefficiencies. Any support and general feedback to improve my skills is greatly appreciated!
Thank you,
Bryan
Java Devil is right that the underlying issue because of an ArrayOutOfBoundsException. But it's also worth exploring why you didn't see that. As we discussed in the comments your "Try statement for error handling" is in fact not handling your errors at all, instead it is suppressing them, which is generally a poor plan as it allows your program to continue running even after your assumption (that it works correctly) has been violated.
Here's a slightly cleaned up version of your code. The underlying problem that causes the ArrayOutOfBoundsException is still there, but the issue would be immediately apparent if you'd structured your code this way instead. There's a few comments calling out issues inline.
public class EmployeeData {
// constants should be declared static and final, and not inside main
private static final String FILE = "employees.txt";
// If you have an exception and you don't know how to handle it the best thing
// to do is throw it higher and let the caller of your method decide what to do.
// If there's *nothing* you want to do with an exception allow main() to throw
// it as you do here; your program will crash, but that's a good thing!
public static void main(String[] args) throws IOException {
// Notice the <> after ArrayList - without it you're defining a "raw type"
// which is bad - https://stackoverflow.com/q/2770321/113632
ArrayList<Employee> emp2014 = new ArrayList<>();
ArrayList<Employee> emp2015 = new ArrayList<>();
// A try-with-resources block automatically closes the file once you exit the block
// https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
try (Scanner scan = new Scanner(new BufferedReader(new FileReader(FILE)))) {
while (scan.hasNextLine()) {
String l = scan.nextLine();
String[] token = l.split("\t");
// The code below this line assumes that token has at least five indicies;
// since that isn't always true you need to handle that edge case before
// accessing the array indicies directly.
String year = token[0];
String type = token[1];
String name = token[2];
String monthly = token[3];
String bonus = token[4];
System.out.println(year + " " + type + " " + name + " " + monthly + " " + bonus);
}
}
}
}
This is happening because you are actually getting an ArrayOutOfBoundsException and the message for that is '4'. Because the index of 4 is greater than the length of the array. You should put in your catch statement b.printStackTrace() as this will give you greater details when ever the caught exception occurs.
You can get around this by adding the following:
String bonus = "";
if(token.length > 4)
bonus = token[4];
I have names of 1100 hospitals from NY region. I need to find the address of these hospitals from google. I am looking for some script which I can use to supply all these hospital name and it could return me with an address. The script could return a simple google search result.
Input format:
Hospital Name
Center for Ambulatory Surgery
Genetic Diagnostic Labs Inc
Desired output format:
Hospital Name Hospital Address
Center for Ambulatory Surgery 3112 Sheridan Dr, Amherst, NY 14226
Genetic Diagnostic Labs Inc 490 Delaware Ave, Buffalo, NY 14202
A solution with google Places API, but the results may be not very accurate:
http://codepen.io/anon/pen/JogeyV?editors=101
var NY_latlng = new google.maps.LatLng(40.828624, -73.898605);
map = new google.maps.Map(document.getElementById('map-canvas'), {
center: NY_latlng,
zoom: 15
});
var hospitals = [];
var hospitals_names = ["Center for Ambulatory Surgery","Genetic Diagnostic Labs Inc"];//insert your full list here
var service = new google.maps.places.PlacesService(map);
hospitals_names.forEach( function(name ){
service.textSearch(
{
query: name,
location: NY_latlng,
radius: 50000, //in meter
},function(results,status){
if (status == google.maps.places.PlacesServiceStatus.OK){
var hospital= { name: name, addresses: []};
$('#address-list').append("<h2>"+name+"</h2><ul></ul>");
for (var i = 0; i < results.length; i++) {
hospital.addresses.push( results[i].formatted_address );
$('#address-list > ul').append("<li>"+results[i].formatted_address);
}
hospitals.push( hospital );
}
});
You can do this in R with the ggmap package, though perhaps not reliably enough to produce the results you want. For instance this attempt to geocode fails:
geocode("Genetic Diagnostic Labs Inc")
Warning message:
geocode failed with status ZERO_RESULTS, location = "Genetic Diagnostic Labs Inc"
So to illustrate a solution, I appended " NY" to the Google searches:
library(ggmap)
hospital_names <- c("Center for Ambulatory Surgery", "Genetic Diagnostic Labs Inc")
address_vec <- lapply(hospital_names, function(x) revgeocode(as.numeric(geocode(paste(x,", NY")))))
result <- data.frame(name = hospital_names, address = unlist(address_vec))
Result:
result
name address
1 Center for Ambulatory Surgery 426 Union Road, West Seneca, NY 14224, USA
2 Genetic Diagnostic Labs Inc City Hall Park Path, New York, NY 10007, USA
But these are not the addresses you specified - you may need to refine your inputs.
I'm a Java noob so please bear with me.
I'm having an issue with a java project I have to complete. We have to sort a list of 10,000 customer transactions, pick the top three customers that spent the most, then give five random customers gift cards, five of them starting at $20 and ending at $100, increasing in $20 increments. So far I have the following:
public static void main(String[] args) throws IOException {
BufferedReader inputStream = new BufferedReader (new FileReader("Transactions.txt"));
BufferedWriter outputStream = new BufferedWriter (new FileWriter("output.txt"));
Scanner trans = null;
try {
trans = new Scanner(new BufferedReader(new FileReader("Transactions.txt")));
trans.useDelimiter("s*");
while (trans.hasNext()) {
System.out.println(trans.next());
}
}
finally {
if (trans !=null) {
trans.close();
I'm confused as to how I would put this information into an OrderedList so it'll sort them in ascending order according to the amount they spent.
EDIT: Here are some lines from the transaction.txt file:
Order # Date First name Middle Initial Last name Address City State Zip Email Transaction Amount
1 8/26/2012 Kristina H Chung 947 Martin Ave. Muncie CA 46489 khchung#business.com $593
2 11/16/2012 Paige H Chen 15 MainWay Rd. Dallas HI 47281 phchen#business.com $516
3 11/10/2012 Sherri E Melton 808 Washington Way Brazil CA 47880 semelton#business.com $80
4 9/20/2012 Gretchen I Hill 56 Washington Dr. Atlanta FL 47215 gihill#business.com $989
5 3/11/2012 Karen U Puckett 652 Maplewood Ct. Brazil FL 46627 kupuckett#business.com $826
My apologies, but I have no idea how to make this look neat.
I have a json which has a number of nested JSONARRAY. here is the snippet.
{
"location": [
{
"name": "Perth",
"conferencelocation": [
{
"locationname":"Stage 1" ,
"guests": [
{
"guestid":"4074513426041094",
"guestname":"Keegan Connor Tracy",
"time":"9am",
"largeimg":"http://ozcomiccon.com/images/banner/Keegan.jpg",
"smallimg":"http://ozcomiccon.com/images/banner/Keeganresized.jpg",
"biotext": "Born in Windsor, Ontario, Canada, Tracy attended Wilfrid Laurier University in Waterloo, Ontario, Canada, where she orginally studied business. She later switched to psychology. She spent a year in Europe working in Dublin, Paris and Nice, where she was supposed to be completing her 4th year of study. She later returned to WLU to finish her degree. She moved to Vancouver, B.C. where she has had all of her acting jobs.",
"autographs":"$30 each (an 8x10 photograph will be included with each signature, or you may choose to have an appropriate personal item signed).",
"photographs":"Photo with Keegan $40.",
"genre":"acting",
"links": [
{"linkname":"Twitter", "url":"https://twitter.com/keegolicious" },
{"linkname":"IMDB", "url":"http://www.imdb.com/name/nm0870535/" }
]
},
{
"guestid":"1054713366041913",
"guestname":"Matthew Clark",
"time":"10am",
"largeimg":"http://ozcomiccon.com/images/banner/matthewclark.jpg",
"smallimg":"http://ozcomiccon.com/images/banner/matthewclarkresized.jpg",
"biotext": "Matthew Clark is a comic book artist living and working in Portland, Oregon. Having worked on art of some of the most well-known DC characters in comic book history, he recently did pencils for DC’s latest version of the Doom Patrol. Matthew is currently working on Ghost Rider for Marvel Comics, with whom he has signed an exclusive two-year deal.<br /><br />Matthew has lived in Portland for the past 13 years, just above an art gallery in the heart of downtown. He loves to walk around this fair city (mainly because he sold his car and needed to force himself to exercise). He’s a native Oregonian and that’s saying something. For the past 11 years he’s met Greg Rucka for coffee every Wednesday pretty much without fail at the same place (we pretty much carved our names in the table). Matthew was also one of the original founders of Mercury Studio (now Periscope Studio); he got his start at Studiosaurus.<br /><br />He still reads comics, loves what he does, and works very hard. Loves to meet new people, but is really quiet (and has great hair).",
"autographs":"Complimentary at guest's discretion.(Twitter)",
"photographs":"",
"genre":"comic",
"links": [
{"linkname":"Website", "url":"http://www.matthewclarkartist.com/" },
{"linkname":"Twitter", "url":"https://twitter.com/emceeartist" }
]
}
]
},
{
"locationname":"Stage 2" ,
"guests": [
{
"guestid":"106146633306036834",
"guestname":"Sean Williams",
"time":"8am",
"largeimg":"http://ozcomiccon.com/images/banner/seanwilliams.jpg",
"smallimg":"http://ozcomiccon.com/images/banner/seanwilliamsresized.jpg",
"biotext": "Sean Williams was born in the dry, flat lands of South Australia, where he still lives with his wife and family. He has been called many things in his time, including “the premier Australian speculative fiction writer of the age†(Aurealis), the “Emperor of Sci-Fi†(Adelaide Advertiser), and the “King of Chameleons†(Australian Book Review) for the diversity of his output. That award-winning output includes thirty-five novels for readers all ages, seventy-five short stories across numerous genres, the odd published poem, and even a sci-fi musical.<br /><br />He is a multiple recipient of the Aurealis and Ditmar Awards in multiple categories and has been nominated for the Philip K. Dick Award, the Seiun Award, and the William Atheling Jr. Award for criticism. He received the “SA Great†Literature Award in 2000 and the Peter McNamara Award for contributions to Australian speculative fiction in 2008.<br /><br />On the sci-fi front, he is best-known internationally for his original award-winning space opera series as well as several novels set in the Star Wars universe, many co-written with fellow-Adelaidean Shane Dix. These include the Astropolis, Evergence, Orphans and Geodesica series, and the computer game tie-in The Force Unleashed–the first such adaptation ever to debut at #1 on the New York Times bestseller list. A series for young readers, The Fixers, pitted an increasingly lost protagonist against zombies, cyborgs, and vampires across numerous universes. His most recent releases in the Star Wars universe are The Old Republic: Fatal Alliance and The Force Unleashed II.",
"autographs":"Complimentary at guest's discretion.",
"photographs":"",
"genre":"comic",
"links": [
{"linkname":"website", "url":"http://www.seanwilliams.com" }
]
},
{
"guestid":"17148603639603876",
"guestname":"Richard Dean Anderson",
"time":"10am",
"largeimg":"http://ozcomiccon.com/images/banner/richarddeananderson.jpg",
"smallimg":"http://ozcomiccon.com/images/banner/richarddeanandersonresized.jpg",
"biotext": "Richard Dean Anderson is probably best known as MacGyver, the clever and inventive nonviolent hero who solved problems in his own unique way for seven successful seasons on ABC. In his roles before and since, this gifted actor has continued to demonstrate his remarkable talent and versatility.<br /><br />Richard was born on January 23, 1950 in Minneapolis, Minnesota. His father, Stuart Anderson, taught English, drama, and humanities at a local high school, and is an accomplished jazz bassist. His mother, Jocelyn, is an artist, talented in both painting and sculpture. Richard is the eldest of four sons. He and his brothers, Jeffrey Scott, Thomas John, and James Stuart, grew up in the Minneapolis suburb of Roseville, where Richard developed early interests in sports, the arts, music, and acting.<br /><br />Like many boys growing up in Minnesota, Richard dreamed of becoming a professional hockey player. However, at the age of 16, he broke both arms, in separate accidents three weeks apart, while playing in high school hockey games. He put aside his dreams of playing professionally, though he still harbors a deep love for the sport. Richard talks of his restlessness growing up, his early desire to explore, and his adventures hitchhiking and hopping freight trains. At the age of 17, he took a 5641 mile bicycle trip from his home in Minnesota through Canada and Alaska, an experience which was sparked by his sense of adventure and discovery, but which also gave him a more centered sense of direction.",
"autographs":"Autograph from Richard $50.",
"photographs":"Photograph with Richard $80. SG1 double shot with Richard and Teryl Rothery $150. SG1 triple shot with Richard, Teryl Rothery and Corin Nemec $200.",
"genre":"acting",
"links": [
{"linkname":"Website", "url":"http://www.rdanderson.com/" },
{"linkname":"Twitter", "url":"https://twitter.com/andersonrdean" }
]
}
]
}
]
}
]
I have object class named Name, and I want to put all the data of the name(perth) jsonobject as a single object of the Name class. But it is not adding data in the arraylist correctly, more clearly the guestid, guestname etc tag values are being saved but overwrites the previous one. Here is my parsing code:
public ArrayList<Guest> parseInitiator() throws ClientProtocolException,
IOException, JSONException {
InputStream is = new FileInputStream(new File(Url));
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
String mResponse = new String(buffer);
JSONObject first = new JSONObject(mResponse);
JSONArray firstarray = first.getJSONArray("location");
ArrayList<Guest> parsedData = new ArrayList<Guest>();
for (int i = 0; i < firstarray.length(); i++) {
JSONObject jonj = firstarray.getJSONObject(i);
name = jonj.getString("name");
JSONArray confarray = jonj.getJSONArray("conferencelocation");
locationname = new String[confarray.length()];
for (int j = 0; j < confarray.length(); j++) {
JSONObject conobbj = confarray.getJSONObject(j);
locationname[j] = conobbj.getString("locationname");
JSONArray guestarray = conobbj.getJSONArray("guests");
guestid= new String[guestarray.length()];
guestname= new String[guestarray.length()];
time= new String[guestarray.length()];
largeimg= new String[guestarray.length()];
smallimg= new String[guestarray.length()];
biotext= new String[guestarray.length()];
autographs= new String[guestarray.length()];
photographs= new String[guestarray.length()];
genre= new String[guestarray.length()];
for (int k = 0; k < guestarray.length(); k++) {
JSONObject guestobbj = guestarray.getJSONObject(k);
guestid[k] = guestobbj.getString("guestid");
guestname[k] = guestobbj.getString("guestname");
time[k] = guestobbj.getString("time");
largeimg[k] = guestobbj.getString("largeimg");
smallimg[k] = guestobbj.getString("smallimg");
biotext[k] = guestobbj.getString("biotext");
autographs[k] = guestobbj.getString("autographs");
photographs[k] = guestobbj.getString("photographs");
genre[k] = guestobbj.getString("genre");
JSONArray linkar = guestobbj.getJSONArray("links");
arlink= new String[linkar.length()];
arurl= new String[linkar.length()];
for (int l = 0; l < linkar.length(); l++) {
JSONObject linkobj = linkar.getJSONObject(l);
arlink[l] = linkobj.getString("linkname");
arurl[l] = linkobj.getString("url");
}
}
}
parsedData.add(new Guest(name,locationname, guestid, guestname, time, largeimg, smallimg, biotext,
autographs, photographs, genre,arlink, arurl));
}
return parsedData;
}
Can anyone make me clear about the mistake I have made?
So here is my solution:
JSONObject first = new JSONObject(mResponse);
JSONArray locArr = first.getJSONArray("location"); // contains one object
JSONObject locArrObj = locArr.getJSONObject(0); // cotains one "out" array
JSONArray conferenceLocArr = locArrObj.getJSONArray("conferencelocation");
// this array has two objects and each object has array
JSONObject o = null;
JSONArray arr = null;
for (int i = 0; i < conferenceLocArr.length(); i++) {
o = conferenceLocArr.getJSONObject(i); // it has one array
arr = o.getJSONArray("guests");
// do your work with Stage 1 and guests
// and for second object for Stage 2 and guests.
}
I run a small online gaming community and deal with a database of accounts.
The setup is this:
Folder named Accounts
Inside the Accounts directory, there is 200,000+ text files organized by player name. Access to this folder manually is a pain because of the needed RAM to get in and search files. I find this very inconvenient.
I access this directory to send password reminders or for highscores on who has been playing the longest.
Here is an example of an account file. This file is named Falcon.txt
[ACCOUNT]
character-username = Falcon
character-password = falconpassword
[INFO]
character-coordx = 3252
character-coordy = 3432
character-active = yes
character-ismember = 1
character-messages = 5
character-lastconnection = [removed]
character-lastlogin = 2009-11-29
character-energy = 100
character-gametime = 193
character-gamecount = 183
[EQUIPMENT]
character-equip = 0 4724 0
character-equip = 1 1052 0
character-equip = 2 6585 0
character-equip = 3 4151 0
character-equip = 4 4720 0
character-equip = 5 1215 0
character-equip = 6 -1 0
character-equip = 7 4722 0
character-equip = 8 -1 0
character-equip = 9 775 0
character-equip = 10 1837 0
character-equip = 11 -1 0
character-equip = 12 6735 0
character-equip = 13 -1 0
[APPEARANCE]
character-look = 0 1
character-look = 1 1
character-look = 2 2
character-look = 3 3
character-look = 4 5
character-look = 5 2
[STATS]
character-skill = 0 1 0
character-skill = 1 1 0
character-skill = 2 1 0
character-skill = 3 1 0
character-skill = 4 1 0
character-skill = 5 1 0
character-skill = 6 1 0
character-skill = 7 1 0
character-skill = 8 1 0
character-skill = 9 1 0
character-skill = 10 1 0
character-skill = 11 1 0
character-skill = 12 1 0
character-skill = 13 1 0
character-skill = 14 1 0
character-skill = 15 1 0
character-skill = 16 1 0
character-skill = 17 1 0
character-skill = 18 1 0
character-skill = 19 1 0
character-skill = 20 1 0
[ITEMS]
[BANK]
[FRIENDS]
[IGNORES]
[END]
There is a huge database of these and search through the directory in the files for values.
Values I mean by item ID's or IP addresses to find and track other accounts.
However I have a new problem and my development for this is crashing.
As you can see in the file the lines are organized by tabs.
character-equip = 0 4724 1
If I put the value 4724 in my search application, I want it to print out the value 1 tab to the right of the found search result. I want it to print out the value for the found results only, not extra results.
So the search could look like this:
1 "Enter item to find:"
2 "Enter item to find: 4724"
3 "Account Falcon.txt has 1!"
press any key to continue...
Or if there was more quantity of that equipped item
character-equip = 5 1239 102
1. "Enter item to find:"
2. "Enter item to find: 1239"
3. "Account Falcon2.txt has 102!"
press any key to continue...
I simply want to input an item ID, and have it display the value after the found value. The white space is a tab. I have tried doing this and the only successful way of getting any result is to put a tab in between the search term. So if I want to find item 1239 id type this in the cmd line:
Enter item to find:<tab>1239<tab>
It would then search for that and will display the accounts with that item in it. However I still have to individually open up the accounts to find out the quantity of that item. I want the search results to display the quantity of the item if the value is found. However if the value is a quantity and it trys to search one tab over, I want it to either skip it or say zero.
This is what I mean.
character-equip = 0 1024 1239
Enter item to find: 1239
If it hits this account I want to make the search results display a zero if it cannot tab over or view any values in the white space. So it will display as null or zero
Account Falcon3.txt has null!
or
Account Falcon3.txt has 0!
I've attempted to do this but I am unsure how to achieve this.
Here is my code.
import java.io.*;
import java.util.*;
public class ItemDatabase {
public static void main(String args[]) {
System.out.print("Enter item to find: ");
Scanner sc = new Scanner(System.in);
find(sc.nextLine());
}
public static void find(String delim) {
File dir = new File("accounts");
if (dir.exists()) {
String read;
try {
File files[] = dir.listFiles();
for (int i = 0; i < files.length; i++) {
File loaded = files[i];
if (loaded.getName().endsWith(".txt")) {
BufferedReader in = new BufferedReader(new FileReader(loaded));
StringBuffer load = new StringBuffer();
while ((read = in.readLine()) != null) {
load.append(read + "\n");
}
String delimiter[] = new String(load).split(delim);
if(delimiter.length > 1) {
System.out.println("Account " + loaded.getName() + "has " + delimiter[1] + "!");
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("error: dir wasn't found!");
}
}
}
Thanks guys I hope you can help me.
This is simply crying out for a database. If your entire back end is running in a single java process I'd recommend going with something like Apache Derby or H2.
If you'd rather not move to a database, and the main problem is the act of listing all the entries in a single directory, could you split it into a heirarchy. Your Falcon account could then be located in F/FA/Falcon.txt - each directory would then contain a more manageable number of files.
Aside from the need for a database, you could probably implement your solution more intuitively and easily using commandline utilities such as find, grep, etc. or a text-processing language such as perl.
Maybe
grep '[0-9]+\t[0-9]+\t1239' Account_Falcon3.txt
Would return
character-equip = 0 1024 1239
You could then easily see that the value is 0 for that item.
I cannot emphasize enough the need to not write a Java program to do this - you won't do as good a job as the authors of the standard shell utilities. Let's face it, the fact that you are asking this question indicates that you are a newb! :) (We are all newbs depending on the topic).