I'm a beginner, so please don't blast my work so far :)
I'm trying to read in a CSV file and then see if it matches certain commands. Some of the data in the CSV has a period and I think it's messing up when I'm trying to split it. When I try to dump my arrays to see what's there, it always gets cut off after the period. Here is a data sample. Any help would be appreciated. Again I'm a beginner so simplicity would be appreciated.
Sample data
create,Mr. Jones,blah,blah
create,Mrs. Smith,blah,blah
public class TestHarness {
public static void main(String[] args) throws IOException, FileNotFoundException {
Scanner input = new Scanner(new File("C:\\Users\\Ree\\Desktop\\SPR\\commands.txt"));
String[] validCommands = { "create", "move", "useWeapon", "search", "heal" };
boolean proceed = false;
while (!proceed)
{
for (int i = 0; i < validCommands.length; i++)
{
String line = input.next();
String[] nline = line.split (",");
if (nline[0].equals("create"))
{
String soldierName = nline[1];
String soldierType = nline[2];
String weapon = nline[3];
Soldier aSoldier = new Soldier(soldierName,weapon);
System.out.println("Command: "+ nline[0] +","+ soldierName +","+ soldierType+","+ weapon);
if (soldierType.equals("enlisted"))
{
Soldier s = new Enlisted(soldierName,weapon);
System.out.println(s.toString());
}
else if (soldierType.equals("officer"))
{
Soldier s = new Officer(soldierName,weapon);
System.out.println(s.toString());
}
}
else if (nline[0].equals("useWeapon")) {
System.out.print("weapon " + nline[0] + "\n");
}
else if (nline[0].equals("move")) {
System.out.print("move " + nline[0] + "\n");
}
else if (nline[0].equals("search")) {
System.out.print("search " + nline[0] + "\n");
}
else if (nline[0].equals("heal")) {
System.out.print("heal " + nline[0] + "\n");
}
}
}
}
}
Calling Scanner.next will only return the next word (separated by whitespace).
You need to call nextLine to read entire lines at a time.
There are several open source CSV parers available for Java:
http://supercsv.sourceforge.net/
http://commons.apache.org/sandbox/csv/
That was a rather quick mistake, wasn't it?
This is not an answer to your question but a recommendation to use a hash.
First define an interface
public interface InputDance
{
public void dance(String[] input);
}
I recommend that your main routine should be
public static void main(String[] args)
throws IOException, FileNotFoundException{
Scanner input = new Scanner(
new File("C:\\Users\\Ree\\Desktop\\SPR\\commands.txt"));
String line = input.nextLine();
String[] nline = line.split (",");
InputDance inputxn = inputActions.get(nline[0]);
if (inputxn!=null)
inputxn.dance(nline);
}
You would be using a hash to store all the actions outlined by the interface InputDance.
So that your input reading routine would be simplified to
retrieve action from hash of actions
using word0 of input as key.
execute that action
If you have only five types of soldiers, it would ok to place all your logic in one routine.
However, for more than 10 types of personnel, it would be cleaner to place the actions outside the routine.
If you are writing a computer game, or keeping personnel records on a military database, you would frequently encounter enhancement requests to include new personnel types or exceptions to the rule. Then your if-then-else-if chain would become increasingly longer and confusing. Especially when there are special requirements for soldiers dancing to a different tune. Or when your game canvas or personnel database needs to include non-battle units. But, of course, you still need to update the hash in the main class every time you have a new personnel type.
Notice that in my recommendation all your routine would do is to perform the dance(String[]) method. Any complication would be handled by the individual class implementing the dance.
Next define an implementing class
public class SoldierDance
implements InputDance
{
public void dance(String[] nline){
String soldierName = nline[1];
String soldierType = nline[2];
String weapon = nline[3];
System.out.println(
"Command: "+ nline[0] +","+ soldierName +","+ soldierType+","+ weapon);
Soldier s;
if (soldierType.equals("enlisted")){
s = new Enlisted(soldierName,weapon);
}
else if (soldierType.equals("officer")){
s = new Officer(soldierName,weapon);
}
else{
s = new Soldier(soldierName,weapon);
}
System.out.println(s.toString());
}
}
Then define your main class. Notice that the hash is a static instance.
Also, there is a placeholder dance so that when you have a new personnel type, but you don't know what to do with it yet, you just hash the new personnel type to this placeholder dance.
Notice, for example in the "useWeapon" hash key, that an interface can be implemented anonymously too
public class TestHarness
{
static public class PlaceHolderDance
implements InputDance
{
public void dance(String[] nline){
System.out.print("Action=" + nline[0] + "\n");
}
}
static public Hashtable<String, InputDance> inputActions;
// A static enclosure is to execute all the class definition once.
static {
inputActions = new Hashtable<String, InputDance>();
InputDance placeHolderAction = new PlaceHolderDance();
inputActions.put("create", new SoldierDance());
inputActions.put("move", placeHolderAction);
inputActions.put("search", placeHolderAction);
inputActions.put("heal", placeHolderAction);
// Can also anonymously implement an interface
inputActions.put("useWeapon",
new InputDance(){
public void dance(String[] nline){
System.out.print("weapon " + nline[0] + "\n");
}
}
);
}
// The static main method
public static void main(String[] args)
throws IOException, FileNotFoundException{
Scanner input = new Scanner(
new File("C:\\Users\\Ree\\Desktop\\SPR\\commands.txt"));
String line = input.nextLine();
String[] nline = line.split (",");
InputDance inputxn = inputActions.get(nline[0]);
if (inputxn!=null)
inputxn.dance(nline);
}
}
And, if there is a one-one correspondence between a soldier class and its inputdance, you could even implement InputDance in the soldier class and provide the dance method.
Related
I am trying to learn how to utilize Java 8 features(such as lambdas and streams) in my daily programming, since it makes for much cleaner code.
Here's what I am currently working on:
I get a string stream from a local file with some data which I turn into objects later. The input file structure looks something like this:
Airport name; Country; Continent; some number;
And my code looks like this:
public class AirportConsumer implements AirportAPI {
List<Airport> airports = new ArrayList<Airport>();
#Override
public Stream<Airport> getAirports() {
Stream<String> stream = null;
try {
stream = Files.lines(Paths.get("resources/planes.txt"));
stream.forEach(line -> createAirport(line));
} catch (IOException e) {
e.printStackTrace();
}
return airports.stream();
}
public void createAirport(String line) {
String airport, country, continent;
int length;
airport = line.substring(0, line.indexOf(';')).trim();
line = line.replace(airport + ";", "");
country = line.substring(0,line.indexOf(';')).trim();
line = line.replace(country + ";", "");
continent = line.substring(0,line.indexOf(';')).trim();
line = line.replace(continent + ";", "");
length = Integer.parseInt(line.substring(0,line.indexOf(';')).trim());
airports.add(new Airport(airport, country, continent, length));
}
}
And in my main class I iterate over the object stream and print out the results:
public class Main {
public void toString(Airport t){
System.out.println(t.getName() + " " + t.getContinent());
}
public static void main(String[] args) throws IOException {
Main m = new Main();
m.whatever();
}
private void whatever() throws IOException {
AirportAPI k = new AirportConsumer();
Stream<Airport> s;
s = k.getAirports();
s.forEach(this::toString);
}
}
My question is this: How can I optimize this code, so I don't have to parse the lines from the file separately, but instead create a stream of objects Airport straight from the source file? Or is this the extent in which I can do this?
You need to use map() to transform the data as it comes past.
Files.lines(Paths.get("resources/planes.txt"))
.map(line -> createAirport(line));
This will return a Stream<Airport> - if you want to return a List, then you'll need to use the collect method at the end.
This approach is also stateless, which means you won't need the instance-level airports value.
You'll need to update your createAirport method to return something:
public Airport createAirport(String line) {
String airport = line.substring(0, line.indexOf(';')).trim();
line = line.replace(airport + ";", "");
String country = line.substring(0,line.indexOf(';')).trim();
line = line.replace(country + ";", "");
String continent = line.substring(0,line.indexOf(';')).trim();
line = line.replace(continent + ";", "");
int length = Integer.parseInt(line.substring(0,line.indexOf(';')).trim());
return new Airport(airport, country, continent, length);
}
If you're looking for a more functional approach to your code, you may want to consider a rewrite of createAirport so it doesn't mutate line. Builders are also nice for this kind of thing.
public Airport createAirport(final String line) {
final String[] fields = line.split(";");
return new Airport(fields[0].trim(),
fields[1].trim(),
fields[2].trim(),
Integer.parseInt(fields[3].trim()));
}
Throwing it all together, your class now looks like this.
public class AirportConsumer implements AirportAPI {
#Override
public Stream<Airport> getAirports() {
Stream<String> stream = null;
try {
stream = Files.lines(Paths.get("resources/planes.txt"))
.map(line -> createAirport(line));
} catch (IOException e) {
stream = Stream.empty();
e.printStackTrace();
}
return stream;
}
private Airport createAirport(final String line) {
final String[] fields = line.split(";");
return new Airport(fields[0].trim(),
fields[1].trim(),
fields[2].trim(),
Integer.parseInt(fields[3].trim()));
}
}
The code posted by Steve looks great. But there are still two places can be improved:
1, How to split a string.
2, It may cause issue if the people forget or don't know to close the stream created by calling getAirports() method. So it's better to finish the task(toList() or whatever) in place.
Here is code by abacus-common
try(Reader reader = IOUtil.createBufferedReader(file)) {
List<Airport> airportList = Stream.of(reader).map(line -> {
String[] strs = Splitter.with(";").trim(true).splitToArray(line);
return Airport(strs[0], strs[1], strs[2], Integer.valueOf(strs[3]));
}).toList();
} catch (IOException e) {
throw new RuntimeException(e);
}
// Or By the Try:
List<Airport> airportList = Try.stream(file).call(s -> s.map(line -> {
String[] strs = Splitter.with(";").trim(true).splitToArray(line);
return Airport(strs[0], strs[1], strs[2], Integer.valueOf(strs[3]));
}).toList())
Disclosure: I'm the developer of abacus-common.
I have a basic greeting program that is supposed to come up with a response based on the user's input. I am trying to accomplish it using for loops; however, whenever the user replies with the "bad" or "you" values stored in different arrays, the console prints out the same response multiple times. How could this problem be approached?
I'm a noob here, and in java.
I apologize if this answer has been previously answered. I searched but couldn't find.
Thank you for your time.
import java.util.Scanner;
public class Greeter {
public static void main(String[] args) {
String[] greetings = { "well", "good", "great", "awesome", "fabulous" };
String[] bad_greetings = { "bad", "awful" };
String[] responses = { "you", "yourself" };
System.out.println("Hello there, how are you?");
String response;
Scanner scan = new Scanner(System.in);
response = scan.nextLine();
for (String greeting : greetings) {
if (response.contains(greeting)) {
System.out.println("Well, good for you!");
}
for (String b_greet : bad_greetings) {
if (response.contains(b_greet)) {
System.out.println("At least you have me.");
}
}
for (String reply : responses) {
if (response.contains(reply)) {
System.out.println("I'm well, thank you.");
// } else {
// System.out.println("Let's move on then.");
// }
}
}
}
}
}
Change yout Main(). Your problem was that you have bad } for first loop also I recommand you break the cycle (or instead of break use return; from function) cause it is not neccesary to run all cycle if you already find your answer.
public static void main(String[] args) {
String[] greetings = {"well", "good", "great", "awesome", "fabulous"};
String[] bad_greetings = {"bad", "awful"};
String[] responses = {"you", "yourself"};
System.out.println("Hello there, how are you?");
String response;
Scanner scan = new Scanner(System.in);
response = scan.nextLine();
for (String greeting : greetings) {
if (response.contains(greeting)) {
System.out.println("Well, good for you!");
break;//return;
}
}
for (String b_greet : bad_greetings) {
if (response.contains(b_greet)) {
System.out.println("At least you have me.");
break;//return;
}
}
for (String reply : responses) {
if (response.contains(reply)) {
System.out.println("I'm well, thank you.");
break;//return;
// } else {
// System.out.println("Let's move on then.");
// }
}
}
}
Milkmaid's answer is correct. To further elaborate on his response is that you are going to print your response 5 times (one for each item in your "greetings" array).
I can think of three options to solve your problem:
keep what you have now, but use a break; statement to discontinue the for loop.
Split up your for loops as Milkmaid did and include the break.
Change your array to a list instead which has a built in "contains" method.
How can I test if an array contains a certain value?
option 3 would be the cleanest :) You can convert it on the fly or just start with a list altogether. Seems like your program can just start with a list though.
You can try below
public static void main(String[] args) {
String[] greetings = {"well", "good", "great", "awesome", "fabulous"};
String[] bad_greetings = {"bad", "awful"};
String[] responses = {"you", "yourself"};
System.out.println("Hello there, how are you?");
String response;
Scanner scan = new Scanner(System.in);
response = scan.nextLine();
if(Arrays.asList(greetings).contains(response)){
System.out.println("Well, good for you!");
break;//return;
}
if(Arrays.asList(bad_greetings).contains(response)){
System.out.println("At least you have me.");
break;//return;
}
if(Arrays.asList(responses).contains(response)){
System.out.println("I'm well, thank you.");
break;//return;
}
// } else {
// System.out.println("Let's move on then.");
// }
}
I am trying to understand why my code is not writing the output to the textfile as I expect it to work. My program takes a filename as a command line argument, and prints some text to the file as well as the screen. It is a bit more complicated since it uses classes and objects to demonstrate how objects work. Can anyone help decipher why it is not writing to the file? Here's my code:-
public class Mamoonp3test {
public static void main(String[] args) throws Exception {
//Create array of 10 guitar (Mamoonp3) objects
final int NUMBER_OF_INSTANCES = 10;
Mamoonp3[] objectNames = new Mamoonp3[NUMBER_OF_INSTANCES];
try
{
String fileName = new String(args[0]);
for(int i=0; i<NUMBER_OF_INSTANCES; i++) {
objectNames[i] = new Mamoonp3(FileName);
System.out.println("This is guitar number: " + i);
objectNames[i].tuneGuitar();
objectNames[i].playGuitar();
objectNames[i].displayAcronym();
objectNames[i].stopGuitar();
System.out.println("---------------------------");
}
}
catch (Exception e)
{
System.out.println("please provide an input file");
System.out.println("Usage: java Mamoonp3test filename.txt");
}
}
}
import java.io.*;
public class Mamoonp3 {
final int NUMBER_OF_STRINGS = 6;
char[] stringNames = {'E','A','D','G','B','E'};
int[] stringNumbers = {6,5,4,3,2,1};
String[] stringPitch = {"Sixth","Fifth","Fourth","Third","Second","First"};
boolean isTuned;
boolean isPlaying;
String stringAcronym = new String("Even After Dinner Giant Boys Eat");
//create a PrintWriter for output
PrintWriter output;
public Mamoonp3(String fileName) throws Exception{
isTuned = false;
isPlaying = false;
// create target file
File targetFile = new File(fileName);
//create a PrintWriter for output
output = new PrintWriter(targetFile);
}
public void tuneGuitar() {
System.out.println("The guitar is now tuned.");
for (int i=0; i<NUMBER_OF_STRINGS; i++) {
System.out.println(stringNames[i] + " is string number " + stringNumbers[i] + " and ranked " + stringPitch[i] + " in pitch");
output.print(stringNames[i] + " is string number " + stringNumbers[i] + " and ranked " + stringPitch[i] + " in pitch");
output.close();
}
}
public void playGuitar() {
System.out.println("The guitar is now playing.");
output.print("The guitar is now playing.");
output.close();
}
public void stopGuitar() {
System.out.println("The guitar is now stoped.");
output.print("The guitar is now stoped.");
output.close();
}
public void displayAcronym() {
System.out.println("Always remember your string names!");
System.out.println("Heres a reminder: " + stringAcronym);
output.print("Always remember your string names!");
output.print("Heres a reminder: " + stringAcronym);
output.close();
}
}
You're setting the File of an object that you then do nothing with, that you're not writing with,
Mamoonp3 newObject = new Mamoonp3(fileName);
... and not setting the File in objects that you try to write with. Check which constructors you are using: every Manoop3 object created in the for loop. To see that this is so, check which constructors you're using
I suggest that you change your approach entirely.
Get all file input and output out of your Mamoonp3 class.
Instead, that class should concern itself with representing the state of the musical instrument, and nothing else.
Give the class a decent toString() override method.
I & O should go elsewhere in a separate class of its own.
Give your I&O class a method that allows you to pass Mamoonp3 objects into it so that they can be written.
As an aside, you almost never would use new String(anything). Just use args[0].
Always close your PrintWriter when you are done writing. This is likely causing your error.
Edit
Possibly another way to solve this:
Create a PrintWriter object in the main method.
Give your Manoop3 class a PrintWriter field and a constructor that takes this PrintWriter and sets its field with it.
Write with the PrintWriter in Manoop3, but don't close it.
Then close the PrintWriter in the main method when all Manoop3 objects have completed their use of it.
Let me preface this by saying that I'm extremely new to java. This is my eighth week in the class and I'm stuck on a project. Here is what I have so far:
import java.io.*;
public class Guitar {
// Initialize variables
boolean isPlaying;
boolean inTune;
char[] guitStrings = {'D', 'G', 'C', 'A'}; // Guitar strings
int numOfStrings = 4; // Number of strings the guitar has.
public void Guitar(){
isPlaying = false; // Guitar is not playing by default.
inTune = false; // Guitar is not tuned by default.
System.out.println("The guitar is not tuned and is not playing.");
}
public void isPlaying(){
System.out.println("Your guitar is now playing!");
isPlaying = true; // Set guitar to playing
}
public void inTune(){
System.out.println("Your guitar is now tuned!");
inTune = true; // Set guitar to tuned.
}
public void stopPlaying(){
isPlaying = false; // Set isPlaying to false.
System.out.println("Your guitar has finished playing!");
}
public void notes(){
System.out.println("The guitar has played a total of " + numOfStrings +
" strings and they are: " + guitStrings[0] + "," + guitStrings[1] + ","
+ guitStrings[2] + "," + guitStrings[3]);
}
public static void main(String[] args) throws IOException{
java.io.File file = new java.io.File("guitartest.txt");
if(file.exists()){
System.out.println("File already exists!");
System.exit(1);
}
// Create a file
java.io.PrintWriter output = new java.io.PrintWriter(file);
Guitar[] guit = new Guitar[10];
for (int i = 0; i < guit.length; i++){
guit[i] = new Guitar();
guit[i].Guitar();
guit[i].inTune();
guit[i].isPlaying();
guit[i].notes();
guit[i].stopPlaying();
}
}
}
This program does everything I need it to do, but we have one last step on the project. I must output this to a text file from the command line. I've changed the last bit of code to this:
public static void main(String[] args) throws IOException{
java.io.File file = new java.io.File("guitartest.txt");
if (file.exists()){
System.out.println("This file already exists!");
System.exit(1);
}
// Create a file
java.io.PrintWriter output = new java.io.PrintWriter(file);
Guitar[] guit = new Guitar[10]; // Create 10 instruments
for (int i = 0; i < guit.length; i++){
output.println(guit[i] = new Guitar());
output.println(guit[i].Guitar());
output.println(guit[i].inTune());
output.println(guit[i].isPlaying());
output.println(guit[i].notes());
output.println(guit[i].stopPlaying());
}
}
This compiles the codes, and displays the results I want in the console, but the text file guitartest.txt is completely blank. I am NOT looking for someone to complete this assignment for me, I'm just looking for any advice or resources you could point me to. Thank you very much!
PrintWriter is buffered, that means that the text you're writing to it is stored in its internal buffer before being actually written to the file. So you need to call a close() method when you're done writing, so that the PrintWriter object wrote the data to the file and closed it.
You can also call flush(), this may be useful if you want your data written now but also want to continue using the PrintWriter object.
After you're done writing
output.flush();
output.close();
The PrintWriter constructor that accepts a File is implemented as
public PrintWriter(File file) throws FileNotFoundException {
this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),
false);
}
In other words, your outputs are being buffered and need to be flushed from time to time or all in one shot.
Call
output.flush();
or
output.close();
when you are finished using it.
You probably need to flush the output stream at the end, i.e. after the for loop in the main() method do
output.flush();
output.close();
You can include both of these calls in a try/catch block, for safety:
try {
output.flush();
output.close();
} catch (Exception e) {
e.printStackTrace();
}
I am not a good programmer. In school, I learned MATLAB. So i have no idea what I am doing.
I am working with the ThingMagic M6 reader. They have their own API. I wanted to create my own application to read the program. I want to use a sample program that they have supplied (since my program doesn't seem to work). However, the supplied program only accepts command line arguments. How do i change it so I can pass arguments to it in my code.
This is the supplied code: (at the command line I input tmr://10.0.0.101)
/**
* Sample program that reads tags for a fixed period of time (500ms)
* and prints the tags found.
*/
// Import the API
package samples;
import com.thingmagic.*;
public class read
{
static void usage()
{
System.out.printf("Usage: demo reader-uri <command> [args]\n" +
" (URI: 'tmr:///COM1' or 'tmr://astra-2100d3/' " +
"or 'tmr:///dev/ttyS0')\n\n" +
"Available commands:\n");
System.exit(1);
}
public static void setTrace(Reader r, String args[])
{
if (args[0].toLowerCase().equals("on"))
{
r.addTransportListener(r.simpleTransportListener);
}
}
static class TagReadListener implements ReadListener
{
public void tagRead(Reader r, TagReadData t) {
System.out.println("Tag Read " + t);
}
}
public static void main(String argv[])
{
System.out.println(argv.getClass().toString());
// Program setup
TagFilter target;
Reader r;
int nextarg;
boolean trace;
r = null;
target = null;
trace = false;
nextarg = 0;
if (argv.length < 1)
usage();
if (argv[nextarg].equals("-v"))
{
trace = true;
nextarg++;
System.out.println("Trace");
}
// Create Reader object, connecting to physical device
try
{
TagReadData[] tagReads;
r = Reader.create(argv[nextarg]);
if (trace)
{
setTrace(r, new String[] {"on"});
}
r.connect();
if (Reader.Region.UNSPEC == (Reader.Region)r.paramGet("/reader/region/id"))
{
r.paramSet("/reader/region/id", Reader.Region.NA);
}
r.addReadListener(new TagReadListener() );
// Read tags
tagReads = r.read(500);
// Print tag reads
for (TagReadData tr : tagReads)
System.out.println(tr.toString());
// Shut down reader
r.destroy();
}
catch (ReaderException re)
{
System.out.println("Reader Exception : " + re.getMessage());
}
catch (Exception re)
{
System.out.println("Exception : " + re.getMessage());
}
}
}
This is me trying to use it: (arg comes from a JTextField)
String[] argv = new String[1];
argv[0] = arg;
readOnceApp(argv);
I have a feeling there is a really simple answer to this problem, I just can't figure it out. I searched the internet for a few days and read books, and still can't figure it out. Any help is appreciated. Thank You.
edit: readOnceApp is one method I wrote. It is basically just the main method of the supplied code. I can include it, if it will help. I just didn't want to post too much code.
If you want to call the "main" method of a class from another class, do it like this:
String [] args = new String [1];
args[0]= "some param";
readOnceApp.main(args);
This is making the assumption that "readOnceApp" is the name of your class. (BTW, you should follow the convention of using capitalized class names, e.g. ReadOnceApp).
Hope this helps.