I have this file: "Test.txt" -> 1,cont,details,950.5,asd
My Class is Auto, the constructor is int, string, string, double, string.
How can I read from this file and then initialize my object with the correct data conversion?
I think I need to use a comma splitter too.
FileReader inFile2=null;
BufferedReader outBuffer2=null;
inFile2=new FileReader("Test.txt");
outBuffer2 = new BufferedReader(inFile2);
List<String> lines = new ArrayList<String>();
String line="";
while((line = outBuffer2.readLine()) != null) {
lines.add(line);
System.out.println(lines);
}
outBuffer2.close();
inFile2.close();
//
String[] splitTranzactie = lines.toArray(new String[]{});
Auto t = new Auto(Int32(splitTranzactie[0]), splitTranzactie[1], splitTranzactie[2],
ToDouble(splitTranzactie[3]), splitTranzactie[4]);
There are a few issues here. First of all:
String[] splitTranzactie = lines.toArray(new String[]{});
is going to just turn your list of lines into an array of lines. To split each line into its constituent parts you can use something like String.split(","). This will return an array of Strings. Note that if you expect any of the last values to be empty, i.e. ending in one or more commas then the returned array will be as long as the last value position it finds. i.e. if the line is 1,cont,details,, you split will return an array of length 3 not 5. You should code defensively against this.
To convert a String to an int or double you can use Integer.parseInt() and Double.parseInt() respectively. Again you may want to consider coding defensively if the values may be anything other than numeric values as those two methods will throw an exception if they can't parse the input.
You should also place your close() methods in a finally block to ensure they are called, however as they are AutoCloseable you can avoid this altogether by using the try-with-resources syntax which will close the reader automatically.
try(Reader in = new Reader()) {
}
A working example with all of the above (but without any defensive code) following your example may look something like the following:
List<Auto> autos = new ArrayList<>();
try (BufferedReader in = new BufferedReader(new FileReader("Test.txt"))) {
String line = null;
while((line = in.readLine()) != null) {
String[] values = line.split(",");
autos.add(new Auto(
Integer.parseInt(values[0]),
values[1],
values[2],
Double.parseDouble(values[3]),
values[4]));
}
}
you can create stream from the lines then you can apply the Function(ArrayList< String >,ArrayList< Auto >) interface to get data by defining custom behaviour through lambda function. To convert data to integer from String use Integer.parse(String) and for double data use Double.parse(string)
Using Java 8 stream:
try (Stream<String> fileStream = Files.lines(Paths.get("Test.txt"))) {
fileStream.map(line -> line.split(",")).forEach(array -> {
Auto auto = new Auto(Integer.parseInt(array[0]), array[1], array[2], Double.parseDouble(array[3]), array[4]);
});
}
You can collect the auto to list by:
List<Auto> autoList;
try (Stream<String> fileStream = Files.lines(Paths.get("Test.txt"))) {
autoList = fileStream.map(line -> {
String[] array = line.split(",");
return new Auto(Integer.parseInt(array[0]), array[1], array[2], Double.parseDouble(array[3]), array[4]);
}).collect(Collectors.toList());
}
Following your current scheme, here one way I might carry out the task. The code also validates the data and places defaults if those validations fail.
public List<Auto> getAutoListFromFile(String filePath) {
List<Auto> list = new ArrayList<>(); // Declare a List Interface
Auto auto; // Declare Auto
// Open a file reader. Try With Resourses is used here so as to auto close reader.
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line = "";
// Iterate through the file lines
while((line = reader.readLine()) != null) {
line = line.trim(); // Trim lines of any unwanted leading or trailing whitespaces, tabs, etc.
// Skip blank lines.
if (line.equals("")) {
continue;
}
System.out.println(line); // Display file line to console (remove if desired).
/* Split the current comma delimited file line into specific components.
A regex is used here to cover all comma/space scenarios (if any). */
String[] lineParts = line.split("\\s{0,},\\s{0,}");
// Establish the first Auto memeber value for the Auto class constructor.
int id = -1; // default
// Make sure it is an unsigned Integer value. RegEx is used here again.
if (lineParts[0].matches("\\d+")) {
id = Integer.parseInt(lineParts[0]);
}
// Establish the second Auto memeber value for the Auto class constructor.
String cont = !lineParts[1].equals("") ? lineParts[1] : "N/A"; //Ternary Used
// Establish the third Auto memeber value for the Auto class constructor.
String details = !lineParts[2].equals("") ? lineParts[2] : "N/A"; //Ternary Used
// Establish the fourth Auto memeber value for the Auto class constructor.
double price = 0.0d; //default
// Make sure it is a signed or unsigned Integer or double value. RegEx is used here again.
if (lineParts[3].matches("-?\\d+(\\.\\d+)?")) {
price = Double.parseDouble(lineParts[3]);
}
// Establish the fifth Auto memeber value for the Auto class constructor.
String asd = !lineParts[4].equals("") ? lineParts[4] : "N/A"; //Ternary Used
auto = new Auto(id, cont, details, price, asd); // Create an instance of Auto
list.add(auto); // Add Auto instance to List.
// Go and read next line if one exists
}
}
// Handle Exceptions.
catch (FileNotFoundException ex) {
Logger.getLogger("getAutoListFromFile() Method Error!").log(Level.SEVERE, null, ex);
}
catch (IOException ex) {
Logger.getLogger("getAutoListFromFile() Method Error!").log(Level.SEVERE, null, ex);
}
return list; // Return the filled list.
}
And to use this method you might do:
List<Auto> list = getAutoListFromFile("Test.txt");
For int you can use
int a = Integer.parseInt(string);
Almost the same for the double
double b = Double.parseDouble(string);
But be aware that both can throw NumberFormatException if the string is not what it is meant to be.
Related
Hopefully my explanation does me some justice. I am pretty new to java. I have a text file that looks like this
Java
The Java Tutorials
http://docs.oracle.com/javase/tutorial/
Python
Tutorialspoint Java tutorials
http://www.tutorialspoint.com/python/
Perl
Tutorialspoint Perl tutorials
http://www.tutorialspoint.com/perl/
I have properties for language name, website description, and website url. Right now, I just want to list the information from the text file exactly how it looks, but I need to assign those properties to them.
The problem I am getting is "index 1 is out of bounds for length 1"
try {
BufferedReader in = new BufferedReader(new FileReader("Tutorials.txt"));
while (in.readLine() != null) {
TutorialWebsite tw = new TutorialWebsite();
str = in.readLine();
String[] fields = str.split("\\r?\\n");
tw.setProgramLanguage(fields[0]);
tw.setWebDescription(fields[1]);
tw.setWebURL(fields[2]);
System.out.println(tw);
}
} catch (IOException e) {
e.printStackTrace();
}
I wanted to test something so i removed the new lines and put commas instead and made it str.split(",") which printed it out just fine, but im sure i would get points taken off it i changed the format.
readline returns a "string containing the contents of the line, not including any line-termination characters", so why are you trying to split each line on "\\r?\\n"?
Where is str declared? Why are you reading two lines for each iteration of the loop, and ignoring the first one?
I suggest you start from
String str;
while ((str = in.readLine()) != null) {
System.out.println(str);
}
and work from there.
The first readline gets the language, the second gets the description, and the third gets the url, and then the pattern repeats. There is nothing to stop you using readline three times for each iteration of the while loop.
you can read all the file in a String like this
// try with resources, to make sure BufferedReader is closed safely
try (BufferedReader in = new BufferedReader(new FileReader("Tutorials.txt"))) {
//str will hold all the file contents
StringBuilder str = new StringBuilder();
String line;
while ((line = in.readLine()) != null) {
str.append(line);
str.append("\n");
} catch (IOException e) {
e.printStackTrace();
}
Later you can split the string with
String[] fields = str.toString().split("[\\n\\r]+");
Why not try it like this.
allocate a List to hold the TutorialWebsite instances.
use try with resources to open the file, read the lines, and trim any white space.
put the lines in an array
then iterate over the array, filling in the class instance
the print the list.
The loop ensures the array length is a multiple of nFields, discarding any remainder. So if your total lines are not divisible by nFields you will not read the remainder of the file. You would still have to adjust the setters if additional fields were added.
int nFields = 3;
List<TutorialWebsite> list = new ArrayList<>();
try (BufferedReader in = new BufferedReader(new FileReader("tutorials.txt"))) {
String[] lines = in.lines().map(String::trim).toArray(String[]::new);
for (int i = 0; i < (lines.length/nFields)*nFields; i+=nFields) {
TutorialWebsite tw = new TutorialWebsite();
tw.setProgramLanguage(lines[i]);
tw.setWebDescription(lines[i+1]);
tw.setWebURL(lines[i+2]);
list.add(tw);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
list.forEach(System.out::println);
A improvement would be to use a constructor and pass the strings to that when each instance is created.
And remember the file name as specified is relative to the directory in which the program is run.
I have a text file in which I have written some information line by line like this:
name|Number|amount|PIN
How can I read back data In a way that (for example) I will be able to use just the "name" part in a method?
The sample code is shown in the image below.
in the beginning declare a List to collect the accounts:
import java.util.ArrayList;
...
public Account[] inReader() { //BTW: why do you pass an Account[] here?
ArrayList accountList = new ArrayList();
...
}
replace the for(String records : dataRecords) {...} with
String name = dataRecords[0];
String cardNumber = dataRecords[1];
int pin = Integer.parseInt(dataRecords[2]); //to convert the String back to int
double balance = Double.parseDouble(dataRecords[3]);
Account account = new Account(name, cardNumber, pin, balance);
accountList.add(account);
because you already proceed record by record (while ((line = br.readLine())!=null) {...})
in the end return accountList.toArray(new Account[0]);
You can read the text line by line and then use the "|" delimiter to separate the columns.
try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
stream.forEach(System.out::println);
}
You could read the file line-by-line and split on the delimiter '|'.
The following example assumes the filepath is in args[0] and would read then output the name component of the input:
public static void main(String[] args) {
File file = new File(args[0]);
BufferedReader br = new BufferedReader(new FileReader(file));
while(String line = br.readLine()) != null) {
String[] details = line.split("|");
System.out.println(details[0]);
}
}
As mentioned in the comment above, you can simply split the line on your delimiter, |, and go from there.
Something like:
public class Account {
// ...
public static Account parseLine(String line) {
String[] split = line.split("|");
return new Account(split[0], split[1], split[2], split[3]);
}
}
should work fine (assuming you have a constructor which takes the four things you're putting in). If your Account class has more information than this, you can create an AccountView or similarly named class which does only contain the details you have available here. With this, just iterate line by line, parse your lines to one of these Objects, and use it's properties (including the already available getters) when calling other methods which need name, etc.
First, you need to read the whole content of the file or line by line.
Then, for each line you need to create a function to split the line text by a configurable delimiter. This function can receive the column number and it should return the needed value. For example: extractData(line, 0) should return 'name', extractData(line, 2) should return 'amount' etc.
Also, you need some validation: what if there are only 3 columns and you expect 4? You can throw and exception or you can return null/empty.
There are many possible ways to do it. One of them is to make an object that will hold the data. Example since you know that your data will always have name, number, amount and pin then you can make a class like this:
public class MyData {
private String name;
private String number;
private double amount;
private String pin;
// Add getters and setters below
}
Then while reading the text file you can make a list of MyData and add each data. You can do it like this:
try {
BufferedReader reader = new BufferedReader(new FileReader("path\file.txt"));
String line = reader.readLine();
ArrayList<MyData> myDataList = new ArrayList<MyData>();
while (line != null) {
String[] dataParts = line.split("|"); // since your delimiter is "|"
MyData myData = new MyData();
myData.setName(dataParts[0]);
myData.setNumber(dataParts[1]);
myData.setAmount(Double.parseDouble(dataParts[2]));
myData.setPin(dataParts[3]);
myDataList.add(myData);
// read next line
line = reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
Then you can use the data like this:
myDataList.get(0).getName(); // if you want to get the name of line 1
myDataList.get(1).getPin(); // if you want to get the pin of line 2
You can convert the file into a csv file and use a library specific for reading csv files, e.g. OpenCSV. This will give you more flexibility in handling the data in the file.
I have a textfile as such:
type = "Movie"
year = 2014
Producer = "John"
title = "The Movie"
type = "Magazine"
year = 2013
Writer = "Alfred"
title = "The Magazine"
What I'm trying to do is, first, search the file for the type, in this case "Movie" or "Magazine".
If it's a Movie, store all the values below it, i.e
Set the movie variable to be 2014, Producer to be "John" etc.
If it's a Magazine type, store all the variables below it as well separately.
What I have so far is this:
public static void Parse(String inPath) {
String value;
try {
Scanner sc = new Scanner(new FileInputStream("resources/input.txt"));
while(sc.hasNextLine()) {
String line = sc.nextLine();
if(line.startsWith("type")) {
value = line.substring(8-line.length()-1);
System.out.println(value);
}
}
} catch (FileNotFoundException ex) {
Logger.getLogger(LibrarySearch.class.getName()).log(Level.SEVERE, null, ex);
}
}
However, I'm already having an issue in simply printing out the first type, which is "Movie". My program seems to skip that one, and print out "Magazine" instead.
For this problem solely, is it because the line: line.startsWith("type")is checking if the current line in the file starts with type, but since the actual String called lineis set to the nextline, it skips the first "type"?
Also, what would be the best approach to parsing the actual values (right side of equal sign) below the type "Movie" and "Magazine" respectively?
I recommend you try the following:
BufferedReader reader = new BufferedReader(new FileReader(new File("resources/input.txt")));
String line;
while((line = reader.readLine()) != null) {
if (line.contains("=")) {
String[] bits = line.split("=");
String name = bits[0].trim();
String value = bits[1].trim();
if (name.equals("type")) {
// Make a new object
} else if (name.equals("year")) {
// Store in the current object
}
} else {
// It's a new line, so you should make a new object to store stuff in.
}
}
In your code, the substring looks suspect to me. If you do a split based on the equals sign, then that should be much more resilient.
I'm trying to make this work, I don't understand why it doesn't work since it makes sense to me, but it doesn't make sense to java it seems.
As you read the code, what I expect is _NAME to be replaced by TEST while maintaining the same structure of the text (keeping \n) to save it later(not done yet)
I also stored it using ArrayList, but the replace never took off either, so I'm clueless
try {
BufferedReader reader = new BufferedReader (new InputStreamReader (
new FileInputStream (temp), "utf-8"));
String line = reader.readLine();
StringBuffer text = new StringBuffer();
while(line != null) {
line.replace("[_NAME]", "TEST");
Logger.info(line);
line = reader.readLine();
}
reader.close();
} catch(FileNotFoundException ex) {
} catch(UnsupportedEncodingException ex) {
} catch(IOException ex ) {}
The correct line is
line = line.replace("_NAME", "TEST");
If you use brackets, you are specifying the characters as individual matches (_, N, A, M and E), and you want to replace the whole match.
Second, the replace method return a new String that contains the modified String. Remember that Strings in Java are immutable, so no method that modifies a String would modify the input object, they will always return a new object.
One possible problem is the fact that you have [] around _NAME but I'm going to go with the "you forgot that replace returns the new string instead of changing it in-situ" option. See here.
In other words, it should changed from:
line.replace ( ...
to:
line = line.replace ( ...
A file name will be passed in from standard in. I want to open it, read it, and create some information based off the text in the file.
For example, if this is a line in the file:
Hristo 3
... then I want to create a Member() named Hristo with a value of 3. So I want to pull out a String for the name and an int for the value. The name and the value are separated by some unknown number of tabs and spaces which I need to ignore. Could I just read the line, use .trim() to get rid of whitespace, and the last character would be the value?
I have not shown the class Member() for simplicity's sake. This is what I have so far:
public static void main(String[] args) {
int numMembers = 0;
ArrayList<Member> veteranMembers = new ArrayList<Member>();
File file = new File(args[0]);
FileReader fr;
BufferedReader br;
// attempt to open and read file
try {
fr = new FileReader(file);
br = new BufferedReader(fr);
String line;
// read file
while ((line = br.readLine()) != null) {
// extract name and value from line
... ? ...
// create member
// initialize name and value
Member member = new Member();
veteranMembers.add(member);
}
br.close();
} catch (FileNotFoundException e1) {
// Unable to find file.
e1.printStackTrace();
} catch (IOException e) {
// Unable to read line.
e.printStackTrace();
}
}
How would I parse that line of text?
Thanks in advance for your help.
I would use the split function.
You can give it a regular expression as the argument
i.e.
line.split(" |\t");
will return array of the words ( {list[0] = Hristo, list[1] = 3} in your example)
Hope it helps.
Use split("\\s+"), this regex ignore any space, tab, etc from the String.
A more robust way might be to use regular expressions; if you received malformed input (e.g., "Ted One"), parseInt() would throw a NumberFormatException.
import java.util.regex.*;
...
Pattern p = Pattern.compile("^(.*)\\s+(\\d+)$"); // Create a regex Pattern that only matches (text - white space - integer)
Matcher m = p.matcher(line); // Create a Matcher to test the input line
if(m.find()){
// If there's a match, ..
String name = m.group(1); // Set "name" to the first parenthesized group
String value = m.group(2); // Set "value" to the second parenthesized group
}
else{
// Bad Input
}
Looks like a home work. You came really close doing it. Use StringTokenizer to tokenize the line. Then create a new member object and and call setters for both the attributes with tokens as params. If your second attribute is an int use parseInt to convert and assign it.