How to use string tokenizer when reading in from a file? - java

I am implementing a RPN calculator in Java and need help creating a class to parse the equations into separate tokens.
My input file will have an unknown number of equations similar to the ones shown below:
49+62*61-36
4/64
(53+26)
0*72
21-85+75-85
90*76-50+67
46*89-15
34/83-38
20/76/14+92-15
I have already implemented my own generic stack class to be used in the program, but I am now trying to figure out how to read data from the input file. Any help appreciated.
I've posted the source code for my stack class at PasteBin, in case it may help.
I have also uploaded the Calculator with no filereading to PasteBin to show what I have done already.
I have now managed to get the file read in and the tokens broken up thanks for the help. I am getting an error when it reaches the end of the file and was wondering how to solve that?
Here is the code:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.StringTokenizer;
public class TestClass {
static public void main(String[] args) throws IOException {
File file = new File("testEquations.txt");
String[] lines = new String[10];
try {
FileReader reader = new FileReader(file);
BufferedReader buffReader = new BufferedReader(reader);
int x = 0;
String s;
while((s = buffReader.readLine()) != null){
lines[x] = s;
x++;
}
}
catch(IOException e){
System.exit(0);
}
String OPERATORS = "+-*/()";
for (String st : lines) {
StringTokenizer tokens = new StringTokenizer(st, OPERATORS, true);
while (tokens.hasMoreTokens()) {
String token = tokens.nextToken();
if (OPERATORS.contains(token))
handleOperator(token);
else
handleNumber(token);
}
}
}
private static void handleNumber(String token) {
System.out.println(""+token);
}
private static void handleOperator(String token) {
System.out.println(""+token);
}
}
Also How would I make sure the RPN works line by line? I am getting quite confused by the algorithms I am trying to follow.

Because all of the operators are single characters, you can instruct StringTokenizer to return them along with the numeric tokens.
String OPERATORS = "+-*/()";
String[] lines = ...
for (String line : lines) {
StringTokenizer tokens = new StringTokenizer(line, OPERATORS, true);
while (tokens.hasMoreTOkens()) {
String token = tokens.nextToken();
if (OPERATORS.contains(token))
handleOperator(token);
else
handleNumber(token);
}
}

As your question has now changed completely from it's original version - this is in response to your original one, which was how to use FileReader to get the values from your file.
This will put each line into a separate element of a String array. You should probably use an ArrayList instead, as it's far more flexible, but I have just done this as a quick demo - you can clean it up as you wish, although I notice the code you are using expects a String array as it's input. Perhaps you could read the values initially into an ArrayList, then copy that to an array once you have all the lines - that way you can put as many lines in as you wish and keep your code flexible for changes in the number of lines in your input file.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class TestClass {
static public void main(String[] args) {
File file = new File("myfile.txt");
String[] lines = new String[10];
try {
FileReader reader = new FileReader(file);
BufferedReader buffReader = new BufferedReader(reader);
int x = 0;
String s;
while((s = buffReader.readLine()) != null){
lines[x] = s;
x++;
}
}
catch(IOException e){
//handle exception
}
// And just to prove we have the lines right where we want them..
for(String st: lines)
System.out.println(st);
}
}
You mentioned before that you were using the code on this link:
http://www.technical-recipes.com/2011/a-mathematical-expression-parser-in-java/#more-1658
This appears to already deal with operator precedence doesn't it? And with parsing each String from the array and sorting them into numbers or operators? From my quick look it at least it appears to do that.
So it looks like all you need is for your lines to be in a String array, which you then pass to the code you already have. From what I can see anyway.
Obviously this doesn't address the issue of numbers greater than 9, but hopefully it helps with the first half.
:-)

public void actionPerformed(ActionEvent e) {
double sum=0;
int count = 0 ;
try {
String nomFichier = "Fichier.txt";
FileReader fr = new FileReader(nomFichier);
BufferedReader br = new BufferedReader(fr);
String ligneLue;
do {
ligneLue = br.readLine();
if(ligneLue != null) {
StringTokenizer st = new StringTokenizer(ligneLue, ";");
String nom = st.nextToken();
String prenom = st.nextToken();
String age = st.nextToken();
String tele = st.nextToken();
String adress = st.nextToken();
String codePostal = st.nextToken();
String ville = st.nextToken();
String paye = st.nextToken();
double note = Double.parseDouble(st.nextToken());
count++;
}
}
while(ligneLue != null);
br.close();
double mediane = count / 2;
if(mediane % 2 == 0) {
JOptionPane.showMessageDialog(null, "Le mediane dans le fichier est " + mediane);
}
else {
mediane +=1;
JOptionPane.showMessageDialog(null, "Le mediane dans le fichier est " + mediane);
}
}//fin try
catch(FileNotFoundException ex) {
System.out.println(ex.getMessage());
}
catch(IOException ex) {
System.out.println(ex.getMessage());
}
}

