The method reads the data for the First class and second Class using scanner and then it stores them in the ArrayList the tow class. First and Second are inherited From Main Class. The problem I have is the duplication I created to objects.
How can I only create one and use it for both.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
public class Auto {
private ArrayList<Main> lists;
public Auto() {
lists = new ArrayList<Main>();
}
public void storeData(Main main) {
list.add(main);
}
public void readFile(String filePath) throws FileNotFoundException {
File file = new File(filePath);
Scanner input = new Scanner(file);
String dataToBe;
while (input.hasNext()) {
String lines = input.nextLine().trim();
Scanner scanner = new Scanner(lines).useDelimiter("\n[ ]*,");
if (lines.startsWith("Data")) {
if (lines.startsWith("FirstData")) {
dataToBe = "first";
} else if (lines.startsWith("SecondData")) {
dataToBe = "second";
}
} else if (dataToBe.equals("first")) {
Main main = new First();
main.readData(scanner);
storeData(main);
} else if (dataToBe.equals("second")) {
Main main = new Second();
main.readData(scanner);
storeData(main);
}
}
}
}
Okay, you might think its longwinded, but it's probably how I would do it under your restrictions.
public void readFile(String filePath) throws FileNotFoundException {
final Pattern pattern = Pattern.compile("\n[ ]*,");
final Scanner fileInput = new Scanner(new File(filePath));
while (fileInput.hasNextLine()) {
final String line = fileInput.nextLine().trim();
final Matcher matcher = pattern.matcher(line);
final StringBuilder builder = new StringBuilder();
byte flag = 0;
while (matcher.find()) {
final String match = matcher.group();
if(match.startsWith("FirstData")){ flag = 1;}
else if(match.startsWith("SecondData")){flag = 2;}
builder.append(line).append(",");
}
Main mainObj = (flag == 1) ? (new First()) : (flag == 2) ? (new Second()) : null;
if(null != mainObj){
mainObj.readData(builder.toString());
}
}
}
The approach above does require you to accept a String instead of a Scanner in the parameter, but the CSV format passed to each method lets the behaviour of each class handle the work.
Related
I am having a bit of an issues trying to pass in a file read by my program and sorted accordantly. I am not used to working with files, and i ran out of ideas as to how this could be achieved.
/////////////////////////////////////// class reads file ///////////////////////////////////
import java.io.*;
public class InFileReader {
private BufferedReader inputStream = null;
private String fileLine;
private StringBuilder sb;
public String getFile(File fileRead) throws FileNotFoundException,
IOException {
inputStream = new BufferedReader(new FileReader(fileRead)); //reads files
sb = new StringBuilder();
while((fileLine = inputStream.readLine()) != null){//keep reading lines in file till there is none
sb.append(fileLine).append("\n");
}
return sb.toString(); //returns StringBuffer read values in String form
}
}
///////////////////////////////////////////////////// end of read file class ///////////////////////
public void getFile(File fileRead) throws FileNotFoundException,
IOException {
try {
String input = fileReader.getFile(fileRead.getAbsoluteFile());
HashMap<Integer, Thing.Ship> hashmap = new HashMap<>();
while (!input.isEmpty()) { // as long as there is data in the file keep looping
Scanner sc = new Scanner(input); // scan file
if (!input.startsWith("//")) { // take out "//" from directory
String type = "";
if (sc.hasNext()) { // if there are character lines get next line
type = sc.next();
}
if (type.equalsIgnoreCase("port")) { // looks for "port"
world.assignPort(new Thing.SeaPort(sc)); // assigns value to Seaport
} else if (type.equalsIgnoreCase("dock")) {
world.assignDock(new Thing.Dock(sc));
} else if (type.equalsIgnoreCase("ship")) {
Thing.Ship s = new Thing.Ship(sc);
hashmap.put(s.getIndex(), s);
world.assignShip(s);
} else if (type.equalsIgnoreCase("pship")) {
Thing.Ship s = new Thing.PassengerShip(sc);
hashmap.put(s.getIndex(), s);
world.assignShip(s);
} else if (type.equalsIgnoreCase("cship")) {
Thing.Ship s = new Thing.CargoShip(sc);
hashmap.put(s.getIndex(), s);
world.assignShip(s);
} else if (type.equalsIgnoreCase("person")) {
world.assignPerson(new Thing.Person(sc));
}
}
}
//inputOut.setText(type);
inputOut.setText(world.toString());
} catch (Exception e) {
System.out.println(e + "-----");
}
}
Here fileRead knows where to find the file to be read "C:\Users\abe\IdeaProjects\CreateSeaPortDataFile\src\text.txt"
public void getFile(File fileRead) throws FileNotFoundException,
IOException {
this is where things just fall apart:
String input = fileReader.getFile(fileRead.getAbsoluteFile());
My intent here is to pass the location of the file so that the getFile class can read it and then be sorted into the hashmap.
again i am not familiar with how to work with file, any suggestion or comment would be greatly appreciated.
thank you in advanced.
If you get a FileNotFoundException then the file was not found.
You say the filename was "C:\Users\abe\IdeaProjects\CreateSeaPortDataFile\src\text.txt".
If you type that name in the code you must escape the backslash:
"C:\\Users\\abe\\IdeaProjects\\CreateSeaPortDataFile\\src\\text.txt".
I need to read two text files and display all the unique words in both the text files.(the words in both 2 files can only be printed once)
file1.txt
lion
tiger
cheetah
elephant
cow
file2.txt
mouse
dog
cow
cat
lion
expected output :
lion
tiger
cheetah
elephant
cow
dog
cat
mouse
public class Workshop {
static int count1 = 0;
static int count2 = 0;
private static final String FILE1 = "C:\\Users\\shagi\\Desktop\\file1.txt";
private static final String FILE2 = "C:\\Users\\shagi\\Desktop\\file2.txt";
static String arrayLines1[] = new String[countLines(FILE1)];
static String arrayLines2[] = new String[countLines(FILE2)];
static String totalArray[] = new String[arrayLines1.length + arrayLines2.length];
static String arrayLines1new[]=new String[countLines(FILE1)];
static int flag = 0;
static int k=arrayLines1.length;
public static void main(String[] args) throws IOException {
readFile(FILE1, FILE2);
displaySimilar();
displayAll();
}
public static int countLines(String File) {
int lineCount = 0;
try {
BufferedReader br = new BufferedReader(new FileReader(File));
while ((br.readLine()) != null) {
lineCount++;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return lineCount;
}
public static void readFile(String File1, String File2) {
String contents1 = null;
String contents2 = null;
try {
FileReader file1 = new FileReader(File1);
FileReader file2 = new FileReader(File2);
BufferedReader buf1 = new BufferedReader(file1);
BufferedReader buf2 = new BufferedReader(file2);
while ((contents1 = buf1.readLine()) != null) {
arrayLines1[count1] = contents1;
count1++;
}
while ((contents2 = buf2.readLine()) != null) {
arrayLines2[count2] = contents2;
count2++;
}
} catch (Exception e) {
e.printStackTrace();
}
}
There are two methods which i tried to find the ans for my question
Method 1
public static void displayAll() {
for (int i =0; i<k-1;i++){
System.out.println(totalArray[i]);
}
System.out.println(totalArray[k-1]);
System.out.println("");
int p=0;
for (int i=0;i<arrayLines2.length;i++){
for (int j=0;j<arrayLines1.length;j++){
if (arrayLines2[i].equals(arrayLines1[j])){
flag=1;
break;
} else {
flag=0;
}
if (flag==1){
arrayLines1new[p]=arrayLines2[i];
p++;
}
}
}
Method 2
public static void displayAll() {
for (int i=0;i<arrayLines1.length;i++){
String a=arrayLines1[i];
for (int j=0;j<arrayLines2.length;j++){
String b =arrayLines2[j];
if (!a.equals(b)){
System.out.println(a);
}
}
}
}
But both doesnt give the expected output
There is lot of redundant code. Here is a simpler and shorter version.
I am using Set and its operations to find common (intersection), uncommon and all unique words.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
public class Workshop {
private static final String FILE1 = "C:\\Users\\shagi\\Desktop\\file1.txt";
private static final String FILE2 = "C:\\Users\\shagi\\Desktop\\file2.txt";
static Set<String> file1Words = new HashSet<String>();
static Set<String> file2Words = new HashSet<String>();
static Set<String> allWords = new HashSet<String>();
static Set<String> commonWords = new HashSet<String>();
static Set<String> uncommonWords = new HashSet<String>();
public static void main(String[] args) throws IOException {
file1Words.addAll(readFile(FILE1));
file2Words.addAll(readFile(FILE2));
System.out.println("file1 : " + file1Words);
System.out.println("file2 : " + file2Words);
displaySimilar();
System.out.println("common : " + commonWords);
displayAll();
System.out.println("all : " + allWords);
displayUnCommon();
System.out.println("uncommon : " + uncommonWords);
}
public static void displaySimilar() {
commonWords.addAll(file1Words);
commonWords.retainAll(file2Words);
}
public static void displayUnCommon() {
uncommonWords.addAll(file1Words);
uncommonWords.addAll(file2Words);
uncommonWords.removeAll(commonWords);
}
public static Set<String> readFile(String file) {
Set<String> words = new HashSet<String>();
try {
FileReader fileReader = new FileReader(file);
BufferedReader buffer = new BufferedReader(fileReader);
String content = null;
while ((content = buffer.readLine()) != null) {
words.add(content);
}
} catch (Exception e) {
e.printStackTrace();
}
return words;
}
public static void displayAll() {
allWords.addAll(file1Words);
allWords.addAll(file2Words);
}
}
Sample Run:
file1 : [lion, cheetah, tiger, elephant, cow]
file2 : [lion, mouse, cat, cow, dog]
common : [lion, cow]
all : [cheetah, lion, cat, mouse, tiger, elephant, cow, dog]
uncommon : [cheetah, cat, mouse, tiger, elephant, dog]
This would be a good situation for a HashMap. The keys would be the words and the values would be the number of occurrences. You could then print out the keys with a value of 1. The pseudo code would look like this:
Initialize the map: HashMap <String, Integer> wordMap = new HashMap<>();
For each file:
-- For each word:
---- Put the word in wordMap with the appropriate value.
For each key in wordMap:
-- If wordMap.get(key) == 1, print out the key
You could also accomplish the same thing using two arrayLists, using one to keep track out the words and another to keep track of the counts.
Both methods have an O(N) time complexity, but using the map is more performant because the maps's values can be updated in O(1).
I'm able to pull out the 20 names randomly but how do I store them in an output file rather than displaying them to the screen? I tried filewriter but couldn't get it to work.
public class Assignment2 {
public static void main(String[] args) throws IOException {
// Read in the file into a list of strings
BufferedReader reader = new BufferedReader(new FileReader("textfile.txt"));
//BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));
List<String> lines = new ArrayList<String>();
String line = reader.readLine();
while( line != null ) {
lines.add(line);
line = reader.readLine();
}
// Choose a random one from the list
Random r = new Random();
FileWriter letters = new FileWriter("out.txt");
for (int i = 0; i < 20; i++) {
int rowNum = r.nextInt(lines.size ());
System.out.println(lines.get(rowNum));
}
}
}
System.out is a PrintStream (javadoc) and not a Writer (javadoc) so the api to access it will be different, you can't replace one by the other. The Writer is some how a lower level abstraction.
But it is easy to create a PrintStream that output a a file and use it as replacement of System.out:
PrintStreasm out = new PrintStream("out.txt");
// you can event assign System.out to out.
// out = System.out;
for (int i = 0; i < 20; i++) {
int rowNum = r.nextInt(lines.size ());
out.println(lines.get(rowNum));
}
out.close()
PS: don't forget to closed any file you open (auto closable functionality of Java 7 is even better)
PSS: I assume you are learning Java, I can't recommend enough that you have a look to at the Java I/O stream apis.
I am using a convince method to write to the file from the library commons.io-2.4, code is also available on github
this example demonstrate how to read and write String lines to a file
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
/**
* Created by Pankaj Nimgade on 10-02-2016.
*/
public class WriteFile {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
list.add("somename_" + i);
}
File file = new File("file.txt");
try {
// FileUtils.writeLines(file, list);
ArrayList<String> strings = (ArrayList<String>) FileUtils.readLines(file);
ArrayList<Name> names = new ArrayList<>();
for (String single:strings) {
names.add(new Name(single));
if (names.size() == 20) {
break;
}
}
for (Name single_name:names) {
System.out.println(single_name.getName());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Name {
String name;
public Name(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public boolean equals(Object obj) {
return this.name.equalsIgnoreCase(((Name) obj).getName());
}
}
output, this will be inside file.txt
somename_0
somename_1
somename_2
somename_3
somename_4
somename_5
somename_6
somename_7
somename_8
somename_9
somename_10
somename_11
somename_12
somename_13
somename_14
somename_15
somename_16
somename_17
somename_18
somename_19
I want to return an array that is accessible by other objects after having read a text file. My instruction parsing class is:
import java.io.*;
public class Instruction {
public String[] instructionList;
public String[] readFile() throws IOException {
FileInputStream in = new FileInputStream("directions.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(in));
int n = 5;
instructionList = new String[n];
for (int j = 0; j < instructionList.length; j++) {
instructionList[j] = br.readLine();
}
in.close();
return instructionList;
}
}
The above takes in a text file with 5 lines of text in it. In my main() I want to run that function and have the string array be accessible to other objects.
import java.util.Arrays;
public class RoverCommand {
public static void main(String[] args) throws Exception {
Instruction directions = new Instruction();
directions.readFile();
String[] directionsArray;
directionsArray = directions.returnsInstructionList();
System.out.println(Arrays.toString(directionsArray));
}
}
What's the best way to do that? I would need the elements of the array to be integers if they are numbers and strings if they are letters. P.S. I'm brand new to Java. is there a better way to do what I'm doing?
You don't have to use generics. I try to catch exceptions in the accessors and return null if anything blows up. So you can test if the value returned is null before proceeding.
// Client.java
import java.io.IOException;
public class Client {
public static void main(String args[]) {
try {
InstructionList il = new InstructionList();
il.readFile("C:\\testing\\ints.txt", 5);
int[] integers = il.getInstructionsAsIntegers();
if (integers != null) {
for (int i : integers) {
System.out.println(i);
}
}
} catch (IOException e) {
// handle
}
}
}
// InstructionList.java
import java.io.*;
public class InstructionList {
private String[] instructions;
public void readFile(String path, int lineLimit) throws IOException {
FileInputStream in = new FileInputStream(path);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
instructions = new String[lineLimit];
for (int i = 0; i < lineLimit; i++) {
instructions[i] = br.readLine();
}
in.close();
}
public String[] getInstructionsAsStrings() {
return instructions; // will return null if uninitialized
}
public int[] getInstructionsAsIntegers() {
if (this.instructions == null) {
return null;
}
int[] instructions = new int[this.instructions.length];
try {
for (int i = 0; i < instructions.length; i++) {
instructions[i] = new Integer(this.instructions[i]);
}
} catch (NumberFormatException e) {
return null; // data integrity fail, return null
}
return instructions;
}
}
check instructionList is null or not. if it is null, call readFile method.
public String[] returnsInstructionList() {
if (instructionList== null){
try { readFile(); } catch(Exception e){}
}
return instructionList;
}
because of readFile can throw exception, it would be good to use one extra variable. like:
private boolean fileReaded = false;
public String[] returnsInstructionList() {
if (!fileReaded){
fileReaded = true;
try { readFile(); } catch(Exception e){}
}
return instructionList;
}
and if readFile can be run concurrently, easiest way to make function synchronized, like
private boolean fileReaded = false;
public synchronized void readFile() throws IOException {
.
.
.
}
public synchronized String[] returnsInstructionList() {
if (!fileReaded){
fileReaded = true;
try { readFile(); } catch(Exception e){}
}
return instructionList;
}
There is no guarantee that readFile is called before returnsInstructionList is invoked. Leaving you returnsInstructionList returning null.
I would :
public String[] getContentsFromFile(String fileName) throws IOException {
FileInputStream in = new FileInputStream(fileName);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
int n = 5;
instructionList = new String[n];
for (int j = 0; j < instructionList.length; j++) {
instructionList[j] = br.readLine();
}
in.close();
return instructionList;
}
Part two to the question you can use generics. To achieve what you want but you have to incorporate a way to say what it is.
Eg
public class Foo {
public ReturnForFoo returnAStringOrIntger(boolean val) {
if(val){
return new ReturnForFoo("String", ValueType.STRING) ;
}
return new ReturnForFoo(10, ValueType.INTEGER); //int
}
}
public class ReturnForFoo {
Object value;
ValueType type;
public ReturnForFoo(Object value, ValueType type) {
this.value=value;
this.type=type
}
// Asume you have getters for both value and value type
public static ENUM ValueType {
STRING,
INTEGER,
UNKNOWN
}
}
This code is in your main.
Foo foo = new Foo();
String value;
int val;
ReturnForFoo returnForFoo = foo.returnAStringOrIntger(true);
// NOTE you can use switch instead of if's and else if's. It will be better
if(returnForFoo.getValueType().equals(ValueType.INTEGER)){
val = (int) returnForFoo.getValue();
} else if(returnForFoo.getValueType().equals(ValueType.STRING)){
value = (String) returnForFoo.getValue();
} else {
// UNKOWN Case
}
I'm try to create one simple reservation system, we'll read a file, then we'll add Train, Bus, etc., then we'll writer everything to output.
import java.io.*;
import java.util.*;
public class Company
{
private static ArrayList<Bus> bus = new ArrayList<Bus>();
static int buscount = 0, traincount = 0;
public static void main (String[] args) throws IOException
{
FileParser();
}
public Company()
{
}
public static void FileParser()
{
try {
File file = new File(); //i fill this later
File file2 = new File(); // i fill this later
FileInputStream fis = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(file2);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
String line;
while ((line = br.readLine()) != null)
{
String[] splitted = line.split(",");
if(splitted[0].equals("ADDBUS"))
{
bus.add(buscount) = Bus(splitted[0],splitted[1],splitted[2],splitted[3],splitted[4],splitted[5]);
}
}
}
catch (FileNotFoundException fnfe) {
}
catch (IOException ioe) {
}
}
}
I try to read the file line by line. For example one of the line is "ADDBUS,78KL311,10,140,54" I split the line for "," then i try to add every pieces of array to Bus' class' constructor but i couldn't figured it out.
My Bus Class is like `
public class Bus extends Vehicle{
private String command;
private String busName;
private String busPlate;
private String busAge;
private String busSpeed;
private String busSeat;
public Bus(String command, String busname, String busplate, String busage, String busspeed, String busseat)
{
this.command = command;
this.busName = busname;
this.busPlate = busplate;
this.busAge = busage;
this.busSpeed = busspeed;
this.busSeat = busseat;
}
public String getBusName() {
return busName;
}
public void setBusName(String busName) {
this.busName = busName;
}
public String getBusPlate() {
return busPlate;
}
public void setBusPlate(String busPlate) {
this.busPlate = busPlate;
}
public String getBusAge() {
return busAge;
}
public void setBusAge(String busAge) {
this.busAge = busAge;
}
public String getBusSpeed() {
return busSpeed;
}
public void setBusSpeed(String busSpeed) {
this.busSpeed = busSpeed;
}
public String getBusSeat() {
return busSeat;
}
public void setBusSeat(String busSeat) {
this.busSeat = busSeat;
}
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
}
can someone show me a way to solve this problem?
Thank you,
You are missing the keyword new to create a new instance of the class:
bus.add(new Bus(...));
You can add items to ArrayList like this
bus.add( new Bus(splitted[0],splitted[1],splitted[2],splitted[3],splitted[4],splitted[5]));
you were missing new keyword before Bus constructor call. Then you can increment the counter (or do whatever)
bus.add( new Bus(splitted[0],splitted[1],splitted[2],splitted[3],splitted[4],splitted[5]));
buscount++;
try to add new Bus(...)
bus.add( new
Bus(splitted[0],splitted[1],splitted[2],splitted[3],splitted[4],splitted[5]));
As I understand if you want to call constructor you need to call new Bus(parms).
when you say new it will call constructor of your class
when you say this() again it going to call enclosing class' constructor
if you say super() it will call super class' constructor.
if you want it into a map order by counter you can use this:
Map(Integer, Bus) busPosition = new HashMap<>();
busPosition.put(buscount, new
Bus(splitted[0],splitted[1],splitted[2],splitted[3],splitted[4],splitted[5]));