I'm new to java and I've just started a project where I need to create a network from a .txt file, where each line in the file is "node1 node2", with a tabulation between nodes. I have created a node class and an edge class which accepts node names as their arguments, and now I'm writing the network class. I'm using Arraylist to store my nodes and interaction (edge) information, but I'm confused as to how I retrieve this information in my main program. Network class as it stands:
import java.io.*;
import java.util.ArrayList;
public class Network {
public ArrayList<String> nodes = new ArrayList<String>();
public ArrayList<String> edges = new ArrayList<String>();
public String filename;
public Network(String f) {
this.filename = f;
FileReader networkinput = null;
try {
networkinput = new FileReader("f");
BufferedReader bufferedReader = new BufferedReader(networkinput);
//reads the argument file in.
String line = null;
while((line = bufferedReader.readLine()) != null) {
edges.add(line); // Adds each line of the file to the array
String delimiter = "\t";
String[] tempnodelist; // Creates an array each loop
tempnodelist = line.split(delimiter);
nodes.add(tempnodelist[0]); // Adds the first node
nodes.add(tempnodelist[1]); // Adds second node to node array.
}
bufferedReader.close();
}
catch (IOException e) {
System.out.println("Read Error!");
}
}
}
As it stands I want this code to accept the file, reach each line and place each node into the arraylist "nodes", and each line (representing an interaction) into the arraylist "edges". I'm unsure how to retrieve this information within the main program to check whether it is doing what I think it is.
Is this code doing what I expect? and how can I retrieve this ArrayList information in the main program?
Please ask any questions if anything is unclear.
Create an instance of the Network class to initialize everything going on in the constructor. Then access the data.
public class TestNetwork {
public static void main(String[] args){
Network network = new Network("file.txt"); <-- create instance
ArrayList<String> nodes = network.nodes; <-- reference the data
ArrayList<String> edges = network.edges;
for (String s : nodes) { <-- traverse data
System.out.println(s); <-- print data
}
for (String s : edges){
System.out.println(s);
}
}
}
Also, another thing wrong I noticed in your constructor is this
networkinput = new FileReader("f"); <-- "f" I don't think is the file path.
You should use this
networkinput = new FileReader(f);
or
networkinput = new FileReader(filename);
Note: Consider what #erzr2 said.
You can call Network.nodes to get the ArrayList, but this is not necessarily advisable, depending on how you use it. More advisably make the ArrayList private and create a getter method that will return the ArrayList and then you can call the method from another class. So something like this:
private ArrayList<String> nodes = new ArrayList<String>();
private ArrayList<String> edges = new ArrayList<String>();
then later have this:
public ArrayList<String> getNodes(){
return nodes;
}
Related
Forgive the beginners question but I'm a tester first and foremost and am struggling to comprehend how to work through this. I'm simply trying to populate some test data by reading a partial website url and its corresponding syndicator login ID by using a buffered input stream reader and returning two values from each line, split by a comma.
Here's my csv:
website1.uk, website1syndicator
website2.uk, website2syndicator
website3.uk, website3syndicator
Here's my class to read the csv and populate List with one String element:
public class AbstractTestAllSites extends PageBase {
private static Logger log = LoggerFactory.getLogger(AbstractTestAllSites.class);
private static List<String> allWebsiteNames;
static {
try (InputStream websiteListInputStream = AbstractTestAllSites.class.getResourceAsStream("/websites/my_sites.csv")) {
readAllWebsiteNamesFrom(websiteListInputStream);
} catch (IOException e) {
log.error("Failed to read websitelist!", e);
}
}
private static void readAllWebsiteNamesFrom(InputStream input) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
List<String> websites = new ArrayList<String>();
String listLine;
while ((listLine = reader.readLine()) != null) {
listLine = listLine.trim();
if (!(listLine.startsWith("#") || isBlank(listLine))) {
websites.add(listLine);
}
}
allWebsiteNames = unmodifiableList(websites);
}
#Parameterized.Parameters
public static final List<String> data() {
return allWebsiteNames;
}
}
I can then pass the website endpoints into my test like so:
private static final String url = "http://mydomain.";
private String website;
private String syndicator;
public static WebDriver driver;
public TestAllSitesTest(String website, String syndicator){
this.website = website;
this.syndicator = syndicator;
}
#Before
public void getNextWebsite(){
driver.get(url + this.website);
}
//run my tests here...
...and iterate over them until done. But how can I pass two params in so I can access the syndicator variable - probably need a HashMap or similar and then split on the comma but struggling a bit.
In case you want to know how to split each line of your csv file in order to create an object of class TestAllSitesTest (which has a constructor taking a website and a syndicator), you can do it as follows (at the desired position in your code, this is just a main method showing an example):
public static void main(String[] args) {
// create two ArrayLists, first one containing lines, second containing desired objects
List<String> websites = new ArrayList<String>();
List<TestAllSitesTest> testAllSitesTests = new ArrayList<TestAllSitesTest>();
// add csv lines to the first ArrayList
websites.add("website1.uk, website1syndicator");
websites.add("website2.uk, website2syndicator");
websites.add("website3.uk, website3syndicator");
// iterate the list containing the csv lines
websites.forEach((String website) -> {
// split one line into the desired two parts, eliminating comma and space
String[] splitWebsite = website.split(", ");
// create a new object passing the parts of the split line as constructor parameters
TestAllSitesTest test = new TestAllSitesTest(splitWebsite[0], splitWebsite[1]);
testAllSitesTests.add(test);
});
// print the resulting objects
testAllSitesTests.forEach((TestAllSitesTest t) -> {
System.out.println("Website: " + t.getWebsite()
+ ", Syndicator: " + t.getSyndicator());
});
}
I hope this helps…
How can I have only one same name in my combobox? There are 2 same name in my fee text file and I want to get the name from fee text file to the combobox. But it display 2 same name.
There are no error in my code and I cannot find out the questions. I think my combobox function got problems. Below is my expected result.
//fee.txt
john|123|0.00
john|456|0.00
//my expected result in combobox
john
//my result
john
john
//filefuncion.java
public class FileFunction {
public static ArrayList getContent(File f) {
ArrayList ls = null;
try (BufferedReader in = new BufferedReader(new FileReader(f));) {
String line;
ls = new ArrayList();
/*while ((line = in.readLine()) != null) {
ls.add(line);
}*/
while ((line = in.readLine()) != null) {
if (line.trim().length() > 0) {
ls.add(line);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return ls;
}
//my code
private void combobox(){
File file = new File("fee.txt");
ArrayList al = FileFunction.getContent(file);
for (Object obj : al) {
String newobj = obj.toString();
String text[] = newobj.split("\\|");
String name = text[0];
String status = text[2];
if(status.equals("0.00")){
comboboxResident.addItem(name);
}
}
}
First, use generics to ensure a stronger type-checking and reduce bugs due to incorrect types. Write something like ArrayList<String> instead of plain ArrayList.
If you want to remove duplicate elements in an ArrayList instance, the most convenient way is to build a Set (which is a class under the Collection framework) and convert it back to ArrayList (if you need to).
For example, suppose you have an ArrayList instance, then you may write
ArrayList<String> list = ...
LinkedHashSet<String> set = new LinkedHashSet<>(list);
Just iterate through set will do. Or you can convert it back to a list by ArrayList<String> newList = new ArrayList<>(set);.
A LinkedHashSet implements the Set interface and does not contain duplicate elements. It also has predictable iteration order. If you want to further sort you elements, try a TreeSet instead.
I know there are many questions about reading text files here but I have gone through all of them and I think I'm having some difficulty with syntax or SOMETHING because nothing that I've been trying has been working at all.
What I'm attempting to do is this:
1) read a text file inputed by user
2) copy each individual line into an array, so each line is its own element in the array
I feel like I am very close but for some reason I can't figure out exactly how to get it to work!
Here is the relevant code I have right now:
I keep getting out of bounds exceptions in three locations which I've marked off.
Been working on this for quite a while not sure what to do next! Any ideas?
import java.io.IOException;
import java.util.Scanner;
public class FindWords {
public static void main (String args[]) throws IOException{
FindWords d = new Dictionary();
((Dictionary) d).dictionary(); //********* out of bounds here
}
/**
* Validates and returns the dictionary inputed by the user.
*
* #param
* #return the location of the dictionary
*/
public static String getDict(){
///////////////////ASK FOR DICTIONARY////////////////////
System.out.println("Please input your dictionary file");
//initiate input scanner
Scanner in = new Scanner(System.in);
// input by user
String dictionary = in.nextLine();
System.out.println("Sys.print: " + dictionary);
//make sure there is a dictionary file
if (dictionary.length() == 0){
throw new IllegalArgumentException("You must enter a dictionary");
}
else return dictionary;
}
}
which calls on the class Dictionary:
import java.io.*;
public class Dictionary extends FindWords{
public void dictionary () throws IOException{
String dict = getDict();
String[] a = readFile(dict); //********** out of bounds here
int i = 0;
while(a[i] != null){
System.out.println(a[i]);
i++;
}
}
public static String[] readFile(String input) throws IOException{
//read file
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(input)));
System.out.println ();
int count = 0;
String[] array = new String[count];
try{
while (br.readLine() != null){
array[count] = br.readLine(); //********out of bounds here
count++;
}
br.close();
}
catch (IOException e){
}
return array;
}
}
Thank you for looking!
Edit: Just fyi: I have my .txt file in the parent project folder.
Have you tried this?:
List<String> lines = Files.readAllLines(Paths.get("/path/to/my/file.txt"));
and then transform your list to an array if you want:
String[] myLines = lines.toArray(new String[lines.size()]);
You start with an array size of zero...
int count = 0;
String[] array = new String[count];
Several issues here :
In Java, you can't expand arrays, i.e you have to know their length in advance when you instantiate them. Hence the ArrayOutOfBoundException. To make this easy, I suggest that you use an ArrayList instead.
In your while loop, you're making 2 calls to br.readLine(), so basically you're skipping one line out of 2.
You are initializing a zero-length array, hence the exception on the first iteration:
int count = 0;
String[] array = new String[count];
Since you probably don't know the expected size, work with a List instead:
List<String> list = new ArrayList<>();
String thisLine = null;
try{
while ((thisLine = br.readLine()) != null) {
list.add(thisLine);
}
}
You can get the total size afterwards by:
list.size();
Or even better, go with morganos solution and use Files.readAllLines().
In my main class, I loop through 120 files. For each file I create a 2d array of the data contained within.
My 2d Array is "fullData" of type List<List<String>>. ParserIPAM is an inherited class and i declare fullData in its super class.
This is my code within main:
for(String filename : filefetcher.getFiles()){
System.out.println("file to parse: "+ filename);
ipam = new ParserIPAM(filename);
i=0;
boolean flag = true;
System.out.println("------------------------------------------");
for(List<String> row : ipam.getSqlData()){
//queries.insertVars(row);
//System.out.println(row);
}
//System.out.println(i);
ipam.clearSqlData();
}
And here is my code where I fill the 2d Array:
public ParserIPAM(String filename){
super(filename);
try {
Parse(filename);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
SpecialOperations(fullData);
//System.out.println("+++++++++++++++++++++++++++++++++++"+ls2d.size());
}
#Override
void Parse(String filename) throws FileNotFoundException{
fullData.clear();
FileReader input = new FileReader(filename);
ArrayList<String> Raw = new ArrayList<String>();
BufferedReader bufRead = new BufferedReader(input);
Scanner bufferinput = new Scanner(bufRead);
String nextline = bufferinput.nextLine();
int i = 0;
while(bufferinput.hasNext()){
Raw.clear();
nextline = bufferinput.nextLine();
for(String cell: nextline.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)")){
Raw.add(cell);
//System.out.print(i+" "+cell); ////// THIS PRINTS CORRECT DATA
}
i++;
//System.out.println(i + " " + Raw); ////THIS PRINTS CORRECT DATA
fullData.add(Raw);
}
for(List<String> sub: fullData){
//System.out.println(sub); ///THIS DOES NOT PRINT CORRECTLY
}
}
Edit: ParserIPAM is an inherited class. Here is the complete code for the super class:
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
public abstract class Parser {
protected static String filename;
//private List<List<String>> dataArray = new ArrayList<ArrayList<String>()>();
protected List<List<String>> fullData = new ArrayList<List<String>>();
public Parser(String filename){
//this.filename = filename;
}
//Parse will only parse file and put raw data into a 2d ArrayList.
abstract void Parse(String filename) throws FileNotFoundException;
//SpecialOperations will add additional data to raw data for table insertions.
abstract void SpecialOperations(List<List<String>> data);
}
When I print everything out in the last System.out it prints the correct number of elements (256) but it always prints out the last line of the file 256 times in a row. I'm not exactly sure if I'm filling the array incorrectly or if I'm printing it incorrectly. Either way its wrong and I can't seem to figure it out.
I know there is probably a better way to do this than with an ArrayList, but that's not affecting the issue I'm having.
You only create one ArrayList instance (and clear it in your loop), so you only have one reference added (just many times). For Java 7 and above, the easiest solution I can think of is to use new ArrayList<>() diamond operator instead -
// Raw.clear();
Raw = new ArrayList<>();
for Java 6 and 5,
// Raw.clear();
Raw = new ArrayList<String>();
Similarly, you could also use this instead -
// fullData.add(Raw);
fullData.add(new ArrayList<>(Raw)); // <-- copies Raw
Try putting the instantiation of Raw inside the While loop
while(bufferinput.hasNext()){
ArrayList<String> Raw = new ArrayList<String>();
Raw.clear();
nextline = bufferinput.nextLine();
for(String cell: nextline.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)")){
Raw.add(cell);
//System.out.print(i+" "+cell); ////// THIS PRINTS CORRECT DATA
}
i++;
//System.out.println(i + " " + Raw); ////THIS PRINTS CORRECT DATA
fullData.add(Raw);
}
I have a Vehicle class which contains all information about Vehicle objects including get and set methods. There is also a Showroom class which maintains a list of all of the Vehicle objects, with methods to add/delete and scroll through the list.
In my main (a seperate class called VehicleDriverClass) I am trying to use I/O to write Vehicle data to a file and read in Vehicle data from a file. I can write to a file fine. I am using notepad and so a .txt file to read from. The problem I am having is with how to terminate the end of a line when reading from the file. Here is the constructor for the Vehicle class, so you know the paramaters.
public Vehicle(String man, String mod, String VIN, String dateOfMan, char taxBand, int costOfVehicle)
{
this.manufacturer = man;
this.model = mod;
this.VIN = VIN;
this.dateOfManufacture = dateOfMan;
this.taxBand = taxBand;
this.costOfVehicle = costOfVehicle;
}
This is what I have for the Input method at the moment (without trying to create the oject, just reading from file). The Showroom s being passed to it is for use later, when I create the vehicle object and add it to the showroom.
// code replaced below.
With this implementation when the dataFromFile is outputted to the console it is all on one line, rather than on new lines. Does readline() not terminate the line when '\n' is read in?
Here is how my data is stored in the input file.
Fordtest\n Focus\n frank\n ioCheck\n 09/01/1989\n 23/11/2013\n true\n d\n 1995\n
So for now, how do I get the line to terminate? So that I can then implement the creation of an object from this.
EDIT: I/O is working now. I am now having trouble with the constructor for my Vehicle object needing a the data types char and int for the last two variables. With the current method they are in a string array.
I have removed the code from above and added the new implementation below.public static void
addNewVehicleFromFile(Showroom s)
{
String dataFromFile;
String[] tokens = null;
try
{
File fileReader = new File("AddNewVehicleFromFile.txt");
FileReader fr = new FileReader(fileReader);
BufferedReader br = new BufferedReader(fr);
while ((dataFromFile = br.readLine()) != null)
{
tokens = dataFromFile.split("~");
}
System.out.println(Arrays.toString(tokens));
Vehicle inputVehicle = new Vehicle(tokens[0], tokens[1], tokens[2], tokens[3],
tokens[4], tokens[5]);
/*
Erorr above here with these two. token[4] should be a char and [5] an int
*/
s.addVehicle(inputVehicle);
System.out.println("addNewVehicleFromFile Complete");
}
catch (FileNotFoundException fnfe)
{
System.out.println("File not found exception: " + fnfe.toString());
}
catch (IOException ioe)
{
System.out.println("I/O exception: " + ioe.toString());
}
}
Should I be writing my own toChar and toInt methods to call for these two variables? Or parsing to int or similar.
I think you'll do better if you change your input data format. This is what XML and JSON were born for. If you must persist with your current arrangement, change the delimiter between data elements to something like a tilde '~' instead of \n.
So your input looks like this:
Fordtest~Focus~frank~ioCheck~09/01/1989~23/11/2013~true~d~1995
It's easy to parse now:
String [] tokens = data.split("~");
Write yourself some factory methods to create Vehicles:
public class VehicleFactory {
private static final VehicleFactory INSTANCE= new VehicleFactory();
private VehicleFactory() {}
public static VehicleFactory getInstance() { return INSTANCE; }
public static Vehicle createVehicle(String data) {
Vehicle value = null;
String [] tokens = data.split("~");
if ((tokens != null) && (tokens.length > X)) {
// Map String to int or Date here
value = new Vehicle(tokens[0], tokens[1], tokens[2], tokens[3], tokens[4], tokens[5]);
}
return value;
}
public static List<Vehicle> createVehicles(File f) {
List<Vehicle> values = new ArrayList<Vehicle>();
// implementation left for you
return values;
}
}
readLine() terminates the line when a character matching the Java syntax of \n is read. In most text editors, this is a newline. To express a newline in a Java string, use \n in the source code, but when creating the file by hand, use:
Fordtest
Focus
frank
ioCheck
09/01/1989
23/11/2013
true
d1995