Using scanner with a prompt and user input - java

I tried to do counting lines, words, character from user "inputted" file.
After this show counting and keep asking again.
If file doesn't exist print all data which have been counted during running.
Code:
public class KeepAskingApp {
private static int lines;
private static int words;
private static int chars;
public static void main(String[] args) {
boolean done = false;
//counters
int charsCount = 0, wordsCount = 0, linesCount = 0;
Scanner in = null;
Scanner scanner = null;
while (!done) {
try {
in = new Scanner(System.in);
System.out.print("Enter a (next) file name: ");
String input = in.nextLine();
scanner = new Scanner(new File(input));
while(scanner.hasNextLine()) {
lines += linesCount++;
Scanner lineScanner = new Scanner(scanner.nextLine());
lineScanner.useDelimiter(" ");
while(lineScanner.hasNext()) {
words += wordsCount++;
chars += charsCount += lineScanner.next().length();
}
System.out.printf("# of chars: %d\n# of words: %d\n# of lines: ",
charsCount, wordsCount, charsCount);
lineScanner.close();
}
scanner.close();
in.close();
} catch (FileNotFoundException e) {
System.out.printf("All lines: %d\nAll words: %d\nAll chars: %d\n",
lines, words, chars);
System.out.println("The end");
done = true;
}
}
}
}
But I can't understand why it always show output with no parameters:
All lines: 0
All words: 0
All chars: 0
The end
Why it omits all internal part.
It may be coz I'm using few scanners, but all look ok.
Any suggestions?
UPDATE:
Thanks all who give some hint. I rethinking all constructed and rewrite code with newly info.
To awoid tricky scanner input line, I used JFileChooser:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import javax.swing.JFileChooser;
public class KeepAskingApp {
private static int lines;
private static int words;
private static int chars;
public static void main(String[] args) {
boolean done = false;
// counters
int charsCount = 0, wordsCount = 0, linesCount = 0;
Scanner in = null;
Scanner lineScanner = null;
File selectedFile = null;
while (!done) {
try {
try {
JFileChooser chooser = new JFileChooser();
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
selectedFile = chooser.getSelectedFile();
in = new Scanner(selectedFile);
}
while (in.hasNextLine()) {
linesCount++;
lineScanner = new Scanner(in.nextLine());
lineScanner.useDelimiter(" ");
while (lineScanner.hasNext()) {
wordsCount++;
charsCount += lineScanner.next().length();
}
}
System.out.printf(
"# of chars: %d\n# of words: %d\n# of lines: %d\n",
charsCount, wordsCount, linesCount);
lineScanner.close();
lines += linesCount;
words += wordsCount;
chars += charsCount;
in.close();
} finally {
System.out.printf(
"\nAll lines: %d\nAll words: %d\nAll chars: %d\n",
lines, words, chars);
System.out.println("The end");
done = true;
}
} catch (FileNotFoundException e) {
System.out.println("Error! File not found.");
}
}
}
}

Couple of issues (actually there are many issues with your code, but I will address the ones directly related to the output you have posted):
First of all, the stuff in the catch block only happens if you get a FileNotFoundException; that's there to handle and recover from errors. I suspect you meant to put a finally block there, or you meant to do that after the catch. I suggest reading this tutorial on catching and handling exceptions, which straightforwardly describes try, catch, and finally.
Once you read that tutorial, come back to your code; you may find that you have a little bit of reorganizing to do.
Second, with the above in mind, it's obvious by the output you are seeing that you are executing the code in that catch block, which means you are getting a FileNotFoundException. This would be caused by one of two (possibly obvious) things:
The file you entered, well, wasn't found. It may not exist or it may not be where you expect. Check to make sure you are entering the correct filename and that the file actually exists.
The input string is not what you expect. Perhaps you read a blank line from previous input, etc.
Addressing reason 2: If there is already a newline on the input buffer for whatever reason, you will read a blank line with Scanner. You might want to print the value of input just before opening the file to make sure it's what you expect.
If you're seeing blank lines, just skip them. So, instead of this:
String input = in.nextLine();
scanner = new Scanner(new File(input));
Something like this instead would be immune to blank lines:
String input;
do {
input = in.nextLine().trim(); // remove stray leading/trailing whitespace
} while (input.isEmpty()); // keep asking for input if a blank line is read
scanner = new Scanner(new File(input));
And, finally, I think you can work out the reason that you're seeing 0's in your output. When you attempt to open the file with new Scanner(new File(input)); and it fails because it can't find the file, it throws an exception and the program immediately jumps to the code in your catch block. That means lines, words, and chars still have their initial value of zero (all code that modifies them was skipped).
Hope that helps.

