I am learning about all of the different ways to take input from a text file and read through the content. I am struggling to use a try - catch block (with resources), and reading in the file name.
Below is what I have written for this part so far:-
public static void main(String[] args)
{
ArrayList<StationRecord> data = new ArrayList<>();
String stationName = null;
Scanner scan = new Scanner(System.in);
System.out.println("What is the filename?");
String input = scan.nextLine();
File file = new File(input);
try(BufferedReader in = new BufferedReader(new FileReader(file))){
while(scan.hasNext()){
stationName = scan.nextLine();
int yearMonthDay = scan.nextInt();
int max = scan.nextInt();
int min = scan.nextInt();
int avg = scan.nextInt();
double dif = scan.nextDouble();
StationRecord sr = new StationRecord(yearMonthDay, max, min, avg, dif);
data.add(sr);
}
}
catch(IOException e)
{
e.printStackTrace();
}
catch(Exception e)
{
e.printStackTrace();
}
}
I am trying to do this for not only one file, but two of them. Regardless, here is a sample of input:-
Console: What is the filename?
TempData2018a.txt
After this is entered, I am trying to go through the data in the text file and add it to the ArrayList of type StationRecord (my other class).
Any suggestions and guidance would be much appreciated! Also any input on how you might do this with 2 files would be awesome!.
Edit: .txt file data example
PITTSBURGH ALLEGHENY CO AIRPORT PA
20180101 11 2 7 -22.614762
20180102 12 5 9 -20.514762
20180103 23 2 13 -16.414762
I am trying to store that whole first line in a variable called stationName. Then Im trying to store the next int, int, int, int double in an ArrayList of StationRecord type.
Since this is 2018, please stop using new File(..) and start using nio APIs. As you are using Java 8, you can easily achieve what you are trying to achieve here! So, you can create your StationRecord like this:
Path filePath = Paths.get(pathToFile);
String stationName = Files.lines(filePath)
.findFirst()
.get();
List<StationRecord> stationRecords =
Files.lines(filePath)
.skip(1) //Skip first line since it has station name
.map(line -> line.split("\\s")) // split at a space starting from 2nd line
.map(
stationData -> new StationRecord(Integer.valueOf(stationData[0]),
Integer.valueOf(stationData[1]), Integer.valueOf(stationData[2]),
Integer.valueOf(stationData[3]), Double.valueOf(stationData[4]))) // Create StationRecord object using the split fields
.collect(Collectors.toList()); // Collect result to an ArrayList
Using Java 7 & Java 8 API's feature, you can solve your problem like below:
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class LineOperation {
private static List<String> lines;
public static void main(String[] args) throws IOException {
lines = Collections.emptyList();
try {
lines = Files.readAllLines(Paths.get("C:\\Users\\Abhinav\\Downloads\\TempData2018a.txt"), StandardCharsets.UTF_8);
String stationName = lines.get(0);
String[] arr = null;
ArrayList<StationRecord> data = new ArrayList<>();
for(int i=1;i<lines.size();i++) {
arr = lines.get(i).split(" ");
data.add(new StationRecord(Long.parseLong(arr[0]), Integer.parseInt(arr[1]), Integer.parseInt(arr[2]), Integer.parseInt(arr[3]), Double.parseDouble(arr[4])));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
But I strongly recommend you to refer below links for your further clarifications on Java I/O:-
Java – Read from File
Read a File into an ArrayList
Related
I was searching on the internet and came across this code to read files from a file and convert it into a string. But I don't understand how in.read(arr) is reading all the contents of a file at once.
import java.util.Scanner;
import java.io.*;
class Main{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String s = sc.next();
try
{
File file = new File(s);
BufferedReader in = new BufferedReader(new FileReader(file));
int c;
char arr[] = new char[(int)file.length()];
in.read(arr);
String res = new String(arr);
System.out.println(res);
}
catch(Exception e){}
}
}
In contemporary Java code you would use Files.readString for this purpose. It was introduced with Java 11, and it specifically reads an entire text file into a String.
What happens in the code you ask about is a common thing with read(someArray) methods: they read up to a number of conditions, something like
The specified number of characters have been read,
The read method of the underlying stream returns -1, indicating end-of-file, or
The ready method of the underlying stream returns false, indicating that further input requests would block.
here you use the first and second conditions, and hope that the third one will not kick in, so reading from a local file won't cause "blocking" at an arbitrary file position.
File.length tells you the size of the file in bytes. There can't be more characters in a file than its size in bytes, that's why file.length is a good upper estimate for the number of characters you would need. However as there are encodings which can result a single character stored as multiple bytes (such as UTF-8), you should actually use the return value of that read() call which tells you the number of characters read, and then pass it to the String constructor:
char arr[] = new char[(int)file.length()];
int count = in.read(arr);
String res = new String(arr, 0, count);
Actual variants of your code:
with File.toPath() if you like
import java.util.Scanner;
import java.io.File;
import java.nio.file.Files; // "Files" is needed of course
class Main
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String s = sc.next();
try
{
File file = new File(s);
String res = Files.readString(file.toPath()); // many lines disappeared
System.out.println(res);
}
catch (Exception e) {}
}
}
with java.nio classes and interfaces:
import java.util.Scanner;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
class Main
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String s = sc.next();
try
{
Path path = Paths.get(s); // "File file" became "Path path"
String res = Files.readString(path); // many lines disappeared again
System.out.println(res);
}
catch (Exception e) {}
}
}
It's up to a bit of taste and what you have already. If you have a File object anyway (like you need its size for some another purpose, or you get it from GUI code for example - in many cases that's going to be a File), use its toPath(). If you have a String, a single Paths.get() is less typing.
The object 'in' has the information related to file.
'arr' is the array whose length is equal to the length of file contents.
Then 'in' is read upto that length of file
I've found a lot of similar questions on Stack Overflow so far, but none of them have actually answered my question. How do I read the data from different columns in a text file into three separate arrays?
Currently my BufferedReader is going through the entire text file and reading it line by line. The problem is, each line is stored as a singular array element.
As you can see, I tried to access the array elements by calling certain data from the "lines[]" array, which contains all of the lines in the file as separate elements. I just have no idea how to access those elements individually and then store them all in separate arrays. Below are the contents of the text file I'm reading from, and then the Java code itself.
(Name,Team,Score)
John,Blue,20
Jamie,White,28
Jonathan,Blue,19
Ron,White,39
Ron,Blue,29
--
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class Bowling7 {
public static void main(String[] args) {
try {
BufferedReader fin = new BufferedReader(new FileReader(new File("bowling.txt")));
System.out.println("File open successful!");
int line = 0;
String[] lines;
String[] names;
String[] teams;
int[] scores;
for (String x = fin.readLine(); x != null; x = fin.readLine()) {
lines = x.split(",");
teams[line] = lines[line];
scores[line] = lines[line];
line++;
}
System.out.println(lines[0]);
System.out.println(lines[1]);
catch (IOException e) {
System.out.println("File I/O error!");
}
}
}
Java arrays have a fixed length, your approach is off because you assume they are dynamic. Use a Collection, like List, and you can use Files.readAllLines(Path) to get all of the lines with one call. Remember to skip the first line (the header), and parse the score. Like,
File f = new File("bowling.txt");
try {
List<String> lines = Files.readAllLines(f.toPath());
List<String> names = new ArrayList<>();
List<String> teams = new ArrayList<>();
List<Integer> scores = new ArrayList<>();
for (String line : lines.subList(1, lines.size())) {
String[] tokens = line.split("\\s*,\\s*");
names.add(tokens[0]);
teams.add(tokens[1]);
scores.add(Integer.parseInt(tokens[2]));
}
System.out.println("Names: " + names);
System.out.println("Teams: " + teams);
System.out.println("Scores: " + scores);
} catch (IOException e) {
e.printStackTrace();
}
I get
Names: [John, Jamie, Jonathan, Ron, Ron]
Teams: [Blue, White, Blue, White, Blue]
Scores: [20, 28, 19, 39, 29]
Something like this would work
List<String> lines= Files.readAllLines(file.toPath());
String[] teams=new String[lines.size()],names=new String[lines.size()];
int[] scores=new int[lines.size()];
for (int i = 0; i < lines.size(); i++) {
String[] sections=lines.get(i).split(",");
names[i]=sections[0];
teams[i]=sections[1];
scores[i]= Integer.parseInt(sections[2]);
}
System.out.println(Arrays.toString(names));
System.out.println(Arrays.toString(teams));
System.out.println(Arrays.toString(scores));
I am currently writing my Bachelor's thesis in graph theory and use the java scanner to convert a txt file with edges into my Java class graph. My txt file looks like this:
1 2 72 3
2 3 15 98
4 7 66 49
5 6 39 48
6 9 87 97
8 13 31 5
The ints are ordered as: source vertex, sink vertex, cost, capacity.
My Code looks like:
Graph graph = new Graph(false);
File f = new File("Filepath");
Scanner in = new Scanner(f);
while (in.hasNextLine())
{
for (int i =1; i<= numberEdges; i++)
{
String s = in.nextLine();
try (Scanner inscan = new Scanner(s)) {
while (inscan.hasNext())
{
int source = inscan.nextInt();
int sink = inscan.nextInt();
double cost =inscan.nextDouble();
double capacity = inscan.nextDouble();
Vertex Source = new Vertex(source);
Vertex Sink = new Vertex(sink);
Edge edge = new Edge(Source,Sink, cost, capacity);
graph.addEdge(edge);
}
}
}
}
in.close();
I tried to scan each line in a String and then scan the String into my Variables.
It always throws a "NoLineFound" Exception in the first line of the for loop and if I try it with outputing the lines I get none. But when I disable the second scanner and try again I get all lines in the ouput but at the end still a "NoLineFound" Exception.
I checked my txt File and the last line doesn't have a UTF8 line ending, but I don't know how to give it one.
I think that your problem comes from that :
while (in.hasNextLine()){
for (int i =1; i<= numberEdges; i++)
{
First, iteration is redundant (while or for are unitary enough for reading each line. You have to do choice between them).
Besides if your file has less line than numberEdges, a java.util.NoSuchElementException will be raised.
If the number of line is constant in the file, use a for:
for (int i =1; i<= numberEdges; i++)
remove the enclosing while (in.hasNextLine()). It is not required. Iteration control is already done by the for.
If the number of lines in the file may vary, use only a while :
while (in.hasNextLine()){
But anyway, don't use both.
With Java 8 streams:
Files
.lines(f.toPath())
.map(l ->Arrays.stream(l.split(" ")).mapToDouble(Double::parseDouble).toArray())
.map(a->new Edge(new Vertex((int)a[0]), new Vertex((int)a[1]), a[2], a[3]))
.forEach(graph::addEdge);
You are reading nextLine() in a loop after a single check for hasNextLine(). You need to perform a check after each read in order to avoid the "NoLineFound" exception.
It looks like the nested loop is completely unnecessary. You can read file line-by-line, ignoring empty lines, and build your graph without prior knowledge of the number of edges that it has:
Graph graph = new Graph(false);
File f = new File("Filepath");
Scanner in = new Scanner(f);
while (in.hasNextLine()) {
String s = in.nextLine();
try (Scanner inscan = new Scanner(s)) {
if (!inscan.hasNext()) {
continue; // Ignore empty lines
}
int source = inscan.nextInt();
int sink = inscan.nextInt();
double cost =inscan.nextDouble();
double capacity = inscan.nextDouble();
Vertex Source = new Vertex(source);
Vertex Sink = new Vertex(sink);
Edge edge = new Edge(Source,Sink, cost, capacity);
graph.addEdge(edge);
}
}
in.close();
Just perform a check after reading to avoid the "NoLineFound" exception.
You can use the below code to scan the file:
import java.io.File;
import java.util.Scanner;
public class ReadFile {
public static void main(String[] args) {
try {
System.out.print("Enter the file name with extension : ");
Scanner input = new Scanner(System.in);
File file = new File(input.nextLine());
input = new Scanner(file);
while (input.hasNextLine()) {
String line = input.nextLine();
System.out.println(line);
}
input.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
I am creating a program that will produces the statistics of a baseball team
i am trying to create a constructor to read the file into the teamName instance variable and the battingAverages array.
the txt file contains the one word name of the team followed by 20 batting averages.
"Tars 0.592 0.427 0.194 0.445 0.127 0.483 0.352 0.190 0.335 0.207 0.116 0.387 0.243 0.225 0.401 0.382 0.556 0.319 0.475 0.279 "
I am struggling to find how to go about this and get it started?
I ran this and this might be close to what you want. Instead of making a confusing constructor, make a private method that the constructor will call to read in the file into the array.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
public class Baseball {
private File textFile;
private Scanner input;
private String teamName;
//this will only work if you know there will be 20 entries everytime
//otherwise I recommend loading the data into an ArrayList
private double []battingAvgs = new double[20];
public Baseball(String file){
textFile = new File(file);
readInFile(textFile);
}
//private method that reads in the file into an array
private void readInFile(File textFile){
try {
input = new Scanner(textFile);
//read first string into variable teamName
teamName = input.next();
int i=0;
//iterate through rest of file adding it to an ArrayList
while(input.hasNext()){
battingAvgs[i] = input.nextDouble();
i++;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
//print out array
public void printArray(){
for(Double a: battingAvgs){
System.out.println(a);
}
}
}
Well, if these are all on one line in a specific file then what you could do is construct a bufferedreader to read the first line of your file, split the line based on spaces, and then parse the teamName and batting averages out.
BufferedReader br = new BufferedReader(new FileReader("myfile.txt"));
String[] line = br.readLine().split(" ");
br.close();
teamName = line[0];
battingAverages = new int[20];
for(int i = 0; i < 20; i++)
battingAverages[i] = Integer.parseInt(line[i+1]);
These might throw IOExceptions, which you will need to catch. I think Java 7 has a method to automatically handle these kinds of errors (not sure about this), but as I am new to Java 7's added functionality, I would just manually check for those exceptions.
You need to use the BufferedReader, FileInputStream, and InputStreamReader. Your file.txt should have the batting averages on every line, as shown below.
0.592
0.427
0.194
Here is an example of a class that when created, it will read a text file line by line and add each line to the array list:
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.*;
public class Class {
ArrayList<Double> averages;
public Class() {
averages = new ArrayList<Double>();
try {
FileInputStream in = new FileInputStream("inputFile.txt"); //your file path/name
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
while((strLine = br.readLine())!= null) averages.add(Double.parseDouble(strLine));
}catch(Exception e){
System.out.println(e);
}
}
}
Hope this helps
Try using the Scanner class.
File file=new File("TestFile.txt"); //Create a new file
Scanner scan=new Scanner(file);//Create a Scanner object (Throws FileNotFoundException)
if(scan.hasNext()) //Check to make sure that there is actually something in the file.
{
String line=scan.nextLine(); //Read the line of data
String[] array=line.split(" "); //Split line into the different parts
teamName=array[0]; //The team name is located in the first index of the array
battingAverages=new double[array.length-1];//Create a new array to hold the batting average values
for(int i=0;i<battingAverages.length;i++) //Loop through all of the averages
{
double average=Double.parseDouble(array[i+1]);//Convert the string object into a double
battingAverages[i]=average; //Add the converted average to the array
}
System.out.print(teamName+" "+Arrays.toString(battingAverages)); //[Optional] Print out the resulting values
}
I have the following text file (answers.txt):
Problem A: 23|47|32|20
Problem B: 40|50|30|45
Problem C: 5|8|11|14
Problem D: 20|23|25|30
What I need is something that will read the problem that I tell it(Problem A, Problem B), then read the numbers after it, which are separated by the lines, and print it out like this:
Answers for Problem A: a.23 b.47 c.32 d.20
Does anyone know how this can be done? I've been stuck on it for a while.
Read the lines one by one, split the lines at " " first. The you will get an array with three parts "Problem", "A:" and "23|47|32|20". Then split the third part at "|" so you will get a second array with four parts "23,"47","32","20".
Combine all to get the output you want.
If you want info on how to read lines from a file, or spilt strings then there are billions of tutorials online on how to do that so I wont go into detail on how its done. IM sure you can find them.
Check out this code!
It assumes that you have such file format:
Problem A:
23|7|32|20
Problem B:
40|50|30|45
Problem C:
5|8|11|14
Problem D:
20|23|25|30
because you wrote "numbers after it, which are separated by the lines"
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
public class Demo {
public static void main(String[] args) throws FileNotFoundException {
Scanner sc = new Scanner(new File("answers.txt"));
List<String> dataList = new ArrayList<String>();
while(sc.hasNextLine()){
dataList.add(sc.nextLine());
}
System.out.println(dataList);
Map<String,String> map = new HashMap<String,String>();
for(int i=0;i<dataList.size();i=i+2){
map.put(dataList.get(i),dataList.get(i+1));
}
for(Entry<String,String> en:map.entrySet()){
System.out.println(en.getKey()+" : "+en.getValue());
}
String problemC = map.get("Problem C:");
String splitted[] = problemC.split("\\|");
System.out.println("Get me problem C: "+String.format("a:%s, b:%s, c:%s, d:%s",splitted[0],splitted[1],splitted[2],splitted[3]));
}
}
Hope this helps!
public static void main(String args[])
{
BufferedReader br = new BufferedReader(new FileReader(new File("answers.txt")));
String lineRead = null;
String problem = "Problem A";//Get this from user Input
List<String> numberData = new ArrayList<String>();
while((lineRead = br.readLine())!=null)
{
if(lineRead.contains(problem))
{
StringTokenizer st = new StringTokenizer(lineRead,":");
String problemPart = st.nextToken();
String numbersPart = st.nextToken();
st = new StringTokenizer(lineRead,"|");
while(st.hasMoreTokens())
{
String number = st.nextToken();
System.out.println("Number is: " + number);
numberData.add(number);
}
break;
}
}
System.out.println("Answers for " + problem + " : " + numberData );
}
Read the lines one by one, split the lines with :. The you will get an array with two parts "Problem A:" and "23|47|32|20". Then split the second part at "|" so you will get a second array with four parts "23,"47","32","20".
Combining all this you will get the output you want.
Cheers!
Use java.util.Scanner and you can filter the integers in the file.
Scanner s = new Scanner (new File ("answers.txt")).useDelimiter("\\s+");
while (s.hasNext()) {
if (s.hasNextInt()) { // check if next token is integer
System.out.print(s.nextInt());
} else {
s.next(); // else read the next token
}
}
Do you know how to read line by line ? If not , chect it How to read a large text file line by line in java?
To sub your string data there have many ways to do. You can sub as you wish. Here for my code..
String data = yourReader.readLine();
String problem = data.substring("Problem".length(), data.indexOf(":"));
System.err.println("Problem is " + problem);
data = data.substring(data.indexOf(":") + 2, data.length());
String[] temp = data.split("\\|");
for (String result : temp) {
System.out.println(result);
}
Assuming there are always four possible answers as in your Example:
// read complete file in fileAsString
String regex = "^(Problem \\w+): (\\d+)\\|(\\d+)\\|(\\d+)\\|(\\d+)$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(fileAsString);
//and so on, read all the Problems using matcher.find() and matcher.group(int) to get the parts
// put in a Map maybe?
// output the one you want...
I might suggest creating a simple data type for the purpose of organization:
public class ProblemAnswer {
private final String problem;
private final String[] answers;
public ProblemAnswer(String problem, String[] answers) {
this.problem = problem;
this.answers = new String[answers.length];
for (int i = 0; i < answers.length; i++) {
this.answers[i] = answers[i];
}
}
public String getProblem() {
return this.problem;
}
public String[] getAnswers() {
return this.answers;
}
public String getA() {
return this.answers[0];
}
public String getB() {
return this.answers[1];
}
public String getC() {
return this.answers[2];
}
public String getD() {
return this.answers[3];
}
}
Then the reading from the text file would look something like this:
public void read() {
Scanner s = new Scanner("answers.txt");
ArrayList<String> lines = new ArrayList<String>();
while (s.hasNext()) {
lines.add(s.nextLine());//first separate by line
}
ProblemAnswer[] answerKey = new ProblemAnswer[lines.size()];
for (int i = 0; i < lines.size(); i++) {
String[] divide = lines.get(i).split(": "); //0 is the problem name, 1 is the list
//of answers
String[] answers = divide[1].split("|"); //an array of the answers to a given
//question
answerKey[i] = new ProblemAnswer(divide[0], answers); //add a new ProblemAnswer
//object to the key
}
}
Now that leaves you with an answer key with ProblemAnswer objects which is easily checked
with a simple .equals() comparison on the getProblem() method, and whatever index is matched, you have all the answers neatly arranged right within that same object.