Related

how to split one text into multiple text files

I have the following Text:
1
(some text)
/
2
(some text)
/
.
.
/
8519
(some text)
and I want to split this text into several text-files where each file has the name of the number before the text i.e. (1.txt, 2.txt) and so on, and the content of this file will be the text.
I tried this code
BufferedReader br = new BufferedReader(new FileReader("(Path)\\doc.txt"));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
// sb.append(System.lineSeparator());
line = br.readLine();
}
String str = sb.toString();
String[] arrOfStr = str.split("/");
for (int i = 0; i < arrOfStr.length; i++) {
PrintWriter writer = new PrintWriter("(Path)" + arrOfStr[i].charAt(0) + ".txt", "UTF-8");
writer.println(arrOfStr[i].substring(1));
writer.close();
}
System.out.println("Done");
} finally {
br.close();
}
this code works for files 1-9. However, things go wrong for files 10-8519 since I took the first number in the string (arrOfStr [i].charAt(0)) I know my solution is insufficient any suggestions?
In addition to my comment, considering there isn't a space between the leading integer and the first word, the substring at the first space doesn't work.
This question/answer has a few options that should help, the one using regex (\d+) being the simplest one imo, and copied below.
Matcher matcher = Pattern.compile("\\d+").matcher(arrOfStr[i]);
matcher.find();
int yourNumber = Integer.valueOf(matcher.group());
Given a string find the first embedded occurrence of an integer
As you mentioned, the problem is that you only take the first digit. You could enumerate the first characters until you find a non digit character ( arrOfStr[i].charAt(j) <'0' || arrOfStr[i].charAt(j) > '9' ) but it shoud be easier to user a Scanner and an appropriate regexp.
int index = new Scanner(arrOfStr[i]).useDelimiter("\\D+").nextInt();
The delimiter is precisely any group of non-digit character
Here is a quick solution for the given problem. You can test and do proper exception handling.
package practice;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.List;
public class FileNioTest {
public static void main(String[] args) {
Path path = Paths.get("C:/Temp/readme.txt");
try {
List<String> contents = Files.readAllLines(path);
StringBuffer sb = new StringBuffer();
String folderName = "C:/Temp/";
String fileName = null;
String previousFileName = null;
// Read from the stream
for (String content : contents) {// for each line of content in contents
if (content.matches("-?\\d+")) { // check if it is a number (based on your requirement)
fileName = folderName + content + ".txt"; // create a file name with path
if (sb != null && sb.length() > 0) { // this means if content present to write in the file
writeToFile(previousFileName, sb); // write to file
sb.setLength(0); // clearing buffer
}
createFile(fileName); // create a new file if number found in the line
previousFileName = fileName; // store the name to write content in previous opened file.
} else {
sb.append(content); // keep storing the content to write in the file.
}
System.out.println(content);// print the line
}
if (sb != null && sb.length() > 0) {
writeToFile(fileName, sb);
sb.setLength(0);
}
} catch (IOException ex) {
ex.printStackTrace();// handle exception here
}
}
private static void createFile (String fileName) {
Path newFilePath = Paths.get(fileName);
if (!Files.exists(newFilePath)) {
try {
Files.createFile(newFilePath);
} catch (IOException e) {
System.err.println(e);
}
}
}
private static void writeToFile (String fileName, StringBuffer sb) {
try {
Files.write(Paths.get(fileName), sb.toString().getBytes(), StandardOpenOption.APPEND);
}catch (IOException e) {
System.err.println(e);
}
}
}

How to store text from a certain column in an arraylist?

