Error when reading file into 2D array - java

I have the following code which tries to determine the dimensions of a file, but each time it executes through there is this error:
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)
I'm unaware why this is occurring. Can anyone help debug the issue? And explain why it is happening?
public void loadDistances(String fname) throws Exception {
String file = fname;
File f = new File(file);
Scanner in = null;
try {
in = new Scanner(f);
}
catch (FileNotFoundException ex) {
System.out.println("Can't find file " + file);
System.exit(1);
}
int rows = 0;
int cols = 0;
int elements = 0;
while(in.hasNext()){
while(in.next() != null){
System.out.println(elements++);
}
in.nextLine();
rows++;
}
in.close();
cols = (elements + 1) / rows;
// for debug purposes
System.out.println(rows);
System.out.println(cols);
}
Which reads in this file
0 2 3.0
1 0 2.0
2 1 7.0
2 3 1.0
3 0 6.0
// Checking for suggested answer
int tokens = 0;
String line;
Scanner tokenScanner;
Scanner fileScanner;
Scanner lineScanner;
while(fileScanner.hasNextLine()){
line = fileScanner.nextLine();
lineScanner.nextLine() = line;
while(lineScanner.hasNext()){
tokens++;
}
rows++;
}

You assign no data to your variables at all in your scanning loop, and not only that, but you read from the Scanner twice while checking it for data only once, a dangerous thing to do.
while(in.hasNext()){ // **** checking once ****
while(in.next() != null){ // **** read in and waste a token here!
System.out.println(elements++);
}
in.nextLine(); // **** read in and waste a line here
rows++;
}
in.close();
I would:
Use two Scanner variables, one, fileScanner, to read in each line of text in the file,...
And one called lineScanner to read in each token on the line.
I'd use an outer while loop, that checks fileScanner.hasNextLine(), and then calls nextLine() to read the line into a String, say called line.
I'd then create a new Scanner with the line of String created, and assign it into a lineScanner variable.
I'd use an inner while loop that loops while lineScanner.hasNext(), and reads in the data into your your variables.
I'd close the inner lineScanner at the end of the outer while loop so as not to waste resources.
Alternatively, you could use String#split(...) to split the tokens in the line read in, and then parse the Strings into numbers. For example,
public List<RowData> loadDistances(String fname)
throws FileNotFoundException, NumberFormatException {
File file = new File(fname);
Scanner fileScanner = new Scanner(file);
List<RowData> rowList = new ArrayList<RowData>();
while (fileScanner.hasNextLine()) {
String line = fileScanner.nextLine();
String[] tokens = line.split("\\s+");
if (tokens.length != 3) {
// throw some custom exception
}
int rowNumber = Integer.parseInt(tokens[0].trim());
int xData = Integer.parseInt(tokens[1].trim());
double yData = Double.parseDouble(tokens[2].trim());
rowList.add(new RowData(rowNumber, xData, yData));
}
if (fileScanner != null) {
fileScanner.close();
}
return rowList;
}
Edit
By using a line Scanner, I recommend creating a second Scanner, passing in the line obtained from the first Scanner, and extracting data from this second Scanner. You could use a while loop if you didn't know how many tokens to expect, but your data appears to be well defined, with each line holding an int, int, and double, and we can use this information to help us extract the proper data. You could use code something like this:
// use previous same code as above except in the while loop:
while (fileScanner.hasNextLine()) {
String line = fileScanner.nextLine(); // get line
Scanner lineScanner = new Scanner(line); // create Scanner with it
int rowNumber = 0;
int xData = 0;
double yData = 0.0;
if (lineScanner.hasNextInt()) {
rowNumber = lineScanner.nextInt();
} else {
// throw a custom exception since int not found
}
if (lineScanner.hasNextInt()) {
xData = lineScanner.nextInt();
} else {
// throw a custom exception since int not found
}
if (lineScanner.hasNextDouble()) {
yData = lineScanner.nextDouble();
} else {
// throw a custom exception since double not found
}
rowList.add(new RowData(rowNumber, xData, yData));
if (lineScanner != null) {
lineScanner.close();
}
}

Related

Reading txt files in Java

