Considering the below code for an exercise problem, where is the specification that says roughly: "Upon the call to readTokens(), wait for the user to press carriage return and then continue execution."
I'm not fully understanding why my code works, why does the program pause after "Enter Data: " is displayed and wait for a carriage return? Where is this behavior defined and how can it be changed?
import java.io.*;
import java.util.LinkedList;
public class StreamTokeTwo {
private int ttype = 0;
StreamTokenizer tokenizer = new StreamTokenizer(new BufferedReader(
new InputStreamReader(System.in)));
private void setupTokenizer() {
tokenizer.resetSyntax();
tokenizer.wordChars(33, 126);
tokenizer.whitespaceChars(0, 32);
tokenizer.whitespaceChars(44,44);
tokenizer.whitespaceChars(47,47);
tokenizer.eolIsSignificant(true);
}
private String[] readTokens() {
LinkedList<String> list = new LinkedList<String>();
String[] array = null;
do {
try {
ttype = tokenizer.nextToken();
} catch (Exception e) {
System.exit(1);
}
if (ttype == StreamTokenizer.TT_WORD) {
list.add(tokenizer.sval);
}
} while (ttype != StreamTokenizer.TT_EOL);
array = list.toArray(new String[0]);
return array;
}
public static void main(String[] args) {
StreamTokeTwo streamToke = new StreamTokeTwo();
streamToke.setupTokenizer();
for (int i = 0; i < 5; ++i) {
System.out.print("Enter data: ");
String[] array = streamToke.readTokens();
for (String str : array) {
System.out.print(str + " ");
}
System.out.println();
}
}
}
The wait-for-typing behavior is a feature of the operating system and shell. They turn your typing into standard input for the JVM, and decide what constitutes end of file and what makes data available to pass to a program that is reading its standard input.
As far as the JVM is concerned, it is just asking for data from standard input, in a way that will block if there is no data available and it is not at end of file. It would be doing the same if standard input were a disk file.
This is implied by the statement that the InputStreamReader has blocking behavior: the reading methods will not return until there is something to be read, or an error occurs.
Related
I have been tasked to solve a question concerning the creation of a triple-ended queue with efficient random access, as outlined in this: https://open.kattis.com/problems/teque. I created a program based around using 2 very large arrays, one containing the front half of all stored integers so far and the other the back half, with both being of the same size or the front half containing at most 1 more element than the back half after every insertion operation. This should allow all insertion and retrieval operations to be of O(1) time complexity, but the code just keeps exceeding the given time limit. Can anyone tell me what is wrong with my code? Here it is:
import java.util.*;
import java.io.*;
public class Teque3 {
static int[] front = new int[1_000_000];
static int[] back = new int[1_000_000];
static int frontHead = 499_999;
static int backHead = 499_999;
static int frontSize = 0;
static int backSize = 0;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
for (int i = 0; i < n; i++) {
String[] line = br.readLine().split(" ");
if (line[0].equals("get")) {
int index = Integer.parseInt(line[1]);
if (index >= frontSize) System.out.println(back[backHead + index - frontSize]);
else System.out.println(front[frontHead + index]);
continue;
}
if (frontSize == backSize) {
if (line[0].equals("push_front")) {
frontHead--;
front[frontHead] = Integer.parseInt(line[1]);
frontSize++;
} else if (line[0].equals("push_back")) {
back[backHead + backSize] = Integer.parseInt(line[1]);
front[frontHead + frontSize] = back[backHead];
frontSize++;
backHead++;
} else if (line[0].equals("push_middle")) {
front[frontHead + frontSize] = Integer.parseInt(line[1]);
frontSize++;
}
} else {
if (line[0].equals("push_front")) {
frontHead--;
front[frontHead] = Integer.parseInt(line[1]);
backHead--;
back[backHead] = front[frontHead + frontSize];
backSize++;
} else if (line[0].equals("push_back")) {
back[backHead + backSize] = Integer.parseInt(line[1]);
backSize++;
} else if (line[0].equals("push_middle")) {
backHead--;
back[backHead] = Integer.parseInt(line[1]);
backSize++;
}
}
}
}
}
You could try to minimze IO-Operations: Collect your programm output. Instead of writing System.out.println better create a new StringBuilder to collect everything. In the end write all at once.
static StringBuilder result = new StringBuilder();
...
private static void result(int value) {
result.append(value).append("\n");
}
...
if (index >= frontSize) result(back[backHead + index - frontSize]);
else result(front[frontHead + index]);
...
System.out.println(result);
Decouple read from parse and process: Create one thread for reading the operations. But the operations in a Queue. Start another thread for the process.
Create k threads that simultaneously write characters into the same file:
the first thread writes a digit 0 exactly 20 times on the first line of the file;
the second thread writes a digit 1 exactly 20 times on the second line of the file;
...
the tenth thread writes a digit 9 exactly 20 times on the tenth line of the file;
Requirements to the implementation.
It is required to set a 1 millisecond pause for writing of each digit.
Use the RandomAccessFile for writing data to the file.
You can use not more than one object of the RandomAccessFile class!
I wrote something like this:
import java.io.IOException;
import java.io.RandomAccessFile;
public class Part5 {
// creates string before writing to the file
public static String createString(int integer){
StringBuilder result = new StringBuilder("");
for(int i = 0; i < 20; i++){
result.append(integer);
}
result.append("\n");
return result.toString();
}
// writes string into the file
public static void writeString(String st) {
try(RandomAccessFile file = new RandomAccessFile("part5.txt", "rw")){
st+="\n";
file.write(st.getBytes());
}catch(IOException ex){
ex.getMessage();
}
}
// starts writing threads
public static void startThread(int number){
Thread thread = new Thread(){
#Override
public void run() {
synchronized (this){
writeString(createString(number));
}
}
};
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(final String[] args) {
for(int i = 0; i < 9; i++){
startThread(i);
}
}
}
My implementation only rewrites first line of the file, but should write something like this:
00000000000000000000
11111111111111111111
22222222222222222222
33333333333333333333
44444444444444444444
55555555555555555555
66666666666666666666
77777777777777777777
88888888888888888888
99999999999999999999
How can I fix my "concurrency part" of code to make it work correctly?
Thank you in advance!
When you write to file, you need to move the pointer to the correct position. You need to call "seek" method in RandomAccessFile and then move the pointer by number of bytes. For example first thread will seek to 0, second will seek to 21 and so on.
The way your program is right now, every thread will overwrite every other thread.
There may also be a problem with parallelization.
I didn't want to give a ready made solution, but I got curious. So here's something you could learn from
import java.io.IOException;
import java.io.RandomAccessFile;
public class Blah {
// creates string before writing to the file
public static String createString(int integer){
StringBuilder result = new StringBuilder("");
for(int i = 0; i < 20; i++){
result.append(integer);
}
result.append("\n");
return result.toString();
}
public static void main(final String[] args) throws IOException {
RandomAccessFile file = new RandomAccessFile("part5.txt", "rw");
Blah blah = new Blah();
for(int i = 0; i <= 9; i++){
Thread thread = new Thread(blah.new NumberWriter(i, file));
thread.start();
}
file.close();
}
private class NumberWriter implements Runnable {
int number;
RandomAccessFile file;
public NumberWriter(int number, RandomAccessFile file) {
this.number = number;
this.file = file;
}
public void run() {
try {
int seek = this.number * 20 + number;
System.out.println("number is : " + number + " : seeking to : " + seek);
file.seek(seek);
file.write((createString(this.number)).getBytes());
} catch (IOException ioex) {
ioex.printStackTrace();
}
}
}
}
This is the first time I have asked a question on StackOverflow. The problem I have is the following:
I have a Producer and Consumer class. In the Producer class I read a file line by line and put these lines of text in a List of Strings. When the list has an x amount of lines. This list gets added to an ArrayBlockingQueue. I have one Producer Thread that is started within the main thread. Besides this I start a couple of Consumer threads. The Consumer thread takes an item from the queue, which should be a list, and walks through this list of lines looking for a particular word. When the word is found it increments a count variable.
What happends is that when the Consumer takes an item from the queue, it says that it is empty. I cannot figure out why because my producer should certainly add it to the queue.
My code looks like this:
Consumer class:
public static class Consumer implements Callable<Integer> {
int count = 0;
#Override
public Integer call() throws Exception {
List<String> list = new ArrayList<>();
list = arrayBlockingQueueInput.take();
do {
if (!list.isEmpty()){
for (int i = 0; i < arrayBlockingQueueInput.take().size(); i++) {
for (String element : list.get(i).split(" ")) {
if (element.equalsIgnoreCase(findWord)) {
count++;
}
}
}
} else {
arrayBlockingQueueInput.put(list);
}
} while (list.get(0) != "HALT");
return count;
}
}
Producer Class:
public static class Producer implements Runnable {
#Override
public void run() {
try {
FileReader file = new FileReader("src/testText.txt");
BufferedReader br = new BufferedReader(file);
while ((textLine = br.readLine()) != null) {
if (textLine.isEmpty()) {
continue;
}
/* Remove punctuation from the text, except of punctuation that is useful for certain words.
* Examples of these words are don't or re-enter */
textLine = textLine.replaceAll("[[\\W]&&[^']&&[^-]]", " ");
/* Replace all double whitespaces with single whitespaces.
* We will split the text on these whitespaces later */
textLine = textLine.replaceAll("\\s\\s+", " ");
textLine = textLine.replaceAll("\\n", "").replaceAll("\\r", "");
if (results.isEmpty()) {
results.add(textLine);
continue;
}
if (results.size() <= SIZE) {
results.add(textLine);
if (results.size() == SIZE) {
if (arrayBlockingQueueInput.size() == 14){
List<String> list = new ArrayList<String>();
list.add(HALT);
arrayBlockingQueueInput.put(list);
} else{
arrayBlockingQueueInput.put(results);
results.clear();
}
}
}
}
/* Count the remaining words in the list
* (last lines of the file do perhaps not fill up until the given SIZE, therefore need to be counted here)
* Fill the list with empty items if the size of the list does not match with the given SIZE */
while (results.size() != SIZE) {
results.add("");
}
arrayBlockingQueueInput.put(results);
List<String> list = new ArrayList<String>();
list.add(HALT);
arrayBlockingQueueInput.put(list);
results.clear();
} catch (InterruptedException e) {
producerIsRunning = false;
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Main Class:
public void main() throws IOException, InterruptedException {
System.out.println("Enter the word you want to find: ");
Scanner scan = new Scanner(System.in);
findWord = scan.nextLine();
System.out.println("Starting...");
long startTime = System.currentTimeMillis();
Thread producer = new Thread(new Producer());
producer.start();
ExecutorService executorService = Executors.newFixedThreadPool(CORE);
List<Future<Integer>> futureResults = new ArrayList<Future<Integer>>();
for (int i = 0; i < CORE; i++) {
futureResults.add(executorService.submit(new Consumer()));
}
executorService.shutdown();
for (Future<Integer> result : futureResults) {
try {
wordsInText += result.get();
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
}
producer.join();
long stopTime = System.currentTimeMillis();
System.out.println("The word " + findWord + " appears " + wordsInText + " times in the given text");
System.out.println("Elapsed time was " + (stopTime - startTime) + " milliseconds.");
}
Can anybody explain why this happends? I would like to add that we try to use a poison pill to notify the consumers that the producer is on HALT.
To answer the question why we want to do this like this? For school we try to parallelize a certain programming problem. The problem we chose is string matching. We first made a serial solution and a parallel solution. For the next assignment we have to improve our parallel solution and our teacher told us that this is a way to do it.
Thanks in advance!
Nick
You add list to a queue and the clear it:
arrayBlockingQueueInput.put(results);
results.clear();
You need to do something like this to add copy of list to a queue so that clear() will not clean list which is in queue:
arrayBlockingQueueInput.put(new ArrayList<String>(results));
results.clear();
After some help from my teacher he helped us find the problem. There were two mistakes. One was within the producer class. I had code to signal a HALT of the producer within the main while loop. This should not have been done.
Besides this, the .take() I do within the Consumer class before the Do-While should have been done within the do-while loop.
The correct code looks like this:
Consumer class:
public static class Consumer implements Callable<Integer> {
int count = 0;
#Override
public Integer call() throws Exception {
List<String> list = new ArrayList<>();
do {
list = arrayBlockingQueueInput.take();
if (!list.get(0).equals(HALT)){
for (int i = 0; i < list.size(); i++) {
for (String element : list.get(i).split(" ")) {
if (element.equalsIgnoreCase(findWord)) {
count++;
}
}
}
} else {
arrayBlockingQueueInput.put(list);
}
} while (!list.get(0).equals(HALT));
return count;
}
}
Producer class:
public static class Producer implements Runnable {
#Override
public void run() {
try {
FileReader file = new FileReader("src/testText.txt");
BufferedReader br = new BufferedReader(file);
while ((textLine = br.readLine()) != null) {
if (textLine.isEmpty()) {
continue;
}
/* Remove punctuation from the text, except of punctuation that is useful for certain words.
* Examples of these words are don't or re-enter */
textLine = textLine.replaceAll("[[\\W]&&[^']&&[^-]]", " ");
/* Replace all double whitespaces with single whitespaces.
* We will split the text on these whitespaces later */
textLine = textLine.replaceAll("\\s\\s+", " ");
textLine = textLine.replaceAll("\\n", "").replaceAll("\\r", "");
if (results.isEmpty()) {
results.add(textLine);
continue;
}
if (results.size() <= SIZE) {
results.add(textLine);
if (results.size() == SIZE) {
arrayBlockingQueueInput.put(new ArrayList<String>(results));
results.clear();
}
}
}
/* Count the remaining words in the list
* (last lines of the file do perhaps not fill up until the given SIZE, therefore need to be counted here)
* Fill the list with empty items if the size of the list does not match with the given SIZE */
while (results.size() != SIZE) {
results.add("");
}
arrayBlockingQueueInput.put(new ArrayList<String>(results));
List<String> list = new ArrayList<String>();
list.add(HALT);
arrayBlockingQueueInput.put(list);
results.clear();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Main class:
public void main() throws IOException, InterruptedException {
System.out.println("Enter the word you want to find: ");
Scanner scan = new Scanner(System.in);
findWord = scan.nextLine();
System.out.println("Starting...");
long startTime = System.currentTimeMillis();
Thread producer = new Thread(new Producer());
producer.start();
ExecutorService executorService = Executors.newFixedThreadPool(CORE);
List<Future<Integer>> futureResults = new ArrayList<Future<Integer>>();
for (int i = 0; i < CORE; i++) {
futureResults.add(executorService.submit(new Consumer()));
}
executorService.shutdown();
for (Future<Integer> result : futureResults) {
try {
wordsInText += result.get();
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
}
producer.join();
long stopTime = System.currentTimeMillis();
System.out.println("The word " + findWord + " appears " + wordsInText + " times in the given text");
System.out.println("Elapsed time was " + (stopTime - startTime) + " milliseconds.");
}
Thanks to #Ivan for helping me with the .clear method called on results. Without this the code solution did not work.
How do I make this JOptionPane List up to 100 items with a JScrollBar, I know it can be done. I'm asking for a little bit of guidance.
Here's my code
public static ArrayList<String> Matches = new ArrayList<String>();
private void itemSearch(String name) {
try{
String string;
BufferedReader reader = new BufferedReader(new FileReader("items.txt"));
while((string = reader.readLine()) != null) {
String[] args = string.split(" ");
for(int i = 0; i <= 19461; i++) {
if(args[i].contains(name)) {
itemID = Integer.parseInt(args[i-1]);
itemSearched = name;
Matches.add("Name: "+name+", ID: "+itemID+"");
System.out.println("Item name:"+args[i]+" Item ID:"+itemID+"");
}
}
if(Matches.size()<=1) {
continue;
} else {
JOptionPane.showMessageDialog(null, Matches);
}
AMItemDatabaseLabel3.setText(""+itemID+"");
}
} catch(Exception r) {
r.printStackTrace();
}
}
Check out the section from the Swing tutorial on Getting Users Input.
If the number of "possibilities" is greater than 20, then a JList will be used to display the values.
So you need to use an Array (not an ArrayList) containing your items. So based on your current code you would need to copy the items from the ArrayList to the Array.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I'm trying to write a program that gets a .txt file that only has something like 10000010000010000010001
I'm trying to count the number of zeros and output it like 5 5 5 3. I thought if I convert a string into a double or int I could write an if or for loop.
import java.util.Scanner;
public class test1{
public static void main(String[] args) {
java.io.File test2 = new java.io.File("test3.txt");
try
{
Scanner input = new Scanner(test2);
while(input.hasNext())
{
String num = input.nextLine();
System.out.println(num);
double n = Double.parseDouble(num);
System.out.println(n);
}
}
catch (Exception e){
System.out.println("could not find file");
}
}
}
Here you go:
char[] numArray = num.toCharArray();
int counter=0;
for(int i=0;i<numArray.length;i++) {
if(numArray[i]=='0') {
counter++;
}
if((i==numArray.length-1&&counter>0)||(counter>0&&numArray[i]!='0')) {
System.out.println("Number of Zeroes: "+counter);
counter=0;
}
}
Some important points:
1) It's best to use an array of char values here, instead of operating using a double, because a char array can store many more values- the example you posted is too long for a double to handle.
2) Most of this should be self-explanatory (at least, if you study it bit-by-bit), but in case the i==numArray.length-1 part is confusing, this ensures that if the string ends with a 0, the final count of 0's will be printed out as well.
This should work for any string you can throw at it- including values besides 0 and 1, if you need support for it!
where is your effort?
you can simply try (if your string contains only 1s and 0s):
String[] splitArr = num.split("1");
String countStr = "";
for (int i = 0; i < splitArr.length; i++) {
if( ! splitArr[i].isEmpty() )
countStr += splitArr[i].length();
}
System.out.println(countStr);
import java.util.*;
import java.io.*;
public class ZeroCounter {
ArrayList <Integer> listOfNumbers = new ArrayList <Integer> ();
DataInputStream inStream;
long inFileSize;
long outFileSize;
// Track how many bytes we've read. Useful for large files.
int byteCount;
public ZeroCounter() {
}
//read the file and turn it into an array of integers
public void readFile(String fileName) {
try {
// Create a new File object, get size
File inputFile = new File(fileName);
inFileSize = inputFile.length();
// The constructor of DataInputStream requires an InputStream
inStream = new DataInputStream(new FileInputStream(inputFile));
}
// Oops. Errors.
catch (FileNotFoundException e) {
e.printStackTrace();
System.exit(0);
}
// Read the input file
try {
// While there are more bytes available to read...
while (inStream.available() > 0) {
// Read in a single byte and store it in a character
int c = (int)inStream.readByte();
if ((++byteCount)% 1024 == 0)
System.out.println("Read " + byteCount/1024 + " of " + inFileSize/1024 + " KB...");
// Print the integer to see them for debugging purposes
//System.out.print(c);
// Add the integer to an ArrayList
fileArray.add(c);
}
// clean up
inStream.close();
System.out.println("File has been converted into an ArrayList of Integers!");
}
// Oops. Errors.
catch (IOException e) {
e.printStackTrace();
System.exit(0);
}
//Print the ArrayList contents for debugging purposes
//System.out.println(fileArray);
}
public void countZeroes() {
int zeroCounter = 0;
for (int i = 0; i < listOfNumbers.size(); i++) {
if (listOfNumbers.get(i) == 0) {
zeroCounter++;
}
else if (listOfNumbers.get(i) != 0 && zeroCounter > 0) {
//this only prints the number of zeroes if the zero counter isn't zero
System.out.println(zeroCounter + " ");
zeroCounter = 0;
}
else {
//do nothing
}
}
}
public static void main(String[] args) {
ZeroCounter comp = new ZeroCounter();
comp.readFile("test3.txt");
comp.countZeroes();
}
}