Java parse .txt file - java

I am trying to run the below file TemplateMaker.java in Netbeans IDE 8.0.2 and am running into the following error message. Netbeans shows no red indicators for me to fix. Please help.
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:907)
at java.util.Scanner.next(Scanner.java:1416)
at templatemaker.TemplateMaker.processLine(TemplateMaker.java:48)
at templatemaker.TemplateMaker.processLineByLine(TemplateMaker.java:35)
at templatemaker.TemplateMaker.main(TemplateMaker.java:17)
Java Result: 1
Here is my source code:
package templatemaker;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Scanner;
public class TemplateMaker {
public static void main(String [] args)
throws IOException {
TemplateMaker parser = new TemplateMaker("Book1.txt");
parser.processLineByLine();
log("Done.");
}
/**
Constructor.
#param aFileName full name of an existing, readable file.
*/
public TemplateMaker(String aFileName){
fFilePath = Paths.get(aFileName);
}
/** Template method that calls {#link #processLine(String)}.
* #throws java.io.IOException */
public final void processLineByLine() throws IOException {
try (Scanner scanner = new Scanner(fFilePath, ENCODING.name())){
while (scanner.hasNextLine()){
processLine(scanner.nextLine());
}
}
}
protected void processLine(String aLine){
//use a second Scanner to parse the content of each line
Scanner scanner = new Scanner(aLine);
scanner.useDelimiter("=");
if (scanner.hasNext()){
//assumes the line has a certain structure
String name = scanner.next();
String value = scanner.next();
log("Name is : " + quote(name.trim()) + ", and Value is : " + quote(value.trim()));
}
else {
log("Empty or invalid line. Unable to process.");
}
}
// PRIVATE
private final Path fFilePath;
private final static Charset ENCODING = StandardCharsets.UTF_8;
private static void log(Object aObject){
System.out.println(String.valueOf(aObject));
}
private String quote(String aText){
String QUOTE = "'";
return QUOTE + aText + QUOTE;
}
}

Your processLine() is expecting a "name=value" pair. And as MightyPork said you are checking hasNext() once, and then read twice. So if that line does not have an = symbol this will break as scanner wont get the next() token. You should add two hasNext() checks. Ideally you dont need a scanner here. Since you are always expecting two tokens delimited by = you can simply rely on java.util.StringTokenizer as
protected void processLine(String aLine){
StringTokenizer st = new StringTokenizer(aLine, "=");
if(st.countTokens() == 2) {
log("Name is : " + quote(st.nextToken().trim()) + ", and Value is : " + quote(st.nextToken().trim()));
} else {
log("Empty or invalid line. Unable to process.");
}
}

As the stacktrace indicates, the exception was thrown when scanner.next() was called
at java.util.Scanner.next(Scanner.java:1416)
if (scanner.hasNext()){
//assumes the line has a certain structure
String name = scanner.next(); // checked by hasNext()
String value = scanner.next(); // not checked by hasNext()
log("Name is : " + quote(name.trim()) + ", and Value is : " + quote(value.trim()));
}
The error must be in the second .next(). You check if the scanner has a next token, but you call .next() twice. So I assume there is 1 token left and you read twice. Also from the API the next() method:
Throws:
NoSuchElementException - if no more tokens are available
IllegalStateException - if this scanner is closed
You can check that easily by adding a System.out.println statement and check what's the last one before the exception (after the first or second call of next())

Related

Double string output from while loop