I have program that has a section that requires me to read and append items to a txt file. I know how to do basic reading and appending but I am confused as to how I would read every 4th line in a txt file and then store it in a variable. Or even every alternate line.
Also, if there are double valued numbers, can I read it as a number and not a string?
To read say every fourth line from a text file you would read a line and update a counter. When the counter reaches 4, you save the line in a String variable. Something like this would do the job:
import java.io.*;
public class SkipLineReader {
public static void main(String[] args) throws IOException {
String line = "";
String savedLine = "";
int counter = 0;
FileInputStream fin = new FileInputStream("text_file.txt");
BufferedReader bufIn = new BufferedReader(new InputStreamReader(fin));
// Save every fourth line
while( (line = bufIn.readLine()) != null) {
counter++;
if( counter == 4 ) {
savedLine = line;
System.out.println(line);
}
}
}
}
To save every alternate line, you would save the line every time the counter reaches two and then reset the counter back to zero. Like this:
// Save every alternate line
while( (line = bufIn.readLine()) != null) {
counter++;
if( counter % 2 == 0 ) {
counter = 0;
savedLine = line;
System.out.println(line);
}
}
As for reading doubles from a file, you could do it with a BufferedReader and then use Double's parseDouble(string) method to retrieve the double value, but a better method is to use the Scanner object in java.util. The constructor for this class will accept a FileInputStream and there is a nextDouble() method that you can use to read a double value.
Here's some code that illustrates using a Scanner object to grab double values from a String (to read from a file, supply a FileInputStream into the Scanner class's constructor):
import java.util.*;
public class ScannerDemo {
public static void main(String[] args) {
String s = "Hello World! 3 + 3.0 = 6 true";
// create a new scanner with the specified String Object
Scanner scanner = new Scanner(s);
// use US locale to be able to identify doubles in the string
scanner.useLocale(Locale.US);
// find the next double token and print it
// loop for the whole scanner
while (scanner.hasNext()) {
// if the next is a double, print found and the double
if (scanner.hasNextDouble()) {
System.out.println("Found :" + scanner.nextDouble());
}
// if a double is not found, print "Not Found" and the token
System.out.println("Not Found :" + scanner.next());
}
// close the scanner
scanner.close();
}
}
This is my code example.
public static void main(String[] args) throws Exception {
// Read file by BufferedReader line by line.
BufferedReader reader;
try {
reader = new BufferedReader(new FileReader("test.txt"));
String line = reader.readLine();
while (line != null) {
line = line.trim();
System.out.println(line);
// Using regular expression to check line is valid number
if (!line.trim().equals("") && line.trim().matches("^\\d+||^\\d+(\\.)\\d+$")) {
double value = Double.valueOf(line.trim());
System.out.println(value);
} else {
String value = line.trim();
System.out.println(value);
}
// Read next line
line = reader.readLine();
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}

Return array initialized inside try/catch

I am creating a program which creates reads a file into an array separating which file into a different index value in the array.
static String[] readFile () {
int count = 0;
try {
File file = new File("input.txt"); // create file
Scanner scanner = new Scanner(file); // create scanner associated to file
// counts number of lines
while (scanner.hasNextLine()) {
scanner.nextLine();
count++;
}
// reads file into array
while (scanner.hasNextLine()) {
String[] data = new String[count];
int len = data.length;
for (int i = 0; i <= len; i++) {
data[i] = scanner.nextLine();
}
}
} catch (Exception e) {
System.out.println("File not found!!!");
System.exit(0);
}
return data;
}
The problem is that when trying to return the variable data I get an error saying 'cannot resolve symbol data" because it is initialized in a try-catch block. I have tried doing this but it returns the value null because the variable's length is determined by the variable count whose's value is also determined in a catch block. Thanks in advance!
You can use #Sweeper advice from comments. It will be looks like this.
static ArrayList<String> readFile () {
ArrayList<String> data = new ArrayList<>();
try {
File file = new File("input.txt"); // create file
Scanner scanner = new Scanner(file); // create scanner associated to file
while (scanner.hasNextLine()) {
data.add(scanner.nextLine()) ;
}
} catch (Exception e) {
e.printStackTrace();
}
return data;
}
But if you want to stay with your current code, you can initialize data by null out of try block. And also you need to reset Scanner. Your code will be looking something like this. Note, that in the for loop you must use condition <len not <=len.
static String[] readFile () {
String[] data = null;
try {
File file = new File("input.txt"); // create file
Scanner scanner = new Scanner(file); // create scanner associated to file
// counts number of lines
int count = 0;
while (scanner.hasNextLine()) {
scanner.nextLine();
count++;
}
scanner.close(); // don't forget about closing resources
data = new String[count];
// reads file into array
scanner = new Scanner(file);
for (int i = 0; i < len; i++) {
data[i] = scanner.nextLine();
}
scanner.close();
} catch (Exception e) {
e.printStackTrace();
}
return data;
}
Here are some similar questions with answers:
Java: Reading a file into an array
Read text file into an array
Also, I want to point at the try-with-resources statement - the Scanner object should be closed or initialized inside it.
Additionally, System.exit(0); is not a good way to stop a method, because all finally blocks around it wouldn't be executed in this case.
you are having 2 problems the firsthappens because the variable data is declared in the try-catch block ¿what if an instruction throws an exeption and the variable data is never declared? in this case ¿what is going to be returned?, the solution is to declare the variable data before the try-catch block, the second happens because when you invoke nextLine() the Scanner object mantains its state so when you try to invoke nextLine() again after go through the whole file it is in the last line (there is not next line), you can solve it invoking close() and then initialize the scanner object again this will reset the state:
static String[] readFile () {
Scanner scanner = null;
int count = 0;
String[] data = null;
try {
File file = new File("C:\\Users\\Mulé\\Desktop\\doc.txt"); // create file
scanner = new Scanner(file); // create scanner associated to file
// counts number of lines
while (scanner.hasNextLine()) {
scanner.nextLine();
count++;
}
scanner.close();
scanner = new Scanner(file);
// reads file into array
data = new String[count];
for (int i = 0; i < data.length; i++) {
data[i] = scanner.nextLine();
}
} catch (Exception e) {
System.out.println("File not found!!!");
System.exit(0);
}
return data;
}

Overwriting a line in java txt file

So I have created this method which at the end displays the whole line because i am displaying the array after converting and editing it. So my Question is how can i know overwrite the array to the same line i grabbed it from. thanks in advance and here is my code.
public void getData(String path, String accountNumber) {
try {
FileInputStream fis = new FileInputStream(path);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
System.out.println("Please Enter the Deposit amount That you would like to add.");
Scanner sn = new Scanner (System.in);
int add = sn.nextInt();
String str;
while ((str = br.readLine()) != null) {
if (str.contains(accountNumber)) {
String[] array = str.split(" ");
int old = Integer.parseInt(array[3]);
int Sum= old + add;
String Sumf = Integer.toString(Sum);
array[3] = Sumf;
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);}
break;
}
}
} catch (Exception ex) {
System.out.println(ex);
}
}
i am using string accountNumber to grab the specific line that i need. after getting the line i am changing it to an array while splitting the index with str.split(" "); . After that i know that i need to edit index number [3]. so i do so and then i put it back into the array. the final thing i need to do is to right the array back now.
You can keep track of the input from the file you are reading and write it back with the modified version.
public void getData(String path, String accountNumber) {
try {
FileInputStream fis = new FileInputStream(path);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
System.out.println("Please Enter the Deposit amount That you would like to add.");
Scanner sn = new Scanner (System.in);
int add = sn.nextInt();
String line; // current line
String input = ""; // overall input
while ((line = br.readLine()) != null) {
if (line.contains(accountNumber)) {
String[] array = line.split(" ");
int old = Integer.parseInt(array[3]);
int Sum= old + add;
String Sumf = Integer.toString(Sum);
array[3] = Sumf;
// rebuild the 'line' string with the modified value
line = "";
for (int i = 0; i < array.length; i++)
line+=array[i]+" ";
line = line.substring(0,line.length()-1); // remove the final space
}
// add the 'line' string to the overall input
input+=line+"\n";
}
// write the 'input' String with the replaced line OVER the same file
FileOutputStream fileOut = new FileOutputStream(path);
fileOut.write(input.getBytes());
fileOut.close();
} catch (Exception ex) {
System.out.println(ex);
}
}
This is how i understand the question that you have a file you will read it line by line and will make some changes and want to write it again at the same position. Create a new temp file and write the contents to the temp file, if changed write the changed result if not write it as it is.
And at last rename the temp to your original file name