I would like to store only the first column that is contained in the .txt file.
hello28 23232
hello27 23232
hello25 12321
This is the code I have so far, however at the moment it stores every line in the file; how can I make it so that only the first column is stored (The one which contains the user names of the users)?
public static boolean checkUserExists(String userName){
String line = "";
ArrayList <String> userNames = new ArrayList <String>();
try{
FileReader fr = new FileReader("investments.txt");
BufferedReader br = new BufferedReader(fr);
while((line = br.readLine()) != null) {
userNames.add(line);
}
}
catch(IOException e){
System.out.println("File not found!");
}
if (userNames.contains(userName)){
return false;
}
else{
return true;
}
}
All you need to do is just to split each line using whitespace as a delimiter and keep the first token, and repeat that for every line:
This can be achieved using the following line of code which uses the split function (see more info here http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#split(java.lang.String))
line.split("\\s+");
Then, the zero-th (0) element contains the first column, as you wish to do
There you go a fully working class:
import java.io.IOException;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
class white {
public static void main(String[] args) {
String line = "";
String username = "";
ArrayList <String> userNames = new ArrayList <String>();
try{
FileReader fr = new FileReader("investments.txt");
BufferedReader br = new BufferedReader(fr);
while((line = br.readLine()) != null) {
line.split("\\s+");
userNames.add(line.split("\\s+")[0]);
System.out.println(line.split("\\s+")[0]);
}
}
catch(IOException e){
System.out.println("File not found!");
}
}
}
OUTPUT:
hello28
hello27
hello25
You can extract the part of the line preceding the first space:
userNames.add(line.substring(0, line.indexOf(' ') ));

Adding data from .txt document to array

Below is what the text document looks like. The first line is the number of elements that I want the array to contain. The second is the ID for the product, separated by # and the third line is the total price of the products once again separated by #
10
PA/1234#PV/5732#Au/9271#DT/9489#HY/7195#ZR/7413#bT/4674#LR/4992#Xk/8536#kD/9767#
153#25#172#95#235#159#725#629#112#559#
I want to use the following method to pass inputFile to the readProductDataFile method:
public static Product[] readProductDataFile(File inputFile){
// Code here
}
I want to create an array of size 10, or maybe an arrayList. Preferably to be a concatenation of Customer ID and the price, such as Array[1] = PA/1234_153
There you go the full class, does exactly what you want:
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Arrays;
import java.io.FileNotFoundException;
import java.io.IOException;
class myRead{
public static void main(String[] args) throws FileNotFoundException, IOException {
BufferedReader inputFile = new BufferedReader(new FileReader("test.txt"));
String numberOfElements = inputFile.readLine();
//this is the first line which contains the number "10"
//System.out.println(numberOfElements);
String secondLine = inputFile.readLine();
//this is the second line which contains your data, split it using "#" as a delimiter
String[] strArray = secondLine.split("#");
//System.out.println(Arrays.toString(strArray));
//System.out.println(strArray[0]);
String thirdLine = inputFile.readLine();
//this is the third line which contains your data, split it using "#" as a delimiter
String[] dataArray = thirdLine.split("#");
//combine arrays
String[] combinedArray = new String[strArray.length];
for (int i=0;i<strArray.length;i++) {
combinedArray[i]=strArray[i]+"_"+dataArray[i];
System.out.println(combinedArray[i]);
}
}
}
OUTPUT:
PA/1234_153
PV/5732_25
Au/9271_172
DT/9489_95
HY/7195_235
ZR/7413_159
bT/4674_725
LR/4992_629
Xk/8536_112
kD/9767_559
The trick in what I am doing is using a BufferedReader to read the file, readLine to read each of the three lines, split("#"); to split each token using the # as the delimiter and create the arrays, and combinedArray[i]=strArray[i]+"_"+dataArray[i]; to put the elements in a combined array as you want...!
public static Product[] readProductDataFile(File inputFile){
BufferedReader inputFile = new BufferedReader(new FileReader(inputFile));
// the rest of my previous code goes here
EDIT: Everything together with calling a separate method from inside the main, with the file as an input argument!
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Arrays;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.File;
class myRead{
public static void main(String[] args) throws FileNotFoundException, IOException {
File myFile = new File("test.txt");
readProductDataFile(myFile);
}
public static String[] readProductDataFile(File inputFile) throws FileNotFoundException, IOException{
BufferedReader myReader = new BufferedReader(new FileReader("test.txt"));
String numberOfElements = myReader.readLine();
//this is the first line which contains the number "10"
//System.out.println(numberOfElements);
String secondLine = myReader.readLine();
//this is the second line which contains your data, split it using "#" as a delimiter
String[] strArray = secondLine.split("#");
//System.out.println(Arrays.toString(strArray));
//System.out.println(strArray[0]);
String thirdLine = myReader.readLine();
//this is the third line which contains your data, split it using "#" as a delimiter
String[] dataArray = thirdLine.split("#");
//combine arrays
String[] combinedArray = new String[strArray.length];
for (int i=0;i<strArray.length;i++) {
combinedArray[i]=strArray[i]+"_"+dataArray[i];
System.out.println(combinedArray[i]);
}
return combinedArray;
}
}
OUTPUT
PA/1234_153
PV/5732_25
Au/9271_172
DT/9489_95
HY/7195_235
ZR/7413_159
bT/4674_725
LR/4992_629
Xk/8536_112
kD/9767_559
You don't even need the first line. Just read the second line directly into a single string and then split it by using String,split() method.
Read more for split method here.
You could use something like this (Be aware that i can't test it at the moment)
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader("fileeditor.txt"));
String read = null;
String firstLine=in.readLine();
//reads the first line
while ((read = in.readLine()) != null) {
// reads all the other lines
read = in.readLine();
String[] splited = read.split("#");
//split the readed row with the "#" character
for (String part : splited) {
System.out.println(part);
}
}
} catch (IOException e) {
System.out.println("There was a problem: " + e);
e.printStackTrace();
} finally {
try {
//close file
in.close();
} catch (Exception e) {
}
}
This is how you can do it using Java (don't forget to import):
public static Product[] readProductDataFile(File inputFile){
Scanner s = new Scanner(inputFile);
String data = "";
while(s.hasNext())
data += s.nextLine();
String[] dataArray = data.split("#");
}
You can try this way ..
Reading line by line and storing each row in a array.
Use while storing so it will split and save .
String[] strArray = secondLine.split("#");
Now use the for loop and concat the values as u wish and save ina third array .
For(int i=0 ;i< file.readline;i++)
{
string s = a[customerid];
s.concat(a[productid]);
a[k] =s;
}

adding objects to java queues from a data file

I am trying to add objects to a queue from a data file which is made up of text which is made up of a person's first name and their 6 quiz grades (ie: Jimmy,100,100,100,100,100,100). I am accessing the data file using the FileReader and using BufferReader to read each line of my data file and then tokenize each line using the "," deliminator to divide the names and quiz grades up. Based on what I think my professor is asking for is to create a queue object for each student. The assignment says,
Read the contents of the text file one line at a time using a loop. In this loop, invoke the processInputData method for each line read. This method returns the corresponding Student object. Add this student object to the studentQueue.
If someone could point me the right direction that would be great! Here is my code so far:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.StringTokenizer;
public class Test {
public static void main(String[] args) {
// Create an empty queue of student objects
LinkedList<Student> studentQueue;
studentQueue = new LinkedList<Student>();
// Create an empty map of Student objects
HashMap<String, Student> studentMap = new HashMap<String, Student>();
System.out.printf("Initial size = %d\n", studentMap.size());
// Open and read text file
String inputFileName = "data.txt";
FileReader fileReader = null;
// Create the FileReader object
try {
fileReader = new FileReader(inputFileName);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// BufferReader to read text file
BufferedReader reader = new BufferedReader(fileReader);
String input;
// Read one line at a time until end of file
try {
input = reader.readLine();
while (input != null) {
processInputData(input);
input = reader.readLine();
}
}
catch (IOException e) {
e.printStackTrace();
}
// Close the input
try {
fileReader.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
// Tokenize the data using the "," as a delimiter
private static void processInputData(String data) {
StringTokenizer st = new StringTokenizer(data, ",");
String name = st.nextToken();
String homework1 = st.nextToken();
String homework2 = st.nextToken();
String homework3 = st.nextToken();
String homework4 = st.nextToken();
String homework5 = st.nextToken();
String homework6 = st.nextToken();
// Using the set methods to correspond to the Student object
Student currentStudent = new Student(name);
currentStudent.setHomework1(Integer.parseInt(homework1));
currentStudent.setHomework2(Integer.parseInt(homework2));
currentStudent.setHomework3(Integer.parseInt(homework3));
currentStudent.setHomework4(Integer.parseInt(homework4));
currentStudent.setHomework5(Integer.parseInt(homework5));
currentStudent.setHomework6(Integer.parseInt(homework6));
System.out.println("Input File Processing...");
System.out.println(currentStudent);
}
}
One possible solution to your problem is returning the student in processInputData(..)
private static Student processInputData(String data) {
// the same code
return currentStudent;
}
And in while loop
while (input != null) {
studentQueue.add(processInputData(input));
input = reader.readLine();
}
Also try to manage better your try-catch blocks, cause if your fileReader throws exception then the code will continue running and throw probably a nullPointerException that you don't handle.
try{
fileReader = new FileReader(inputFileName);
BufferedReader reader = new BufferedReader(fileReader);
}catch(IOException ex){
//handle exception;
}finally{
// close resources
}

Simultaneous searching of multiple words in an external file(Java)

The program that I am trying to create is a program that takes words from a user defined file, saves those words as variables and then searches a different user defined file for those words, outputting there location.
The program works up to and including the point where the program takes the words and saves them as variables. The problem with the program is that the search method returns a null result. My main suspicions are that the code in the search method is incompatible with the code in the read method, or that the 2 methods aren't running simultaneously.
The search method is in the searching class and the read method is in the reading class.
Here is my code (Containing all 3 of my classes), please excuse all of the imports.
This is the first class:
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Combination{
public static void main(String[] args) throws FileNotFoundException{
Scanner userInput = new Scanner(System.in);
Reading ReadingObject = new Reading();
System.out.println("Please enter the file that you wish to open");
String temp = userInput.nextLine();
ReadingObject.setFileName(temp);
ReadingObject.read();
Scanner searchForWord = new Scanner(System.in);
Searching SearchingObject = new Searching();
System.out.println("Please enter the file that you would like to search for these words in");
String temp1 = searchForWord.nextLine();
SearchingObject.setFileName(temp1);
SearchingObject.search();
}
}
This is the second class:
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
class Reading {
private String file;
public void setFileName(String fileName){
file = fileName;
}
public String getFileName(){
return file;
}
public void read(){
try{
//Choosing the file to open
FileInputStream fstream = new FileInputStream(getFileName());
//Get the object of datainputstream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine = null;
//Read the file line by line
while((strLine = br.readLine()) != null){
// \\s+ means any number of whitespaces between tokens
String [] tokens = strLine.split("\\s+");
String [] words = tokens;
for(String word : words){
System.out.print(word);
System.out.print(" ");
Searching SearchingObject = new Searching();
SearchingObject.setWord(word);
}
System.out.print("\n");
}
in.close();
}
catch(Exception e){
System.err.println("Error: " + e.getMessage());
}
}
}
This is the third class:
import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Searching {
private String file1;
public void setFileName(String fileName){
file1 = fileName;
}
public String getFileName(){
return file1;
}
private String word1;
public void setWord(String wordName){
word1 = wordName;
}
public String getWord(){
return word1;
}
public void search() throws FileNotFoundException{
try{
//Choosing the file to open
FileInputStream fstream = new FileInputStream(getFileName());
//Get the object of datainputstream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine = null;
while((strLine = br.readLine()) != null){
Pattern p = Pattern.compile(getWord());
Matcher m = p.matcher(strLine);
int start = 0;
while (m.find(start)) {
System.out.printf("Word found: %s at index %d to %d.%n", m.group(), m.start(), m.end());
start = m.end();
}
}
}
catch(Exception e){
System.err.println("Error: " + e.getMessage());
}
}
}
Any help will be greatly appreciated.
Regards
Your code is hard to read. Your reading class does not only read; it also searches. You should call it something that reflects its intended use. However, it forgets to tell its searching object where to search, and does not pass the reference to this object to anyone else. In this snippet
for (String word : words) {
System.out.print(word);
System.out.print(" ");
searching searchingObject = new searching();
searchingObject.setWord(word);
}
you are essentially not doing anything. The reference to searchingObject is lost forever.
Your reading class should keep an ArrayList of words to be searched for in the searching, instead of instancing searching objects.
Your searching class should take, as a constructor parameter, one of these ArrayLists -- and convert it into a single regex, which is much more efficient than reading the file once per word to search for. You can search for "a", "b" and "c" using the single regular expression "a|b|c". Works with longer words, too. Escape them first to avoid problems.
Oh, and please, please follow naming guidelines. Call your reading a TokenReader, and your searching a WordListSearcher...

Categories