Your println()s are in a catch block
} catch (FileNotFoundException e) {
System.out.printf("All lines: %d\nAll words: %d\nAll chars: %d\n",
lines, words, chars);
System.out.println("The end");
done = true;
}
That means you caught a FileNotFoundException. I think you can figure out from here.

Related

How to skip reading a line with scanner

I have read in a text file and am scanning said file. The question I have is how would I skip over lines that include a certain character (in my case lines that start with " // " and " " (whitespace).
Here is my code at the moment. Can someone point me in the right direction?
File dataFile = new File(filename);
Scanner scanner = new Scanner(dataFile);
while(scanner.hasNext())
{
String lineOfText = scanner.nextLine();
if (lineOfText.startsWith("//")) {
System.out.println(); // not sure what to put here
}
System.out.println(lineOfText);
}
scanner.close();
You will only want to execute the code within the while-loop if the line of text doesn't start with a / or whitespace. You can filter these out as seen below:
while(scanner.hasNext()) {
String lineOfText = scanner.nextLine();
if (lineOfText.startsWith("//") || lineOfText.startsWith(" ")) {
continue; //Exit this iteration if line starts with space or /
}
System.out.println(lineOfText);
}
As you are iterating over the lines of text in the file, use String's startsWith() method to check if the line starts with the sequences you are trying to avoid.
If it does, continue to the next line. Otherwise, print it.
while (scanner.hasNext()) {
String lineOfText = scanner.nextLine();
if (lineOfText.startsWith("//") || lineOfText.startsWith(" ") ) {
continue;
}
System.out.println(lineOfText);
}
Just use a continue like -
if (lineOfText.startsWith("//")) {
continue; //would skip the loop to next iteration from here
}
Detials - What is the "continue" keyword and how does it work in Java?
If you're just interested in printing out the lines of code that begin with a "//" then you should just use the continue keyword in java.
String lineOfText = scanner.nextLine();
if (lineOfText.startsWith("//")) {
continue;
}
See this post for more information regarding the "continue" keyword.
You can just insert "else" in your code like:
public static void main(String[] args) throws FileNotFoundException {
File dataFile = new File("testfile.txt");
Scanner scanner = new Scanner(dataFile);
while(scanner.hasNext())
{
String lineOfText = scanner.nextLine();
if (lineOfText.startsWith("//")) {
System.out.println();
}
else
System.out.println(lineOfText);
}
scanner.close();
}
}

Scanner restarting in Java