I am trying to make simple one-Class code to copy some definite files (photos) from one folder to another according to a list. The list is kept in separate txt file.
Finally I've got file not found error, so I divided entire code into parts and tested each of them with console output.
And that what I found in scanner while loop:
So the code:
import java.io.File;
import java.util.Scanner;
import java.io.FileNotFoundException;
public class Sandy2 {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
File f = new File("D:\\\\Javasorter\\List.txt");
Scanner in;
in = new Scanner(f).useDelimiter("[?! .,;:\t\r\n\f\'\"]");
String word, pathbuf1, pathbuf2;
while (in.hasNext()) {
word = in.next().toLowerCase();
System.out.println(word);
Thread.sleep(1000);
pathbuf1 = "\\IMG_" + word + ".CR2";
pathbuf2 = "\\IMG_" + word + ".CR2";
System.out.println(pathbuf1);
System.out.println(pathbuf2);
}
}
}
Expected output:
9452
\IMG_9452.CR2
\IMG_9452.CR2
9475
\IMG_9475.CR2
\IMG_9475.CR2
and so on until list has next, but
Output:
9452
\IMG_9452.CR2
\IMG_9452.CR2
\IMG_.CR2
\IMG_.CR2
9475 \IMG_9475.CR2
\IMG_9475.CR2
\IMG_.CR2
\IMG_.CR2
and so on///
Copying command is added in the same loop in full version program, where "\IMG_9452.CR2" is attached to path srting
So, after the first file copied I got error, because of course there is no "IMG_.CR2" file.
Does anybody know why \IMG_.CR2 doubles in each loop iteration?
Many thanks!
Your problem is in the .useDelimiter("[?! .,;:\t\r\n\f\'\"]"), because Scanner will read spaces between lines as string object, so you have to remove it or change it if you still need to use Delimiter.
Also, You can write the file path with forward slashes / then it will be more readable and OS independent, and try to use try-with-resource to prevent source leak.
Consider this code:
public static void main(String[] args) throws Exception {
try (Scanner in = new Scanner(new File("D:/Javasorter/List.txt"))) {
// in.useDelimiter("[?! .,;:\t\r\n\f\'\"]");
String word, pathbuf1, pathbuf2;
while (in.hasNext()) {
word = in.next().toLowerCase();
System.out.println(word);
Thread.sleep(1000);
pathbuf1 = "\\IMG_" + word + ".CR2";
pathbuf2 = "\\IMG_" + word + ".CR2";
System.out.println(pathbuf1);
System.out.println(pathbuf2);
}
}
}
If you want to use Delimiter for some cases, you can use string trim and then check if string is empty, like:
public static void main(String[] args) throws Exception {
try (Scanner in = new Scanner(new File("D:/Javasorter/List.txt"))) {
in.useDelimiter("[?! .,;:\t\r\n\f\'\"]");
String word, pathbuf1, pathbuf2;
while (in.hasNext()) {
word = in.next().trim().toLowerCase();
if (!word.isEmpty()) {
System.out.println(word);
Thread.sleep(1000);
pathbuf1 = "\\IMG_" + word + ".CR2";
pathbuf2 = "\\IMG_" + word + ".CR2";
System.out.println(pathbuf1);
System.out.println(pathbuf2);
}
}
}
}
remove the variable pathbuf2 completely and you will not have any more of the duplicates

Read a line and push into a line-stack until the end of file

I have to do a program and unfortunately I have no idea where to start. It's like we were doing very basic coding and then my teacher went on maternity leave and our substitute thinks we are further along then we actually are. I know how to ready from a file, but I do not know how to put the line into a stack from there.
These are the instructions
1) Read a line and push into a line-stack until the end of file 2) While line_stack is not empty a. Pop one element out and process the following i. Split elements in this line (i.e. numbers) using StringTokenzier ii. Push all numbers into number-stack iii. While number_stack is not empty 1. Pop a number 2. Print a character using that ascii number
If I understand the problem correctly you need to:
Represent a line as a java.lang.String.
Then using java.util.Stack create a Stack< String> and put all the lines there.
Use java.util.StringTokenizer to split each line into multiple parts. Each part will be a String itself.
Turn each part of the line into a number using Integer.valueOf(String)
Put all the numbers into a Stack< Integer>.
Print the right character for each number by casting integer value to char.
I think this may be the solution for your problem:
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Stack;
import java.util.StringTokenizer;
public class LinesProcessor {
private static Stack<String> readLinesFromFile(String fileName) throws IOException {
Stack<String> lines = new Stack<>();
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)))) {
String line = null;
while ((line = br.readLine()) != null) {
lines.push(line);
}
}
return lines;
}
private static void processNumbers(Stack<Integer> stackOfNumbers) {
while (!stackOfNumbers.empty()) {
Integer number = stackOfNumbers.pop();
System.out.print((char) number.intValue());
}
}
private static void processLine(String line) {
StringTokenizer tokenizer = new StringTokenizer(line, " ");
Stack<Integer> stackOfNumbers = new Stack<>();
while (tokenizer.hasMoreTokens()) {
Integer number = Integer.valueOf(tokenizer.nextToken());
stackOfNumbers.push(number);
}
processNumbers(stackOfNumbers);
}
private static void processLines(Stack<String> stackOfLines) {
while (!stackOfLines.empty()) {
String currentLine = stackOfLines.pop();
processLine(currentLine);
}
}
public static void main(String[] args) throws IOException {
if (args.length < 1) {
System.out.println("Name of file missing");
System.exit(1);
}
String fileName = args[0];
Stack<String> stackOfLines = readLinesFromFile(fileName);
processLines(stackOfLines);
}
}