java bufferedReader. how to read parts of a line

Ok now, here's my question. I wrote an algorithm to do specific things. Currently I create my processes myself in the class constructor and store them in a priority queue. However I want to be able to write a .txt file with multiple lines. Each line will represent a process with its different attributes separated by space. Here's what my .txt will look like:
P1 0 8
P2 1 4
P3 2 9
P4 3 3
END 4 9999
p1, p2... etc are the names of each process. Then the second column is the first attribute and the third column is the second attribute.
I need to be able to read each column at a time and store the value in my processes. How can I read those values and distinguish between them? (treat them as separate things)
So you want to read the file line-by-line and separate each line?
BufferReader in=new BufferedReader...
String line;
while ((line=in.readLine())!=null) {
String[] data=line.split(" ");
//now, data will be a array which contains the data
//data[0] = the first item in the line
//data[1] = the first number
//data[2] = the second number
}
Have a look at the java.util.Scanner class, it can help to read separate tokens from a Reader.
It has methods to read the next token as an integer, as a string or many other types. There are also some examples in the class Javadoc...
You got both whitespace (seperating the attributes) and new line (seperates the whole process information) as seperators.
Using a BufferedReader, you could either read a whole line (reader.readLine()) to parse one whole process information and use String.split() to seperate the attributes (edit: see answer from dyslabs).
An obviously more performant (but less intuitive) approach is to read single characters (reader.read()) and check if you either read a whitespace- or a new-line-character:
// caution: code is not tested but shows the general approach
List<ProcessInformation> processInfo = new ArrayList<>();
String pInfoStr = new String[3];
int processInfoIndex = 0;
String[] processInfoHolder = new String[3];
String processInfo = "";
int c;
while( (c = reader.read()) != -1 ) {
if (Character.isWhitespace(c)) {
processInfoHolder[processInfoIndex++] = processInfo;
processInfoStr = "";
}
else if (c == 10) { // not sure if correct codepoint for whitespace
processInfo.add(new ProcessInfo(processInfoHolder));
processInfoIndex = 0;
}
else {
processInfoStr += c;
}
}
You could even more optimize this method by using StringBuilder.
In order to be able to read a file line by line I use readLine() != null while in order to retrieve the values separated by whitespace, use the split method and store each value of a single line in an array,
here's how I implemented your example:
public static void main(String[] args) {
// TODO Auto-generated method stub
BufferedReader buffer;
FileReader fileReader;
String p1[] = new String[4];
String p2[] = new String[4];
String p3[] = new String[4];
String p4[] = new String[4];
String end[] = new String[4];
try {
fileReader = new FileReader(new File("file.txt"));
buffer = new BufferedReader(fileReader);
String line;
line = buffer.readLine();
// ============= Read the fist line =============
p1 = line.split("\\s+");
while((line = buffer.readLine()) != null) {
// ============= Read the second line =============
p2 = line.split("\\s+");
// ============= Read the third line =============
if((line = buffer.readLine()) != null) {
p3 = line.split("\\s+");
}
// ============= Read the forth line =============
if((line = buffer.readLine()) != null) {
p4 = line.split("\\s+");
}
// ============= Read the last line =============
if((line = buffer.readLine()) != null) {
end = line.split("\\s+");
}
}
fileReader.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int v1[] = new int[3];
int v2[] = new int[3];
int v3[] = new int[3];
int v4[] = new int[3];
int v_end[] = new int[3];
for (int i = 0 ; i < p1.length; i++)
System.out.print(p1[i]+ " ");
System.out.println();
for (int i = 0 ; i < p2.length; i++)
System.out.print(p2[i]+ " ");
System.out.println();
for (int i = 0 ; i < p3.length; i++)
System.out.print(p3[i]+ " ");
System.out.println();
for (int i = 0 ; i < p4.length; i++)
System.out.print(p4[i]+ " ");
System.out.println();
for (int i = 0 ; i < end.length; i++)
System.out.print(end[i]+ " ");
}

Method to find string inside of the text file. Then getting the following lines up to a certain limit

So this is what I have so far :
public String[] findStudentInfo(String studentNumber) {
Student student = new Student();
Scanner scanner = new Scanner("Student.txt");
// Find the line that contains student Id
// If not found keep on going through the file
// If it finds it stop
// Call parseStudentInfoFromLine get the number of courses
// Create an array (lines) of size of the number of courses plus one
// assign the line that the student Id was found to the first index value of the array
//assign each next line to the following index of the array up to the amount of classes - 1
// return string array
}
I know how to find if a file contains the string I am trying to find but I don't know how to retrieve the whole line that its in.
This is my first time posting so If I have done anything wrong please let me know.
You can do something like this:
File file = new File("Student.txt");
try {
Scanner scanner = new Scanner(file);
//now read the file line by line...
int lineNum = 0;
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
lineNum++;
if(<some condition is met for the line>) {
System.out.println("ho hum, i found it on line " +lineNum);
}
}
} catch(FileNotFoundException e) {
//handle this
}
Using the Apache Commons IO API https://commons.apache.org/proper/commons-io/ I was able to establish this using FileUtils.readFileToString(file).contains(stringToFind)
The documentation for this function is at https://commons.apache.org/proper/commons-io/javadocs/api-2.4/org/apache/commons/io/FileUtils.html#readFileToString(java.io.File)
Here is a java 8 method to find a string in a text file:
for (String toFindUrl : urlsToTest) {
streamService(toFindUrl);
}
private void streamService(String item) {
try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
stream.filter(lines -> lines.contains(item))
.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
When you are reading the file, have you considered reading it line by line? This would allow you to check if your line contains the file as your are reading, and you could then perform whatever logic you needed based on that?
Scanner scanner = new Scanner("Student.txt");
String currentLine;
while((currentLine = scanner.readLine()) != null)
{
if(currentLine.indexOf("Your String"))
{
//Perform logic
}
}
You could use a variable to hold the line number, or you could also have a boolean indicating if you have passed the line that contains your string:
Scanner scanner = new Scanner("Student.txt");
String currentLine;
int lineNumber = 0;
Boolean passedLine = false;
while((currentLine = scanner.readLine()) != null)
{
if(currentLine.indexOf("Your String"))
{
//Do task
passedLine = true;
}
if(passedLine)
{
//Do other task after passing the line.
}
lineNumber++;
}
This will find "Mark Sagal" in Student.txt. Assuming Student.txt contains
Student.txt
Amir Amiri
Mark Sagal
Juan Delacruz
Main.java
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
final String file = "Student.txt";
String line = null;
ArrayList<String> fileContents = new ArrayList<>();
try {
FileReader fReader = new FileReader(file);
BufferedReader fileBuff = new BufferedReader(fReader);
while ((line = fileBuff.readLine()) != null) {
fileContents.add(line);
}
fileBuff.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
System.out.println(fileContents.contains("Mark Sagal"));
}
}
I am doing something similar but in C++. What you need to do is read the lines in one at a time and parse them (go over the words one by one). I have an outter loop that goes over all the lines and inside that is another loop that goes over all the words. Once the word you need is found, just exit the loop and return a counter or whatever you want.
This is my code. It basically parses out all the words and adds them to the "index". The line that word was in is then added to a vector and used to reference the line (contains the name of the file, the entire line and the line number) from the indexed words.
ifstream txtFile;
txtFile.open(path, ifstream::in);
char line[200];
//if path is valid AND is not already in the list then add it
if(txtFile.is_open() && (find(textFilePaths.begin(), textFilePaths.end(), path) == textFilePaths.end())) //the path is valid
{
//Add the path to the list of file paths
textFilePaths.push_back(path);
int lineNumber = 1;
while(!txtFile.eof())
{
txtFile.getline(line, 200);
Line * ln = new Line(line, path, lineNumber);
lineNumber++;
myList.push_back(ln);
vector<string> words = lineParser(ln);
for(unsigned int i = 0; i < words.size(); i++)
{
index->addWord(words[i], ln);
}
}
result = true;
}
Here is the code of TextScanner
public class TextScanner {
private static void readFile(String fileName) {
try {
File file = new File("/opt/pol/data22/ds_data118/0001/0025090290/2014/12/12/0029057983.ds");
Scanner scanner = new Scanner(file);
while (scanner.hasNext()) {
System.out.println(scanner.next());
}
scanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("usage: java TextScanner1"
+ "file location");
System.exit(0);
}
readFile(args[0]);
}
}
It will print text with delimeters

Categories