My task is to read a text file in chunks of 64 characters, and use 2 different processes called Substitution and Column Transposition to encrypt it. Then, I have to decrypt it and write it out to another file.
I have written and tested out both processes of encrypting and decrypting and it worked wonderfully. But then I tried to loop the processes in case more than 64 characters were in the input file.
As a test case, I tried a 128 character input file. Unfortunately, the result only gives me the first 64 characters twice. I've tracked the scanner position and it goes beyond 64, but the characters read start back from 0. I'm not sure what the problem is.
Here is the relevant part of my code:
public static void main(String[] args) {
//Declare variables
Scanner console = new Scanner(System.in);
String inputFileName = null;
File inputFile = null;
Scanner in = null;
do
{
//Check if there are enough arguments
try
{
inputFileName = args[1];
}
catch (IndexOutOfBoundsException exception)
{
System.out.println("Not enough arguments.");
System.exit(1);
}
catch (Exception exception)
{
System.out.println("There was an error. Please try again.");
System.exit(1);
}
//Check if Input File is valid
try
{
inputFile = new File(inputFileName);
in = new Scanner(inputFile);
outputFile = new File(outputFileName);
out = new Scanner(outputFile);
}
catch (FileNotFoundException exception)
{
System.out.println("Could not find input file.");
System.exit(1);
}
catch (Exception exception)
{
System.out.println("There was an error. Please try again.");
System.exit(1);
}
} while (outputFileName != null && !inputFile.exists());
//Encryption
//Prepare patterns
String subPattern = CreateSubstitutionPattern(hash);
int[] transPattern = CreateTranspositionPattern(hash);
//Apply patterns
String textContent = "";
String applySub = "";
String applyTrans = "";
do
{
textContent = Read64Chars(in);
applySub = applySub + ApplySubstitutionPattern(textContent, subPattern);
applyTrans = applyTrans + ApplyTranspositionPattern(applySub, transPattern);
} while (in.hasNext());
//Decryption
String encryptContent = "";
Scanner encrypt = new Scanner(applyTrans);
String removeTrans = "";
String removeSub = "";
do
{
encryptContent = Read64Chars(encrypt);
System.out.println(applyTrans);
removeTrans = removeTrans + RemoveTranspositionPattern(encryptContent, transPattern);
removeSub = removeSub + RemoveSubstitutionPattern(removeTrans, subPattern);
} while (encrypt.hasNext());
console.close();
in.close();
encrypt.close();
System.out.println(removeSub); //For temporary testing
}
public static String Read64Chars (Scanner in)
{
String textContent = "";
in.useDelimiter("");
for (int x=0; x<64; x++)
{
if (in.hasNext())
{
textContent = textContent + in.next().charAt(0);
}
}
return textContent;
}
Do note that I have more variables to fill in args[0] and args[2] but I removed them for simplicity.
I would like to know if it is true that once a scanner reads a portion of it's input, it "consumes" it, and that portion gets removed. Does the scanner reset itself when declared again through a method? For example, does the declaration only point to the input source of the original scanner, or the actual scanner with its current properties?
encrypt is a diffrent Scanner from in, which you advance by 64 characters when you first call Read64Chars. So, encrypt starts at the first character when you call Read64Chars(encrypt). It seems like you want to use the same Scanner both times.
Also, in the future please name your functions starting with a lowercase letter. I felt dirty typing that... :)
A proper solution to get the whole encrypted text would be a code like this
public static String encryptedTextFile (Scanner in)
{
//ArrayList<String> stringBlocksOf64Chars = new ArrayList<String>();
StringBuilder encryptedTxt = new StringBuilder();
String currentTxt = "";
while (in.hasNextLine()) {
String line = currentTxt + in.nextLine();
currentTxt = "";
int i = 0;
for( ; i < line.length()/64 ; i++){
currentTxt = line.substring(i * 64, (i+1)*64);
//TODO - encrypt the text before adding it to the list
encryptedTxt.append(currentTxt);//encryptedTxt.append(encrypt(currentTxt));
}
currentTxt = line.substring(i * 64, line.length());
}
encryptedTxt.append(currentTxt);
/*for(String str : stringBlocksOf64Chars)
System.out.println(str);*/
return encryptedTxt.toString();
}
Your loop for (int x=0; x<64; x++) makes sure that you read only first 64 characters always and not the complete file. To get around that you should actually read whole file line by line.
The above code block follows this idea.
Steps to break down the logic.
Read the file line by line using scanner.
Break each line into chunks of 64 characters and encrypt the block 64 characters at a time
Generate encrypted text adding the encrypted 64 characters.
Whatever you do first break down the logic/steps you want to use in your code to make it simpler to understand or code.
Break the lines into 64 characters

Java - How to read a big file word by word instead of line by line?