method to find and search files JAVA [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I need help with a method that finds a specific file and then prints out a line of text from that file. The line of text is printed if the string typed in the console matches a string from that line of text. For example if I were to call java Find ring report.txt address.txt Homework.java it should print something like:
report.txt: has broken up an internationa ring of DVD bootleggers that
address.txt: Kris Kringle, North Pole
address.txt: Homer Simpson, Springfield
Homework.java: String file name;
The specified word is always the first command line argument.
This is what I have so far:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
/**
* Code for E11.8. Searches all files specified on the command line and prints out all lines
containing a specified word.
* #Michael Goedken
*/
public class Find
{
/**
Searches file for a word, prints out all lines containing that word.
#param wordToFind the word to find
#param filename the filename for the file to search
*/
public static void findAndPrint(String wordToFind, String filename)
{
String input = args[0];
for (int i = 1; i < args.length; i++)
{
System.out.println(" File " + args[i]);
File one = new File(args[i]);
Scanner in = new Scanner(one);
while (in.hasNext())
{
String line = in.nextLine();
if (line.contains(input))
{
System.out.println(line);
}
}
}
}
/**
First argument of the main method should be the word to be searched
For other arguments of the main method, store the file names to be examined
*/
public static void main(String[] args)
{
// call findAndPrint for each text file
}
}
You're trying to access the array args[] which is not in the scope of the function findAndPrint(). You need to pass args[0] as an argument to the function call statement in the main method:
public static void main(String[] args){
findAndPrint(args[0], args[1]); //for report.txt
findAndPrint(args[0], args[2]); //for address.txt
}
args is an argument of the main method. It is a String array that stores the individual command line inputs. In your case, the contents of the array args[] are = {"ring", "reports.txt", "address.txt", "Homework.java"}.
You can modify your findAndPrint() function in this way now:
static void findAndPrint(String wordToFind, String filename){
Scanner fscan = new Scanner(new File(filename));
String str = "";
while((str = fscan.nextLine()) != null){
if(str.contains(wordToFind))
System.out.println(str);
}
}
I've added main arguments. I haven't ran the code, so that's on you to debug and test.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
/**
* Code for E11.8. Searches all files specified on the command line and prints out all lines containing a specified word.
* #Michael Goedken
*/
public class Find {
/** Searches file for a word, prints out all lines containing that word.
#param wordToFind the word to find
#param filename the filename for the file to search
*/
public static void findAndPrint(String wordToFind, String filename) {
System.out.println(" File " + filename);
File one = new File(filename);
Scanner in;
try {
in = new Scanner(one);
while (in.hasNext()) {
String line = in.nextLine();
if (line.contains(wordToFind)) {
System.out.println(line);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
int length = args.length;
if (length > 0 ) {
String wordToFind = args[0];
// now gather file names, bypassing first string
for (int ii = 1; ii < length; ii++) {
findAndPrint(wordToFind, args[ii]);
}
}
}
}
This seems to work as a solution!
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Scanner;
/**
* Code for E11.8. Searches all files specified on the command line and prints out all lines
containing a specified word.
* #Michael Goedken
*/
public class Find
{
/**
Searches file for a word, prints out all lines containing that word.
#param wordToFind the word to find
#param filename the filename for the file to search
*/
public static void findAndPrint(String wordToFind, String filename) throws FileNotFoundException
{
Scanner in = new Scanner(new FileReader(filename));
String input = wordToFind;
while (in.hasNext())
{
String line = in.nextLine();
if (line.contains(input))
{
System.out.println(line);
}
}
}
/**
First argument of the main method should be the word to be searched
For other arguments of the main method, store the file names to be examined
*/
public static void main(String[] args) throws FileNotFoundException
{
// call findAndPrint for each text file
findAndPrint("tt", "/Users/MichaelGoedken/Desktop/mary.txt");
findAndPrint("0", "/Users/MichaelGoedken/Desktop/transactions.txt");
}
}
Ok, I think I get your issue now.
You can call your method from the main:
public static void main(String[] args) {
//may need to throw file not found exception here
findAndPrint();
}
Then you need to remove the arguments from your method:
public static void findAndPrint() throws FileNotFoundException {
Scanner in = new Scanner(new FileReader("C:\\yourfilepath\\actualfile.txt"));
//you can get user input etc here if necessary
String input = "pass";
while (in.hasNext()) {
String line = in.nextLine();
if (line.contains(input)) {
System.out.println(line);
}
}
}

Filewriter and spaces?

I was asked to write an assignment wherein the user would be prompted to input a key and/or a value.
So far, here is my code:
import java.util.Scanner;
import java.io.*;
class bTree
{
//Fields
static Scanner input = new Scanner(System.in);
static boolean done = false;
public static void main(String args[])throws Exception
{
FileWriter fWriter = new FileWriter("data.txt");
do
{
System.out.print("Enter command: ");
String enter[] = input.nextLine().split(" ", 3);
if(enter[0].toLowerCase().equals("insert"))
{
fWriter.write(enter[1] + "\n" + enter[2] + "\n");
fWriter.flush();
}
else if(enter[0].toLowerCase().equals("select"))
{
FileReader fReader = new FileReader("data.txt");
Scanner fileInput = new Scanner(fReader);
while(fileInput.hasNext() && done == false)
{
if(fileInput.nextLine().equals(enter[1]))
{
System.out.println(fileInput.nextLine());
done = true;
}
else
{
fileInput.nextLine();
}
}
done = false;
}
else if(enter[0].toLowerCase().equals("update"))
{
fWriter.write(enter[2]);
fWriter.flush();
}
else if(enter[0].toLowerCase().equals("exit"))
{
System.exit(0);
}
}
while(true);
}
}
Problem: When i open the data.txt, there are no spaces. So if i enter "insert 1001 gen" and "10001 genny", in notepad, it would come out as "1001gen10001genny". Any suggestions?
The problem is that notepad.exe is picky about line endings, and there are many possibilities. When you write "\n" to a FileWriter, it writes a single character, namely '\n'. But notepad expects the sequence "\r\n" instead. It shows a single "\n" as nothing.
Here is your code, slightly modified to work around some pitfalls.
package so7696816;
import java.io.FileReader;
import java.io.PrintWriter;
import java.util.Locale;
import java.util.Scanner;
public class Excercise {
public static void main(String args[]) throws Exception {
final Scanner input = new Scanner(System.in);
PrintWriter fWriter = new PrintWriter("data.txt");
while (true) {
System.out.print("Enter command: ");
String enter[] = input.nextLine().split(" ", 3);
final String command = enter[0].toLowerCase(Locale.ROOT);
if (command.equals("insert")) {
fWriter.println(enter[1]);
fWriter.println(enter[2]);
fWriter.flush();
} else if (command.equals("select")) {
FileReader fReader = new FileReader("data.txt");
Scanner fileInput = new Scanner(fReader);
while (fileInput.hasNextLine()) {
String key = fileInput.nextLine();
String value = fileInput.nextLine();
if (key.equals(enter[1])) {
System.out.println(value);
break;
}
}
fReader.close(); // don't leave files open
} else if (command.equals("update")) {
fWriter.write(enter[2]);
fWriter.flush();
} else if (command.equals("exit")) {
return;
} else {
System.err.println("Unknown command: " + command);
}
}
}
}
Remarks:
I used a PrintWriter instead of a FileWriter to get the line endings correct.
For the select command I closed the fReader after using it.
I avoided to type enter[0].toLowerCase() multiple times.
I used the proper variant of toLowerCase.
I added error handling for unknown commands.
I rewrote the select command to be a little more concise.
The problem is String enter[] = input.nextLine().split(" ", 3);, it kills the Spaces. So append a space after each array entry or write an additional " " everytime you use fWriter.write.
look here
As already stated the line feed character is incorrect for notepad. Alternatively you could wrap that FileWriter in a BufferedWriter and use the newLine method to always insert the correct line feed.
I think you are running your program in UNIX. In unix system "\r\n" is the line feed.
If you are running your program in Windows, I think the file should contain something like this.
1001
gen
10001
genny

take in different files

Hi I am writing a program that takes in a textfile and goes through it and if it finds the message #GetFile "filename.txt" goes and gets that and stores it in the same arraylist as the first textfile but I am not able to think through the problem because if a file calls another file which calls another file and that file might be able to call another file. And I am wondering if I can call a method that contains a scanner class over and over again.
This is file one
#GetFile "fileSecond.txt"
----------
this is file two
#GetFile "fileThird.txt"
----------
this is text file three
#GetFile "fileOne.txt"
this is how different text file have it the --- <- is different textfile not same page sorry I didn't know how to show it here
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
public class Project3
{
public static void main(String[] args)
{
ArrayList<String> text = new ArrayList<String>();
File dictionaryFile = null; // set default value
File dictionaryFileTwo = null;
Scanner inputFile = null; // set default value
Scanner inputFileTwo = null;
// use a try-catch block to handle situations when the file is not present
keyboard = new Scanner(System.in);
// fileName = keyboard.next();
String fileName = "test1.txt";
try {
dictionaryFile = new File(fileName); // declare the file
inputFile = new Scanner(dictionaryFile);
} catch (Exception e) {
// if File object creation failed (such as when file is not there)
// then this code gets executed.
// print the directory where this program expects to find dictionary
System.out.println(System.getProperty("user.dir"));
// ensure file exists and is in the correct directory
if (!dictionaryFile.exists()) {
System.out.println("*** Error *** \n"
+ "Your text file has the wrong name or is "
+ "in the wrong directory. \n"
+ "Aborting program...\n\n");
System.exit(-1); // Terminate the program
}
}// end catch
// while there are words in the input file, add them to the dictionary
while (inputFile.hasNext()) {
if(inputFile.next().startsWith("#GetFile")){
String filing = inputFile.next();
System.out.println("HEY THIS IS THE FILE THAT I FOUND "+ filing);
String fileNameSecond = filing;
try {
dictionaryFileTwo = new File(filing); // declare the file
inputFile = new Scanner(dictionaryFile);
}catch (Exception e) {
// if File object creation failed (such as when file is not there)
// then this code gets executed.
// print the directory where this program expects to find dictionary
System.out.println(System.getProperty("user.dir"));
// ensure file exists and is in the correct directory
if (!dictionaryFile.exists()) {
System.out.println("*** Error *** \n"
+ "Your text file has the wrong name or is "
+ "in the wrong directory. \n"
+ "Aborting program...\n\n");
System.exit(-1); // Terminate the program
}
}// end catch
} else {
text.add(inputFile.nextLine());
}
}
for(int i =0; i < text.size(); i++){
System.out.println(text.get(i));
}
}
}
The basic algorithm would be:
open the output-file
ExpandIncudes(input-file, output-file) {
open input-file
while (read line from input)
if (line is-a #include) then
ExpandIncudes(input-file)
else
write line to output-file
endif
next line
}
And no, I don't think you could keep reusing the same scanner for reading different files.
Cheers. Keith.
Your question is a little muddled but it seems you need to investigate how to use some recursion here.
You'd just need a method that upon finding the "#GetFile" directive would then grab the file name to get and call the method again with this name.
public void parseFile(String filename) {
//readline while not end of file...
//is line a #GetFile directive?
//parseFile(newFilename)
}
... or something like that
Sibghatuk,
I'm going to presume that your homework's been handed in, so it's "safe" to just hand you "the answer".
I'd do it something like this:
package forums;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
public class HashInclude
{
private static final String[] INCLUDE_PATH =
System.getenv("INCLUDE_PATH").split(File.pathSeparator);
public static void main(String... args) {
try {
for ( String filename : filenames ) {
hashInclude(filename);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void hashInclude(String filename)
throws FileNotFoundException, IOException
{
BufferedReader reader = new BufferedReader(new FileReader(filename));
try {
String line = null;
int lineCount = 0;
while ( (line=reader.readLine()) != null ) {
++lineCount;
if ( line.startsWith("#include ") ) {
String targetFilename = line.replaceFirst("^#include[ \t]*", "").trim();
if ( !targetFilename.matches("^[<\"][A-z0-9_]+\\.h[\">]$") )
// not a <valid.h> or a "valid.h"
throw new IncludeException(targetFilename, lineCount, filename);
// <valid.h> --> valid.h
targetFilename = targetFilename.substring(1, targetFilename.length()-1);
// search directories in the INCLUDE_PATH for targetFilename
for ( String dir : INCLUDE_PATH ) {
File targetFile = new File(dir, targetFilename); // c:/path/to/valid.h
if ( targetFile.exists() ) {
hashInclude( targetFile.getAbsolutePath() ); // <<-- recursive call
return;
}
} // next dir
throw new FileNotFoundException("File " + targetFilename
+ " not found in INCLUDE_PATH="+ System.getenv("INCLUDE_PATH"));
} else {
System.out.println(line);
}
} // next line
} finally {
reader.close();
}
}
}
class IncludeException extends RuntimeException {
private static final long serialVersionUID = 0L;
public IncludeException(String targetFilename, int lineCount, String filename) {
super("Invalid #include: " + targetFilename + " at " + lineCount + " " + filename);
}
}
I think that the above is a "reasaonbly elegant" solution to the problem... even if I do say so myself ;-)
Note that the hashInclude method recursively calls itself... recursion lends itself naturally to following an "arbitrary tree structure"... i.e. a tree whose precise structure is unknowable when you're writing the software... and therefore "recursion" is about the first thing pops into many programmers minds when they here the word "tree".
Please note that the above code implements a greatly-simplified version of the C preprocessor #include mechanism... but could (reasonably easily) be extended into a "proper preprocessor"... one that even (recursively) expands #defines.
Cheers. Keith.

Categories