I'm trying to make a lexical analyzer class, that mostly tokenizes the input stream characters, and I use System.in.read() to read characters. The doc says that it returns -1 when end of stream is reached, but, how is this behaviour different when it has different input, I cannot understand this. For e.g. delete.txt has the input:
1. I have
2. bulldoz//er
Then the Lexer has correct tokenization as:
[I=257, have=257, false=259, er=257, bulldoz=257, true=258]
but now if I insert some blank lines using enter then, the code goes on an infinite loop, the code checks newlines and spaces for input, yet, how does it get bypassed? :
1. I have
2. bulldoz//er
3.
The full code is:
package lexer;
import java.io.*;
import java.util.*;
import lexer.Token;
import lexer.Num;
import lexer.Tag;
import lexer.Word;
class Lexer{
public int line = 1;
private char null_init = ' ';
private char tab = '\t';
private char newline = '\n';
private char peek = null_init;
private char comment1 = '/';
private char comment2 = '*';
private Hashtable<String, Word> words = new Hashtable<>();
//no-args constructor
public Lexer(){
reserve(new Word(Tag.TRUE, "true"));
reserve(new Word(Tag.FALSE, "false"));
}
void reserve(Word word_obj){
words.put(word_obj.lexeme, word_obj);
}
char read_buf_char() throws IOException {
char x = (char)System.in.read();
return x;
}
/*tokenization done here*/
public Token scan()throws IOException{
for(; ; ){
// while exiting the loop, sometime the comment
// characters are read e.g. in bulldoz//er,
// which is lost if the buffer is read;
// so read the buffer i
peek = read_buf_char();
if(peek == null_init||peek == tab){
peek = read_buf_char();
System.out.println("space is read");
}else if(peek==newline){
peek = read_buf_char();
line +=1;
}
else{
break;
}
}
if(Character.isDigit(peek)){
int v = 0;
do{
v = 10*v+Character.digit(peek, 10);
peek = read_buf_char();
}while(Character.isDigit(peek));
return new Num(v);
}
if(Character.isLetter(peek)){
StringBuffer b = new StringBuffer(32);
do{
b.append(peek);
peek = read_buf_char();
}while(Character.isLetterOrDigit(peek));
String buffer_string = b.toString();
Word reserved_word = (Word)words.get(buffer_string);//returns null if not found
if(reserved_word != null){
return reserved_word;
}
reserved_word = new Word(Tag.ID, buffer_string);
// put key value pair in words hashtble
words.put(buffer_string, reserved_word);
return reserved_word;
}
// if character read is not a digit or a letter,
// then the character read is a new token
Token t = new Token(peek);
peek = ' ';
return t;
}
private char get_peek(){
return (char)this.peek;
}
private boolean reached_buf_end(){
// reached end of buffer
if(this.get_peek() == (char)-1){
return true;
}
return false;
}
public void run_test()throws IOException{
//loop checking variable
//a token object is initialized with dummy value
Token new_token = null;
// while end of stream has not been reached
while(this.get_peek() != (char)-1){
new_token = this.scan();
}
System.out.println(words.entrySet());
}
public static void main(String[] args)throws IOException{
Lexer tokenize = new Lexer();
tokenize.run_test();
}
}
The get_peek function gets the value of peek which has current input buffer character.
The check for if the buffer end is reached is done in the run_test function.
The main processing is done in the scan() function.
I used the following command: cat delete.txt|java lexer/Lexer to provide the file as input to the compiled java class. Please tell me how is it that this code with the input file with newline added is going on an infinite loop?
I am not sure how you are checking for the end of stream (-1). At the end of scan() you are assigning "peek" to space, I think this is messing up when you have a blank line, you are not able to catch -1.
Related
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
I'm doing on my translation app, I have some problem in my main translator.
for example like my code below, I try to transform "bed" into "bad" and if last char is "m" it will transform to "t".
When my input was "BEDROOM" I want to transform it into "BADROOT" that code below just read my first statement, and the other became false.
private void MachinetranslatorO(){
String change= input.getText().toString();
if (change.substring(0,3).equals("bed")){
String change1 = change.replaceFirst("bed", "bad");
result.setText(change1);
if (change.substring(change.length()-1).equals("m")){
char replaceWith='t';
StringBuffer aBuffer = new StringBuffer(change);
aBuffer.setCharAt(change.length()-1, replaceWith);
result.setText(aBuffer)
Well...since you asked I will provide a quick little Java Console runnable. The code is commented pretty good so you should have no trouble following it.
This application requires a text file containing Translation data (in this example: English To Spanish) which I have also provided sample data for at the end of this post.
Run the application and enter any one of the English words contained within the Translation Table data file (spanish.txt) and the program will display the Spanish equivalent.
Simply create a new project named LanguageTranslator using your favorite IDE then copy/paste the code below:
package languagetranslator;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
import javax.swing.JOptionPane;
public class LanguageTranslator {
// Declare and intitialize some Class global variables...
// The language. It is also the name of our translation table
// text file (ie: spanish.txt)
private static String language = "spanish";
// The 2 Dimensional Array which will hold our translation table.
private static String[][] translationTable = {};
// Class main() method
public static void main(String[] args) {
// Load up the translationTable[][] 2D String Array from our
// Tanslation Table text file (spanish.txt).
readInTranslationFile(language + ".txt");
// Declare and initialize our String variable we will use to accept
// console input from User with...
String userInput = "lets go";
// Open a Connection to console Using the Scanner Class
try (Scanner conInput = new Scanner(System.in)) {
// Start a while/loop to continually ask the User to
// supply a English word...
while (!userInput.equals("")) {
// Ask User to supply a Word...
System.out.println("\nPlease supply a English word to translate\n"
+ "or supply nothing to exit:");
// Hold what User enters into console within the userInput variable.
userInput = conInput.nextLine();
// If the User supplied nothing then he/she want to quit.
if (userInput.equals("")) { break; }
// Declare and initialize a boolean variable so as to later determine if
// a translation for the supplied word had been found.
boolean found = false;
// Iterate through the translationTable[][] 2D String Array to see if
// the User's supplied word is contained within. The English word to
// match would be in the first column of the array and the translation
// for that word would be in the second column of the array.
for (int i = 0; i < translationTable.length; i++) {
// convert the word supplied by User and the current word being read
// within column 1 of the 2D Array to lowercase so that letter case
// is not a factor here.
if(userInput.toLowerCase().equals(translationTable[i][0].toLowerCase())) {
// If the word supplied by User is found within the translationTable[][]
// array then set the found variable to true and display the spanish
// translation to console.
found = true;
System.out.println("--------------------------------------");
System.out.println("The " + language + " translation is: \u001B[34m"
+ translationTable[i][1] + "\u001B[39;49m");
System.out.println("--------------------------------------");
}
}
// If we've iterated through the entire tanslationTable array and an a match
// was not found then display as such to the User...
if (!found) {
System.out.println("\n\u001B[31mThe supplied word could not be located within "
+ "the Translation Table.\n\u001B[39;49m");
}
// Continue the while/loop and ask User to supply another word
// until the User supplies nothing.
}
}
// Exit the application if nothing is supplied by User.
System.exit(0);
}
// Method used to fill the tanslationTable[][] 2D String Array from
// a text file which contains all the translation data.
private static void readInTranslationFile(String filePath) {
String line = "";
int cnt = 0;
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
// Read in each line of the tanslation Table text file so as to place each
//line of data into the translationTable[][] 2 String Array...
while((line = br.readLine()) != null){
// Skip past blank lines in the text file and only process file lines
// which actually contain data.
if (!line.equals("")) {
// Each line of data within the Translation table text file consists
// of a |English word and it's Spanish equivalent delimited with a
// Pipe (|) character. A pipe character is used because you may later
// want to add definitions to your data that may contain different types
// of punctuation.
String[] tok = line.split("\\|");
// The redimPreserve() method allows for appending to a raw 2D String
// Array on the fly.
translationTable = redimPreserve(translationTable, cnt + 1, 2);
// Add the file data line to the 2D String Array...
translationTable[cnt][0] = tok[0].trim();
translationTable[cnt][1] = tok[1].trim();
cnt++; // counter used for incrementing the 2D Array as items are added.
}
}
// Close the BufferReader
br.close();
}
// Trap IO Exceptions from the Bufferreader if any...
catch (IOException ex) {
System.out.println("\n\u001B[31mThe supplied Translation Table file could"
+ " not be found!\n\u001B[39;49m" + filePath);
}
}
// The redimPreserve() method allows for appending to a raw 2D String
// Array on the fly. I created this method to make the task esier to
// accomplish.
private static String[][] redimPreserve(String[][] yourArray, int newRowSize, int... newColSize) {
int newCol = 0;
if (newColSize.length != 0) { newCol = newColSize[0]; }
// The first row of your supplied 2D array will always establish
// the number of columns that will be contained within the entire
// scope of the array. Any column value passed to this method
// after the first row has been established is simply ignored.
if (newRowSize > 1 && yourArray.length != 0) { newCol = yourArray[0].length; }
if (newCol == 0 && newRowSize <= 1) {
JOptionPane.showMessageDialog (null,"RedimPreserve() Error\n\n"
+ "No Column dimension provided for 2D Array!",
"RedimPreserve() Error",JOptionPane.ERROR_MESSAGE);
return null;
}
if (newCol > 0 && newRowSize < 1 && yourArray.length != 0) {
JOptionPane.showMessageDialog (null,"RedimPreserve() Error\n\n"
+ "No Row dimension provided for 2D Array!",
"RedimPreserve() Error",JOptionPane.ERROR_MESSAGE);
return null;
}
String[][] tmp = new String[newRowSize][newCol];
if (yourArray.length != 0) {
tmp = Array2DCopy(yourArray, tmp);
}
return tmp;
}
// Used within the redimPreserve() method to copy 2D Arrays.
private static String[][] Array2DCopy(String[][] yourArray, String[][] targetArray) {
for(int i = 0; i < yourArray.length; i++) {
System.arraycopy(yourArray[i], 0, targetArray[i], 0, yourArray[i].length);
}
return targetArray;
}
}
For a sample Translation Table text file you can copy/paste the following lines into a text editor and save the file as "spanish.txt" within the Classpath of your project (LanguageTranslator):
0|el cero
1|un
2|dos
3|tres
4|cuatro
5|cinco
6|seis
7|siete
8|ocho
9|nueve
a|un
able|poder
also|además
always|siempre
anyway|de todas formas
anyways|de todos modos
an|un
and|y
any|alguna
anybody|nadie
anything|cualquier cosa
apple|manzana
banana|platano
be|ser
because|porque
bedroom|cuarto
best|mejor
can|poder
can't|hipocresia
date|fecha
easy|facil
hard|difícil
harder|mas fuerte
now|ahora
never|nunca
new|nuevo
goodbye|adiós
hello|hola
her|su
high|alto
him|el
his|su
home|casa
how|como
in|en
inside|dentro
is|es
isn't|no es
it|eso
it's|sus
its|sus
leave|salir
list|lista
low|bajo
love|amor
of|de
out|fuera
outside|fuera de
over|encima
that|ese
the|la
then|entonces
these|estas
this|esta
those|aquellos
top|parte superior
topped|rematada
time|hora
to|a
was|estaba
weather|clima
what|que
where|donde
whether|si
who|quien
why|por que
you|tu
your|tu
Add data as you see fit to the file if you like.
Hope this helps...
Your first statement works fine but after that you assign your new reult to change1 not change. So in your second if statement you should use the newer formed string - change1. Don't use the older string change in the second if statement.
Replace change with change1 in second if statement.
**EDIT - **
private void MachinetranslatorO(){
String change= input.getText().toString();
String change1;
if (change.substring(0,3).equals("bed")){
change1 = change.replaceFirst("bed", "bad");
result.setText(change1);
if (change1.substring(change1.length()-1).equals("m")){
char replaceWith='t';
StringBuffer aBuffer = new StringBuffer(change1);
aBuffer.setCharAt(change1.length()-1, replaceWith);
result.setText(aBuffer)
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.
I am workig on a pretty neat problem challenge that involves reading words from a .txt file. The program must allow for ANY .txt file to be read, ergo the program cannot predict what words it will be dealing with.
Then, it takes the words and makes them their "Pig Latin" counterpart, and writes them into a new file. There are a lot more requirements to this problem but siffice to say, I have every part solved save one...when printng to the new file I am unable to perserve the line spacing. That is to say, if line 1 has 5 words and then there is a break and line 2 has 3 words and a break...the same must be true for the new file. As it stands now, it all works but all the converted words are all listed one after the other.
I am interested in learning this so I am OK if you all wish to play coy in your answers. Although I have been at this for 9 hours so "semi-coy" will be appreaciated as well :) Please pay close attention to the "while" statements in the code that is where the file IO action is happening. I am wondering if I need to utilize the nextLine() commands from the scanner and then make a string off that...then make substrings off the nextLine() string to convert the words one at a time. The substrings could be splits or tokens, or something else - I am unclear on this part and token attempts are giving me compiler arrors exceptions "java.util.NoSuchElementException" - I do not seem to understand the correct call for a split command. I tried something like String a = scan.nextLine() where "scan" is my scanner var. Then tried String b = a.split() no go. Anyway here is my code and see if you can figure out what I am missing.
Here is code and thank you very much in advance Java gods....
import java.util.*;
import javax.swing.*;
import java.io.*;
import java.text.*;
public class PigLatinTranslator
{
static final String ay = "ay"; // "ay" is added to the end of every word in pig latin
public static void main(String [] args) throws IOException
{
File nonPiggedFile = new File(...);
String nonPiggedFileName = nonPiggedFile.getName();
Scanner scan = new Scanner(nonPiggedFile);
nonPiggedFileName = ...;
File pigLatinFile = new File(nonPiggedFileName + "-pigLatin.txt"); //references a file that may or may not exist yet
pigLatinFile.createNewFile();
FileWriter newPigLatinFile = new FileWriter(nonPiggedFileName + "-pigLatin.txt", true);
PrintWriter PrintToPLF = new PrintWriter(newPigLatinFile);
while (scan.hasNext())
{
boolean next;
while (next = scan.hasNext())
{
String nonPig = scan.next();
nonPig = nonPig.toLowerCase();
StringBuilder PigLatWord = new StringBuilder(nonPig);
PigLatWord.insert(nonPig.length(), nonPig.charAt(0) );
PigLatWord.insert(nonPig.length() + 1, ay);
PigLatWord.deleteCharAt(0);
String plw = PigLatWord.toString();
if (plw.contains("!") )
{
plw = plw.replace("!", "") + "!";
}
if (plw.contains(".") )
{
plw = plw.replace(".", "") + ".";
}
if (plw.contains("?") )
{
plw = plw.replace("?", "") + "?";
}
PrintToPLF.print(plw + " ");
}
PrintToPLF.close();
}
}
}
Use BufferedReader, not Scanner. http://docs.oracle.com/javase/6/docs/api/java/io/BufferedReader.html
I leave that part of it as an exercise for the original poster, it's easy once you know the right class to use! (And hopefully you learn something instead of copy-pasting my code).
Then pass the entire line into functions like this: (note this does not correctly handle quotes as it puts all non-apostrophe punctuation at the end of the word). Also it assumes that punctuation is supposed to go at the end of the word.
private static final String vowels = "AEIOUaeiou";
private static final String punct = ".,!?";
public static String pigifyLine(String oneLine) {
StringBuilder pigified = new StringBuilder();
boolean first = true;
for (String word : oneLine.split(" ")) {
if (!first) pigified.append(" ");
pigified.append(pigify(word));
first = false;
}
return pigified.toString();
}
public static String pigify(String oneWord) {
char[] chars = oneWord.toCharArray();
StringBuilder consonants = new StringBuilder();
StringBuilder newWord = new StringBuilder();
StringBuilder punctuation = new StringBuilder();
boolean consDone = false; // set to true when the first consonant group is done
for (int i = 0; i < chars.length; i++) {
// consonant
if (vowels.indexOf(chars[i]) == -1) {
// punctuation
if (punct.indexOf(chars[i]) > -1) {
punctuation.append(chars[i]);
consDone = true;
} else {
if (!consDone) { // we haven't found the consonants
consonants.append(chars[i]);
} else {
newWord.append(chars[i]);
}
}
} else {
consDone = true;
// vowel
newWord.append(chars[i]);
}
}
if (consonants.length() == 0) {
// vowel words are "about" -> "aboutway"
consonants.append("w");
}
consonants.append("ay");
return newWord.append(consonants).append(punctuation).toString();
}
You could try to store the count of words per line in a separate data structure, and use that as a guide for when to move on to the next line when writing the file.
I purposely made this semi-vague for you, but can elaborate on request.
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.