I'd like to read the "text8" corpus in Java and reformat some words. The problem is, in this 100MB corpus all words are on one line. So if I try to load it with BufferedReader and readLine, it takes away too much space at once and can't handle it to separate all the words in one list/array.
So my question: Is it possible in Java to read instead of line by line a corpus, to read it word by word? So for example because all words are on one line, to read for example 100 words per iteration?
you can try using Scanner and set the delimiter to whatever suits you:
Scanner input=new Scanner(myFile);
input.useDelimiter(" +"); //delimitor is one or more spaces
while(input.hasNext()){
System.out.println(input.next());
}
I would suggest you to use the "Character stream" with FileReader
Here is the example code from http://www.tutorialspoint.com/java/java_files_io.htm
import java.io.*;
public class CopyFile {
public static void main(String args[]) throws IOException
{
FileReader in = null;
FileWriter out = null;
try {
in = new FileReader("input.txt");
out = new FileWriter("output.txt");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
It reads 16 bit Unicode characters. This way it doesnt matter if your text is in one whole line.
Since you're trying to search word by word, you can easy read till you stumble upon a space and there's your word.
Use the next method of java.util.Scanner
The next method finds and returns the next complete token from this scanner. A
complete token is preceded and followed by input that matches the
delimiter pattern. This method may block while waiting for input to
scan, even if a previous invocation of Scanner.hasNext returned true.
Example:
public static void main(String[] args) {
Scanner sc = new Scanner (System.in);
String a = sc.next();
String b = sc.next();
System.out.println("First Word: "+a);
System.out.println("Second Word: "+b);
sc.close();
}
Input :
Hello Stackoverflow
Output :
First Word: Hello
Second Word: Stackoverflow
In your case use Scanner for reading the file and then use scannerobject.next() method for reading each token(word)
try(FileInputStream fis = new FileInputStream("Example.docx")) {
ZipSecureFile.setMinInflateRatio(0.009);
XWPFDocument file = new XWPFDocument(OPCPackage.open(fis));
ext = new XWPFWordExtractor(file);
Scanner scanner = new Scanner(ext.getText());
while(scanner.hasNextLine()) {
String[] value = scanner.nextLine().split(" ");
for(String v:value) {
System.out.println(v);
}
}
}catch(Exception e) {
System.out.println(e);
}

Reading a .txt file and excluding certain elements

In my journey to complete this program I've run into a little hitch with one of my methods. The method I am writing reads a certain .txt file and creates a HashMap and sets every word found as a Key and the amount of time it appears is its Value. I have managed to figure this out for another method, but this time, the .txt file the method is reading is in a weird format. Specifically:
more 2
morning's 1
most 3
mostly 1
mythology. 1
native 1
nearly 2
northern 1
occupying 1
of 29
off 1
And so on.
Right now, the method is returning only one line in the file.
Here is my code for the method:
public static HashMap<String,Integer> readVocabulary(String fileName) {
// Declare the HashMap to be returned
HashMap<String, Integer> wordCount = new HashMap();
String toRead = fileName;
try {
FileReader reader = new FileReader(toRead);
BufferedReader br = new BufferedReader(reader);
// The BufferedReader reads the lines
String line = br.readLine();
// Split the line into a String array to loop through
String[] words = line.split(" ");
// for loop goes through every word
for (int i = 0; i < words.length; i++) {
// Case if the HashMap already contains the key.
// If so, just increments the value.
if (wordCount.containsKey(words[i])) {
int n = wordCount.get(words[i]);
wordCount.put(words[i], ++n);
}
// Otherwise, puts the word into the HashMap
else {
wordCount.put(words[i], 1);
}
}
br.close();
}
// Catching the file not found error
// and any other errors
catch (FileNotFoundException fnfe) {
System.err.println("File not found.");
}
catch (Exception e) {
System.err.print(e);
}
return wordCount;
}
The issue is that I'm not sure how to get the method to ignore the 2's and 1's and 29's of the .txt file. I attempted making an 'else if' statement to catch all of these cases but there are too many. Is there a way for me to catch all the ints from say, 1-100, and exlude them from being Keys in the HashMap? I've searched online but have turned up something.
Thank you for any help you can give!
How about just doing wordCount.put(words[0],1) into wordcount for every line, after you've done the split. If the pattern is always "word number", you only need the first item from the split array.
Update after some back and forth
public static HashMap<String,Integer> readVocabulary(String toRead)
{
// Declare the HashMap to be returned
HashMap<String, Integer> wordCount = new HashMap<String, Integer>();
String line = null;
String[] words = null;
int lineNumber = 0;
FileReader reader = null;
BufferedReader br = null;
try {
reader = new FileReader(toRead);
br = new BufferedReader(reader);
// Split the line into a String array to loop through
while ((line = br.readLine()) != null) {
lineNumber++;
words = line.split(" ");
if (words.length == 2) {
if (wordCount.containsKey(words[0]))
{
int n = wordCount.get(words[0]);
wordCount.put(words[0], ++n);
}
// Otherwise, puts the word into the HashMap
else
{
boolean word2IsInteger = true;
try
{
Integer.parseInt(words[1]);
}
catch(NumberFormatException nfe)
{
word2IsInteger = false;
}
if (word2IsInteger) {
wordCount.put(words[0], Integer.parseInt(words[1]));
}
}
}
}
br.close();
br = null;
reader.close();
reader = null;
}
// Catching the file not found error
// and any other errors
catch (FileNotFoundException fnfe) {
System.err.println("File not found.");
}
catch (Exception e) {
System.err.print(e);
}
return wordCount;
}
To check if a String contains a only digits use StringĀ“s matches() method, e.g.
if (!words[i].matches("^\\d+$")){
// NOT a String containing only digits
}
This wont require checking exceptions and it doesnt matter if the number wouldnt fit inside an Integer.
Option 1: Ignore numbers separated by whitespace
Use Integer.parseInt() or Double.parseInt() and catch the exception.
// for loop goes through every word
for (int i = 0; i < words.length; i++) {
try {
int wordAsInt = Integer.parseInt(words[i]);
} catch(NumberFormatException e) {
// Case if the HashMap already contains the key.
// If so, just increments the value.
if (wordCount.containsKey(words[i])) {
int n = wordCount.get(words[i]);
wordCount.put(words[i], ++n);
}
// Otherwise, puts the word into the HashMap
else {
wordCount.put(words[i], 1);
}
}
}
There is a Double.parseDouble(String) method, which you could use in place of Integer.parseInt(String) above if you wanted to eliminate all numbers, not just integers.
Option 2: Ignore numbers everywhere
Another option is to parse your input one character at a time and ignore any character that isn't a letter. When you scan whitespace, then you could add the word generated by the characters just scanned in to your HashMap. Unlike the methods mentioned above, scanning by character would allow you to ignore numbers even if they appear immediately next to other characters.

Print data from file to array

I need to have this file print to an array, not to screen.And yes, I MUST use an array - School Project - I'm very new to java so any help is appreciated. Any ideas? thanks
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
public class HangmanProject
{
public static void main(String[] args) throws FileNotFoundException
{
String scoreKeeper; // to keep track of score
int guessesLeft; // to keep track of guesses remaining
String wordList[]; // array to store words
Scanner keyboard = new Scanner(System.in); // to read user's input
System.out.println("Welcome to Hangman Project!");
// Create a scanner to read the secret words file
Scanner wordScan = null;
try {
wordScan = new Scanner(new BufferedReader(new FileReader("words.txt")));
while (wordScan.hasNext()) {
System.out.println(wordScan.next());
}
} finally {
if (wordScan != null) {
wordScan.close();
}
}
}
}
Nick, you just gave us the final piece of the puzzle. If you know the number of lines you will be reading, you can simply define an array of that length before you read the file
Something like...
String[] wordArray = new String[10];
int index = 0;
String word = null; // word to be read from file...
// Use buffered reader to read each line...
wordArray[index] = word;
index++;
Now that example's not going to mean much to be honest, so I did these two examples
The first one uses the concept suggested by Alex, which allows you to read an unknown number of lines from the file.
The only trip up is if the lines are separated by more the one line feed (ie there is a extra line between words)
public static void readUnknownWords() {
// Reference to the words file
File words = new File("Words.txt");
// Use a StringBuilder to buffer the content as it's read from the file
StringBuilder sb = new StringBuilder(128);
BufferedReader reader = null;
try {
// Create the reader. A File reader would be just as fine in this
// example, but hay ;)
reader = new BufferedReader(new FileReader(words));
// The read buffer to use to read data into
char[] buffer = new char[1024];
int bytesRead = -1;
// Read the file to we get to the end
while ((bytesRead = reader.read(buffer)) != -1) {
// Append the results to the string builder
sb.append(buffer, 0, bytesRead);
}
// Split the string builder into individal words by the line break
String[] wordArray = sb.toString().split("\n");
System.out.println("Read " + wordArray.length + " words");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (Exception e) {
}
}
}
The second demonstrates how to read the words into an array of known length. This is probably closer to the what you actually want
public static void readKnownWords()
// This is just the same as the previous example, except we
// know in advance the number of lines we will be reading
File words = new File("Words.txt");
BufferedReader reader = null;
try {
// Create the word array of a known quantity
// The quantity value could be defined as a constant
// ie public static final int WORD_COUNT = 10;
String[] wordArray = new String[10];
reader = new BufferedReader(new FileReader(words));
// Instead of reading to a char buffer, we are
// going to take the easy route and read each line
// straight into a String
String text = null;
// The current array index
int index = 0;
// Read the file till we reach the end
// ps- my file had lots more words, so I put a limit
// in the loop to prevent index out of bounds exceptions
while ((text = reader.readLine()) != null && index < 10) {
wordArray[index] = text;
index++;
}
System.out.println("Read " + wordArray.length + " words");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
reader.close();
} catch (Exception e) {
}
}
}
If you find either of these useful, I would appropriate it you would give me a small up-vote and check Alex's answer as correct, as it's his idea that I've adapted.
Now, if you're really paranoid about which line break to use, you can find the values used by the system via the System.getProperties().getProperty("line.separator") value.
Do you need more help with the reading the file, or getting the String to a parsed array? If you can read the file into a String, simply do:
String[] words = readString.split("\n");
That will split the string at each line break, so assuming this is your text file:
Word1
Word2
Word3
words will be: {word1, word2, word3}
If the words you are reading are stored in each line of the file, you can use the hasNextLine() and nextLine() to read the text one line at a time. Using the next() will also work, since you just need to throw one word in the array, but nextLine() is usually always preferred.
As for only using an array, you have two options:
You either declare a large array, the size of whom you are sure will never be less than the total amount of words;
You go through the file twice, the first time you read the amount of elements, then you initialize the array depending on that value and then, go through it a second time while adding the string as you go by.
It is usually recommended to use a dynamic collection such as an ArrayList(). You can then use the toArray() method to turnt he list into an array.

Categories

Resources