Is a static method containing loops thread-safe? - java

I have a huge loop that I wanted to split up into 4 threads. I've done so using a little bit noobish method(or maybe not?) and split up the counter of the for loops into 4 intervals, created a new Printwriter, and CrucibleOptimizer for each thread so that there are no conflicts, like this:
public static void main(String[] args) {
Runnable run1 = new Runnable() {
#Override
public void run() {
PrintWriter writer1;
try {
writer1 = new PrintWriter("test_result1.txt");
CrucibleOptimizer optimizer1 = new CrucibleOptimizer();
int[] loop1boundries = new int[]{1, 7};
opt(optimizer1, writer1, loop1boundries[0], loop1boundries[1]);
} catch (FileNotFoundException e) {
System.out.println("File not found");
e.printStackTrace();
}
}
};
Runnable run2 = new Runnable() {
#Override
public void run() {
PrintWriter writer2;
try {
writer2 = new PrintWriter("test_result2.txt");
CrucibleOptimizer optimizer2 = new CrucibleOptimizer();
int[] loop2boundries = new int[]{8, 14};
opt(optimizer2, writer2, loop2boundries[0], loop2boundries[1]);
} catch (FileNotFoundException e) {
System.out.println("File not found");
e.printStackTrace();
}
}
};
Runnable run3 = new Runnable() {
#Override
public void run() {
PrintWriter writer3;
try {
writer3 = new PrintWriter("test_result3.txt");
CrucibleOptimizer optimizer3 = new CrucibleOptimizer();
int[] loop3boundries = new int[]{15, 22};
opt(optimizer3, writer3, loop3boundries[0], loop3boundries[1]);
} catch (FileNotFoundException e) {
System.out.println("File not found");
e.printStackTrace();
}
}
};
Runnable run4 = new Runnable() {
#Override
public void run() {
PrintWriter writer4;
try {
writer4 = new PrintWriter("test_result4.txt");
CrucibleOptimizer optimizer4 = new CrucibleOptimizer();
int[] loop4boundries = new int[]{23, 30};
opt(optimizer4, writer4, loop4boundries[0], loop4boundries[1]);
} catch (FileNotFoundException e) {
System.out.println("File not found");
e.printStackTrace();
}
}
};
Thread[] threads = new Thread[]{new Thread(run1), new Thread(run2), new Thread(run3), new Thread(run4)};
for (Thread thr : threads){
thr.start();
}
}
And this is the method that I'm asking about. I don't know if its thread safe. I've been reading around and google says that as far as I don't have any local variables, I'm fine, but what concerns me is the multiple counters in those loops:
public static void opt(CrucibleOptimizer opt, PrintWriter writer, int minIncluded, int maxIncluded){
//more than this is never used
final int oreMaterialsMaximum = 100;//100
final int ingotMaterialMaximum = 30;//30
//test for every possible material combination
for (int a = minIncluded; a <= maxIncluded; a++){//for amount of ingots
System.out.println("Testing for ingot number: " + a);
double ratioMin = (Reference.UNITS_IMPOSSIBLE / (double)(a * Reference.UNITS_INGOT));
for (int i = 0; i <= (int)(100 / Reference.UNITS_IMPOSSIBLE); i++){//for every ratio possible
double currentRatio = round(i * ratioMin, 6);
System.out.println("Testing for ratio: " + currentRatio);
for (int b = 0; b <= ingotMaterialMaximum; b++){//with every amount of ingots
for (int c = 0; c <= oreMaterialsMaximum; c++){//with every amount of rich ore
for (int d = 0; d <= oreMaterialsMaximum; d++){//with every amount of normal ore
for (int e = 0; e <= oreMaterialsMaximum; e++){//with every amount of poor ore
for (int f = 0; f <= oreMaterialsMaximum; f++){//with every amount of small ore
opt.set(null, null, null, a); //only the ingots are passed in this way
int[] res = opt.optimizeMaterial(new int[]{c, d, e, f, b}, currentRatio);
if (res != null){
int units = 0;
for (int j = 0; j < res.length; j++)
units += res[j] * Reference.MATERIAL_UNITS[j];
double unitsRight = Math.round(a * Reference.UNITS_INGOT * currentRatio);
if (units != (int)unitsRight){ //if the units are not correct, log
writer.println("I: " + a + " Rat: " + currentRatio + " I_av: " + b + " O_Ri: " + c + " O_No: " + d +
" O_Po: " + e + " O_Sm: " + f + " units_wrong: " + units + " units_right: " + (int)unitsRight);
}
}
}
}
}
}
}
}
}
System.out.println("Testing done");
writer.close();
}

The "do not use static variables" advise is indeed too simplistic: the other requirement is to not pass shared objects to static methods running in different threads.
Loop counters and other primitive local variables are thread-safe. The only thing that could make a method non-thread safe is shared state. It appears that you have successfully avoided that by creating separate CrucibleOptimizer and PrintWriter objects.
One refactoring that I would attempt is combining your Runnables. Make a named class that takes loop boundaries, and make four instances of that class in your main. This would work better than four separate anonymous classes that have very few differences:
private static class ThreadRunnable implements Runnable {
final String fileName;
final int[] loopBoundaries;
public ThreadRunnable(String fn, int[] lb) {
fileName = fn;
loopBoundaries = lb;
}
#Override
public void run() {
PrintWriter pw;
try {
pw = new PrintWriter(fileName);
CrucibleOptimizer co = new CrucibleOptimizer();
opt(co, pw, loop4boundries[0], loop4boundries[1]);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
Now you can make four ThreadRunnable instances which share identical code.

Loops in of themselves are thread safe, so no you don't need to worry about that.
The only thing you need to worry about is anything that might be accessed by multiple threads at once.
However your entire architecture really needs some work.
For example why have 4 separate implementations for the runables rather than having one implementation and passing parameters into it to say which chunk to work on.
I also don't know what you are trying to do with all the loops but it's highly unlikely you really need any structure like that.

Related

How to write 1000 records per file or wait to have more record to write then break file?

I have generating data of users with auto-increment ID, then write it to file following these rules:
Name the file in following structure (FileCounter)_(StartID)_(EndID)
Maximum 1000 records per file
If don't have enough 1000 records to write, wait maximum 10s, if any added, write it all to file otherwise, write the remain list to file (not enough 1000), if nothing to write after wait, create empty file with naming (FileCounter)_0_0
My approach is using 2 thread, 1 thread to generate data then push it to the queue, 1 thread to take from the queue add to a list then write the list to the file.
//Generate function
public void generatedata() {
int capacity = 1678;
synchronized(users) {
for(int index = 0; index <capacity; index++) {
users.add(generateUser());
// notify to read thread
users.notifyAll();
}
}
//Write function
public void writeToFile(ArrayList<User> u) {
String fileName ="";
if(!u.isEmpty()) {
String filename = "" + (++FileCounter) + "_"+ u.get(0).getId() + "_" +
u.get(u.size() - 1).getId() + ".txt";
try {
FileWriter writer = new FileWriter(filename, true);
for (User x : u) {
System.out.println(x.toString());
writer.write(x.getId() + " | " + x.getFormatedDate() + " | " +
x.getSex() + " | " + x.getPhoneNum().getPhoneNumber() + " | " +
x.getPhoneNum().getProvider() + "\r\n");
}
writer.close();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else {
try {
fileName = ""+(++FileCounter) +"_0_0.txt";
File f = new File(fileName);
f.createNewFile();
} catch (IOException ex) {
Logger.getLogger(UsersManager.class.getName()).log(Level.SEVERE,
null, ex);
}
}
}
//Read function
public ArrayList<User> ReadFromQueue(ArrayList<User> u) {
while(true) {
try {
int size = users.size();
if(users.isEmpty() && u.size() < 1000) {
users.wait(10000);
if(isChanged(size)) {
System.out.println("Size changed here");
u.add(users.take());
}
else return u;
}
if(u.size() == 1000) {
System.out.println("Check the size is 1000");
return u;
}
u.add(users.take());
} catch (InterruptedException ex) {
Logger.getLogger(UsersManager.class.getName()).log(Level.SEVERE,
null, ex);
}
}
It work fine when I run 1 thread to generate data, 1 thread to read then write data to file but when I use 2++ thread for each generate thread of write thread, There are 1 problems :
The list written in the file still has 1000 records as expected but not sequential at all, it only ascending order.
My output is like:
1_2_1999.txt
2_1_2000.txt
3_2001_3000.txt
My expected output is like:
1_1_1000.txt
2_1001_2000.txt
....
Thanks in advance!
using the thread approach is best for when you do not want to control the amount per file. but since you have a constraint of 1000 records, it's probably easier to use a counter;
public class DataReaderWriter(){
//keeps track of where you left off at, which row in source data.
static int currentRowInSourceData = 0;
public static void main(String[] args){
List<ContactRecord> contacts = getMoreData();
writeRecords(contacts);
}
writeRecords(List<ContactRecord> contacts){
int maxRecords = currentRowInSourceData+1000;
for(int i = currentRowInSourceData;i<maxRecords;i++){
ContactRecord c = contacts.get(i);
writeToFile(c);
currentRowInSourceData++;
}
}
I had a project where I needed to create 90 second previews from larger MP4 files. What I did was to have multiple threads start up with access to a shared Queue of file names. Each thread consumes work from the Queue by using queue.poll().
Here is the Constructor:
public Worker(Queue<String> queue, String conferenceYear, CountDownLatch startSignal, CountDownLatch doneSignal) {
this.queue = queue;
this.startSignal = startSignal;
this.doneSignal = doneSignal;
}
Then, as I said above, I keep polling for data:
public void run() {
while (!queue.isEmpty()) {
String fileName = queue.poll() + ".mp4";
File f = new File("/home/ubuntu/preview_" + fileName);
if (fileName != null && !f.exists()) {
System.out.println("Processing File " + fileName + "....");
I started these threads in another class called WorkLoad:
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
BlockingQueue<String> filesToDownload = new LinkedBlockingDeque<String>(1024);
BlockingQueue<String> filesToPreview = new LinkedBlockingDeque<String>(1024);
BlockingQueue<String> filesToUpload = new LinkedBlockingDeque<String>(1024);
for (int x = 0; x < NUMBER_OF_THREADS; x++) {
workers[x] = new Thread(new Worker(filesToPreview, currentYear, startSignal, doneSignal));
workers[x].start();
}
In your specific case, you could provide each thread its own file name, or a handle on a file. If you want the file names and entries in a chronological sequence, then just start 2 threads, 1 for acquiring data and placing on a queue, with a barrier/limit of 1000 records, and the other thread as a consumer.
the original code creates multiple threads. I am able to create 90 second snippets from over 1000 MP4 videos in about 30 minutes.
Here I am creating a thread per processor, I usually end up with at least 4 threads on my AWS EC2 instance:
/**
* Here we can find out how many cores we have.
* Then make the number of threads NUMBER_OF_THREADS = the number of cores.
*/
NUMBER_OF_THREADS = Runtime.getRuntime().availableProcessors();
System.out.println("Thread Count: "+NUMBER_OF_THREADS);
for (int x = 0; x < NUMBER_OF_THREADS; x++) {
workers[x] = new Thread(new MyClass(param1, param2));
workers[x].start();
}

Set boolean to true, but filewriter still overwrites the file, any advice?

I have created a simple program that sorts integers in an input file using different algorithms. I also use filewriter to output results to another file. Unfortunately no matter how I change my code, file gets overridden. Any advice?
Been searching for answer on google and tried changing the way I input the syntax but nothing works.
important bits:
setting the writer up
try {
FileWriter fileWriter = new FileWriter ("Sorted output.txt");
//BufferedWriter bufferedWriter = new BufferedWriter (fileWriter);
PrintWriter out = new PrintWriter (new FileWriter("Sorted output.txt", true));
outputting to the file
out.println("User's own data set sorted using bubble sort.");
out.println(unsortedArray + Arrays.deepToString(FileOne));
out.println("Sorted Array looks like this:" + Arrays.toString(intArrayBubble));
out.println(timeToSort + bubbleSortIs + bubbleTime + "ms");
it works fine, however its used in a do while loop, with nested if statements, and each one overrides the other.
Rest of code in case its required - UPDATED - still not working
import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class PDD_Sorting {
public static void main (String [] pArgs)
{
//Array for a file
String[] FileOne;
FileOne = new String[0];
int optionOne = 1,
optionTwo = 2,
optionThree = 3,
secondaryOptionOne = 1,
secondaryOptionTwo = 2,
secondaryOptionThree = 3,
userSelection,
subUserSelection;
String unsortedArray = "Unsorted array is: ",
bubbleSort = "Sorted array using bubble sort: ",
selectionSort = "Sorted array using selection sort: ",
insertionSort = "Sorted array using insertion sort: ",
timeToSort = "Time needed to sort this array using ",
bubbleSortIs = "bubble sort is ",
selectionSortIs = "selection sort is ",
insertionSortIs = "insertion sort is ",
welcomeToSorter = "Welcome to the SORTER - program that can sort your txt files containing integeres in an ascending order!",
notFiles = "Integers, not files :)",
pleaseSelect = "Please select one of the following options, by enetering a number asociated with it.",
optionOneUserInput = "1. Sort your own data set - input your own set of data (integers, separated by colons, no spaces) into the Input file.",
optionTwoPredefined = "2. Use predetermind set of data to test the algorythms.",
optionThreeExit = "3. Exit the program.",
subMenuPleaseSelect = "Please select which algorythm would you like to use to sort this file.",
optionBubble = "(1) - Bubble Sort.",
optionSelection = "(2) - Selection Sort.",
optionInsertion = "(3) - Insertion Sort.",
usersDataBubble = "User's own data set sorted using bubble sort.",
sortedArrayLooks = "Sorted Array looks like this:",
msTime = "ms",
usersDataSelection = "User's own data set sorted using selection sort.",
usersDataInsertion = "User's own data set sorted using insertion sort.",
validOption = "Please enter a valid option i.e. 1,2 or 3",
lessThanZero = "If time shown in ms is 0, that means the time needed to conduct the sort is shorter than 1ms.",
fileCreated = "File created.",
terminatingProgram = "Terminating the program.",
unableToWriteFile = "Unable to write to file";
System.out.println(welcomeToSorter);
System.out.println(notFiles);
Scanner tInput = new Scanner (System.in);
try {
FileWriter fileWriter = new FileWriter ("Sorted output.txt");
//BufferedWriter bufferedWriter = new BufferedWriter (fileWriter);
PrintWriter out = new PrintWriter (new FileWriter("Sorted output.txt", true));
do {
System.out.println(pleaseSelect);
System.out.println(optionOneUserInput);
System.out.println(optionTwoPredefined);
System.out.println(optionThreeExit);
// Scanner tInput = new Scanner (System.in);
userSelection = tInput.nextInt();
if (userSelection == optionOne) {
//System.out.println("Please enter a valid path for your file.");
String[] splitFile = null;
//String userFile = tInput.next();
FileOne = getAndPrepareFile(splitFile);
System.out.println(subMenuPleaseSelect);
System.out.println(optionBubble);
System.out.println(optionSelection);
System.out.println(optionInsertion);
subUserSelection = tInput.nextInt();
if (subUserSelection == secondaryOptionOne) {
int size = FileOne.length;
int [] intArrayBubble = new int [size];
for(int i=0; i<size; i++) {
intArrayBubble[i] = Integer.parseInt(FileOne[i]);
}
bubbleSort(intArrayBubble);
long bubbleTime = timeCount(intArrayBubble);
out.println(usersDataBubble);
out.println(unsortedArray + Arrays.deepToString(FileOne));
out.println(sortedArrayLooks + Arrays.toString(intArrayBubble));
out.println(timeToSort + bubbleSortIs + bubbleTime + msTime);
}
else if (subUserSelection == secondaryOptionTwo) {
int size2 = FileOne.length;
int [] intArraySelection = new int [size2];
for(int i=0; i<size2; i++) {
intArraySelection[i] = Integer.parseInt(FileOne[i]);
}
doSelectionSort(intArraySelection);
long selectionTime = timeCount(intArraySelection);
out.println(usersDataSelection);
out.println(unsortedArray + Arrays.deepToString(FileOne));
out.println(sortedArrayLooks + Arrays.toString(intArraySelection));
out.println(timeToSort + selectionSortIs + selectionTime + msTime);
}
else if (subUserSelection == secondaryOptionThree) {
int size3 = FileOne.length;
int [] intArrayInsertion = new int [size3];
for(int i=0; i<size3; i++) {
intArrayInsertion[i] = Integer.parseInt(FileOne[i]);
}
doInsertionSort(intArrayInsertion);
long insertionTime = timeCount(intArrayInsertion);
out.println(usersDataInsertion);
out.println(unsortedArray + Arrays.deepToString(FileOne));
out.println(sortedArrayLooks + Arrays.toString(intArrayInsertion));
out.println(timeToSort + insertionSortIs + insertionTime + msTime);
}
else {
System.out.println(validOption);
tInput.next();
}
}
else if (userSelection == optionTwo){
//file being prepared and loaded via function
String[] splitFilePredefined = null;
FileOne = getAndPrepareFilePredefined(splitFilePredefined);
//converting string array into int array so the method can sort it.
int size = FileOne.length;
int [] intArrayBubble = new int [size];
for(int i=0; i<size; i++) {
intArrayBubble[i] = Integer.parseInt(FileOne[i]);
}
int size2 = FileOne.length;
int [] intArraySelection = new int [size2];
for(int i=0; i<size2; i++) {
intArraySelection[i] = Integer.parseInt(FileOne[i]);
}
int size3 = FileOne.length;
int [] intArrayInsertion = new int [size3];
for(int i=0; i<size3; i++) {
intArrayInsertion[i] = Integer.parseInt(FileOne[i]);
}
//inserting pre-prepared int arrays into variables including a timecount method
int bubbleTime = timeCount(intArrayBubble);
int selectionTime = timeCount(intArraySelection);
int insertionTime = timeCount(intArrayInsertion);
//sorting array using various sorts
bubbleSort(intArrayBubble);
doSelectionSort(intArraySelection);
doInsertionSort(intArrayInsertion);
//out.println("Sorted arrray using insertion sort looks like this: " + Arrays.toString(intArrayInsertion));
out.println(timeToSort + bubbleSortIs + bubbleTime + "ms");
out.println(timeToSort + selectionSortIs + selectionTime + "ms");
out.println(timeToSort + insertionSortIs + insertionTime + "ms");
out.println(lessThanZero);
System.out.println(fileCreated);
}
else if (userSelection == optionThree){
System.out.println(terminatingProgram);
System.exit(0);
}
else {
System.out.println(validOption);
tInput.next();
}
out.flush();
out.close();
//tInput.close();
}while (userSelection != optionThree);
}
catch (Exception e)
{
System.out.println(unableToWriteFile);
tInput.next();
}
tInput.close();
}//end main
//method that fetches the file from predefined, hardcoded location and removes comas, esentially prepares the file for the next phase
private static String[] getAndPrepareFile (String[] splitFile)
{
Scanner fileIn = null;
try
{
fileIn = new Scanner(new FileInputStream("C:\\Users\\Greg\\Documents\\Programming\\PDD - Assignment 1\\Input.txt"));
String fileNew = fileIn.next();
splitFile = fileNew.split(",");
//System.err.println(Arrays.toString(splitFile)); //Arrays.toString needed to print the array correctly, otherwise it prints the address of the object
fileIn.close();
}
catch (IOException e)
{
System.out.println("File not found.");
//System.exit(0);
}
return splitFile;
}
//as above but works for predefined file, that can be generated using randomNumber.java program
private static String[] getAndPrepareFilePredefined (String[] splitFilePredefined)
{
Scanner fileIn = null;
try
{
fileIn = new Scanner(new FileInputStream("C:\\Users\\Greg\\Documents\\Programming\\PDD - Assignment 1\\Generated input.txt"));
String fileNew = fileIn.next();
splitFilePredefined = fileNew.split(",");
//System.err.println(Arrays.toString(splitFile)); //Arrays.toString needed to print the array correctly, otherwise it prints the address of the object
fileIn.close();
}
catch (IOException e)
{
System.out.println("File not found.");
//System.exit(0);
}
return splitFilePredefined;
}
//method used to sort a file using bubble sort
private static void bubbleSort(int[] arr) {
int n = arr.length;
int temp = 0;
for(int i=0; i < n; i++){
for(int j=1; j < (n-i); j++){
if(arr[j-1] > arr[j]){
//swap elements
temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;
}
}
}
}
//method used to sort a file using selection sort
private static int[] doSelectionSort(int[] arr){
for (int i = 0; i < arr.length - 1; i++)
{
int index = i;
for (int j = i + 1; j < arr.length; j++)
if (arr[j] < arr[index])
index = j;
int smallerNumber = arr[index];
arr[index] = arr[i];
arr[i] = smallerNumber;
}
return arr;
}
//method used to sort a file using sinsertion sort
private static int[] doInsertionSort(int[] input){
int temp;
for (int i = 1; i < input.length; i++) {
for(int j = i ; j > 0 ; j--){
if(input[j] < input[j-1]){
temp = input[j];
input[j] = input[j-1];
input[j-1] = temp;
}
}
}
return input;
}
//method used to calculate how much time has lapsed while using any of the given sort methods, outputs in ms, if less than 1 ms, outputs 0ms
private static int timeCount (int[] anArray)
{
long start = System.nanoTime();
Arrays.sort(anArray);
long end = System.nanoTime();
long timeInMillis = TimeUnit.MILLISECONDS.convert(end - start, TimeUnit.NANOSECONDS);
//System.out.println("Time spend in ms: " + timeInMillis);
return (int) timeInMillis;
}
}//end class
File gets constantly overridden, how do i stop this and make it add to file instead?
You don't need the first FileWriter fileWriter = new FileWriter("Sorted output.txt");; this is actually creating/overwriting the file, after which your PrintWriter opens it again for appending.
So, just change
// ... omitting beginning
try {
FileWriter fileWriter = new FileWriter ("Sorted output.txt");
//BufferedWriter bufferedWriter = new BufferedWriter (fileWriter);
PrintWriter out = new PrintWriter (new FileWriter("Sorted output.txt", true));
do {
// ... omitting rest
to
// ... omitting beginning
try {
//BufferedWriter bufferedWriter = new BufferedWriter (fileWriter);
PrintWriter out = new PrintWriter (new FileWriter("Sorted output.txt", true));
do {
// ... omitting rest
Move out.close() outside the loop
else {
System.out.println("Please enter a valid option i.e. 1,2 or 3");
tInput.next();
}
out.flush();
/* THIS -> out.close(); <- THIS */
//tInput.close();
}while (userSelection != optionThree);
out.close();
}
I tried your code and your problem is not that the file is being overwritten, but that you are closing the outputstream in the first iteration.

Java ArrayIndexOutOfBoundsException keeps appearing while trying to find most occuring word in file

I am currently building a program which reads a file and prints the most occurring words and how many times each word appears like so:
package WordLookUp;
import java.util.*;
import java.io.*;
import java.lang.*;
public class WordLookUp {
private String[] mostWords;
private Scanner reader;
private String line;
private FileReader fr;
private BufferedReader br;
private List<String> original;
private String token = " ";
public WordLookUp(String file) throws Exception {
this.reader = new Scanner(new File(file));
this.original = new ArrayList<String>();
while (this.reader.hasNext()) { //reads file and stores it in string
this.token = this.reader.next();
this.original.add(token); //adds it to my arrayList
}
}
public void findMostOccurringWords() {
List<String> mostOccur = new ArrayList<String>();
List<Integer> count = new ArrayList<Integer>();
int counter = 0;
this.mostWords = this.token.split(" "); //storing read lines in mostWords arrayList
try {
for (int i = 0; i < original.size(); i++) {
if (this.original.equals(this.mostWords[i])) {
counter++; //increase counter
mostOccur.add(this.mostWords[i]);
count.add(counter);
}
}
for (int i = 0; i < mostOccur.size(); i++) {
System.out.println("Word: " + mostOccur.get(i) + " count: " + count.get(i));
}
} catch (ArrayIndexOutOfBoundsException ae) {
System.out.println("Illegal index");
}
}
}
package WordLookUp;
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
WordLookUp wL = new WordLookUp("tiny1.txt");
wL.findMostOccurringWords();
}
}
So when I keep running my file, it throws the exception I gave it: "Illegal index". I think it is my findMostOccuringWords method. To me the logic feels correct, but I don't know why it is throwing an ArrayIndexOutOfBoundsException. I tried playing with the for loops and tried to go from int i = 0 to i < mostOccur.size() - 1 but that is not working either. Is my logic wrong ? I am not allowed to use a hashmap and our professor gave us a hint that we can do this assignment easily with arrays and ArrayLists (no other built in functions, but regexes is highly recommended for use as well for the rest of the assignment). I put a private FileReader and BufferedReader up there as I am trying to see if they would work better or not. Thanks for the advice!
Can you try to use the following codes? I think your current algorithm is wrong.
public class WordLookUp {
private List<String> original;
private List<String> mostOccur = new ArrayList<String>();
private List<Integer> count = new ArrayList<Integer>();
public WordLookUp(String file) throws Exception {
try(Scanner reader = new Scanner(new File(file));){
this.original = new ArrayList<String>();
String token = " ";
while (reader.hasNext()) { //reads file and stores it in string
token = reader.next();
this.original.add(token); //adds it to my arrayList
findMostOccurringWords(token);
}
}
}
public void findMostOccurringWords(String token) {
int counter = 0;
String[] mostWords = token.split(" "); //storing read lines in mostWords arrayList
try {
for (int i = 0; i < mostWords.length; i++) {
for(int j = 0; j < this.original.size(); j++) {
if (original.get(j).equals(mostWords[i])) {
counter++; //increase counter
}
}
if (mostOccur.contains(mostWords[i])) {
count.set(mostOccur.indexOf(mostWords[i]),counter);
}else {
mostOccur.add(mostWords[i]);
count.add(counter);
}
}
} catch (ArrayIndexOutOfBoundsException ae) {
System.out.println("Illegal index");
}
}
public void count() {
for (int i = 0; i < mostOccur.size(); i++) {
System.out.println("Word: " + mostOccur.get(i) + " count: " + count.get(i));
}
}
}
public class Main {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
WordLookUp wL = new WordLookUp("F:\\gc.log");
wL.count();
}
}
Here in this loop:
for (int i = 0; i < mostOccur.size(); i++) {
System.out.println("Word: " + mostOccur.get(i) + " count: " + count.get(i));
}
You check to make sure that i is within bounds for mostOccur but not count. I would add a condition to check to make sure it is in bounds. Such as:
for (int i = 0; i < mostOccur.size() && i < count.size(); i++) {
System.out.println("Word: " + mostOccur.get(i) + " count: " + count.get(i));
}

Strange bug while using import com.sun.net.httpserver.HttpExchange and HTTPserver in java

I'm currently working on a "big" project, and I'm facing a incomprehensible bug. This one is just beyond my competence.
I will try to be as clear as possible, because there is a lot of code, I'll try to show you some screenshots of the debug intereface (breakpoint).
Basically, this is a program about surveys, admins can create surveys, users can answer them.. basic.
I'm doing it in java, using a HttpServer which creates a lot of contexts, (html pages) using the createContext method .
I'm also using a RMI object to manage the surveys and the results.
I have written a form for an admin to create a new survey, using the post method, i post it to another page so as to process the query.
Once I have done that, I have three variables to create a new survey : an id, a title, an array of questions, and an integer to say if the survey will be visible for the user or not. Note: I am 100% sure that those variables are correct
(Sorry for the french words in the code / screens, I'll try to rename most of them)
ISurveyManagement test = (ISurveyManagement)Naming.lookup("rmi://localhost/surveys");
I get my RMI object,
test.addSurvey(nsondage, titre, questions, 1);
Then I call my method to add the survey. (of course, all of those instruction are in the Handle method, from the interface HttpHandler)
This is what happens after the break point :
I have clicked on my button, the title has been correctly printed
Same thing for the RMI object, not null or anything, Then, we are supposed to go into the method of the RMI object:
But we are here!!! ServerImpl ExChange run?? what!! I pass a few steps
I passed all the step of the third picture, now we are again in the beggining of the Handle method?? why? and what about my call of addSurvey??
If I pass again a lot of steps, you will see that "HELLO", my title, and the RMI object will be printed again, then instead of going into my method it goes int that Thread-2 thing again and then crash...
I'm really sorry for this big ugly question, but I'm completly lost, I'm searching for hour ><
Thank you so much by advance if you can help me
EDIT:
this is the addSurvey method:
#Override
public void addSurvey(int n, String title, ArrayList<Question> q, int active) throws RemoteException {
System.out.println("anything");
this.loadSurveys();
this.objSurveys.add(new Survey(n, title, q, active));
this.saveSurveys();
}
The sysout at the begining is not displayed, I'm sure that the methods load and save work perfectly, I'm using them in an other functionnality.
EDIT2: as you asked, this is the code of the whole class test
public class CreationManagement implements HttpHandler {
#Override
public void handle(HttpExchange t) throws IOException {
String reponse =
"<html>"
+"<head>"
+ "<title>Page admin</title>"
+"<meta http-equiv=\"content-type\" content=\"text/plain; charset=utf-8\"/>"
+"</head>"
+"<body style=\"font-family: Georgia, Times, serif;padding:20px;width:400px;border:1px solid #172183;\">"
+"<p style=\"text-align:center;padding:5px;color:white;background:#172183;\">Vos changements ont bien été pris en compte!</p>"
+ "<form action=\"http://localhost:8080/admin.html\">"
+ "<button style=\"border: none;color: #ffffff;display: block;margin: auto;background: #172183;padding: 5px 20px;cursor:pointer;\">Retour</button>"
+ "</form>";
URI requestedUri = t.getRequestURI();
String query = requestedUri.getRawQuery();
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(t.getRequestBody(),"utf-8"));
} catch(UnsupportedEncodingException e) {
System.err.println("Error flow" + e);
System.exit(-1);
}
try {
query = br.readLine();
} catch(IOException e) {
System.err.println("Error while reading line " + e);
System.exit(-1);
}
/*String [] p = query.split("&");
for (int i = 0 ; i < p.length ; i++) {
reponse += p[i] + "<br>";
}*/
ISurveyManagement test = null;
try {
test = (ISurveyManagement)Naming.lookup("rmi://localhost/sondages");
} catch(NotBoundException e) {
System.err.println("Error while getting rmi object : " + e);
System.exit(-1);
} catch(MalformedURLException e) {
System.err.println("URL mal forme : " + e);
System.exit(-1);
} catch(RemoteException e) {
System.err.println("not possible to get rmi obj : " + e);
System.exit(-1);
}
test.loadSurveys();
int length = test.getSurveys().size();
int nsurvey= length + 1;
String[] op = query.split("&");
String title = op[0].split("=")[1];
String[] params = Arrays.copyOfRange(op, 1, op.length);
/*for (int a = 0 ; a < params.length ; a++) {
System.out.println(a + " " +params[a]);
}*/
ArrayList<Question> questions = new ArrayList<Question>();
//System.out.println("taille " + params.length );
for (int i = 0 ; i < params.length ; i++) {
if (i%5 == 0) {
String[] detQ = params[i].split("=");
int nq = Integer.parseInt(detQ[0].substring(1, detQ[0].length()));
String libq = detQ[1];
Question q = new Question(nq, libq, nsondage);
q.setReponses(new ArrayList<Reponse>());
questions.add(q);
} else {
String[] detR = params[i].split("=");
if (detR.length == 2) {
String lib = detR[1];
int q = Integer.parseInt(detR[0].split("_")[0]);
int num = Integer.parseInt(detR[0].split("_")[1]);
String l = "";
if (num == 1) {
l = "A";
} else if (num == 2) {
l = "B";
} else if (num == 3) {
l = "C";
} else if (num == 4) {
l = "D";
}
Reponse r = new Reponse(l, lib, q, nsondage);
questions.get(q-1).getReponses().add(r);
}
}
}
System.out.println("HELLO");
System.out.println(title);
System.out.println(test);
//Survey s = new Survey(nsurvey, title, questions, 1);
test.addSurvey(nsurvey, title, questions, 1);
//System.out.println(s.display());
System.out.println(nsurvey);
reponse += "</body></html>";
try {
Headers h = t.getResponseHeaders();
h.set("Content-Type", "text/html; charset=utf-8");
t.sendResponseHeaders(200, 0);
} catch(IOException e) {
System.err.println("error while sending header : " + e);
System.exit(-1);
}
try {
OutputStream os = t.getResponseBody();
os.write(reponse.getBytes());
os.close();
} catch(IOException e) {
System.err.println("error sending corps : " + e);
}
}
}
Is I said the survey is displayed correctly when I try to display it, the object is correctly created.

Can't give values properly trougth serialization

It is going to be a very basic question I suppose, but I've been searching for the answer fo hours and I just can't figure out where's my code go wrong. So: I do serialze an object called SerializableObject, than read it back. In the deserializing method I get a temporary object, which I want to copy to an other new SerializeableObject, wich I want to use after, but I can't copy it properly, however the temporary object got the values properly, at the deserialization. Here's my classes:
SeralizeableObject:
public class SerializableObject implements Serializable, Cloneable{
private Vector<int[]> mixMade;
private Vector<int[]> stepsMade;
private long time;
private int steps;
private int winnerState;
public SerializableObject(Vector<int[]> mixMade, Vector<int[]> stepsMade,
long time, int steps, int winnerState) {
this.mixMade = mixMade;
this.stepsMade = stepsMade;
this.time = time;
this.steps = steps;
this.winnerState = winnerState;
}
#Override
public String toString() {
String str = "";
for(int[] mixEl : mixMade){
str += mixEl[0] + ", " + mixEl[1] + "|";
}
str += " mixes\n";
for(int[] stepEl : stepsMade){
str += stepEl[0] + ", " + stepEl[1] + "|";
}
str += " steps\n";
str += "time: " + time + ", stepsnum: " + steps + ",
winstate: " + winnerState;
return str;
}
#Override
public SerializableObject clone() {
SerializableObject serObj;
Vector<int[]> mixMadeTemp = new Vector<int[]>();
Vector<int[]> stepsMadeTemp = new Vector<int[]>();
for(int i = 0; i < mixMade.size(); ++i){
mixMadeTemp.add(mixMade.get(i));
}
for(int i = 0; i < stepsMade.size(); ++i){
stepsMadeTemp.add(stepsMade.get(i));
}
serObj = new SerializableObject(mixMadeTemp, stepsMadeTemp,
time, steps, winnerstate);
return serObj;
}
}
The Serializator:
public class ObjectSerializator {
public ObjectSerializator() {
}
public void toFile(String filepath, SerializableObject serObj){
ObjectOutputStream out;
try{
FileOutputStream fileOut = new FileOutputStream(filepath);
out = new ObjectOutputStream(fileOut);
out.writeObject(serObj);
}catch (IOException ex) {
}
}
public void fromFile(String filepath, SerializableObject serObj){
SerializableObject tempSerObj;
try {
FileInputStream fileIn = new FileInputStream(filepath);
ObjectInputStream in = new ObjectInputStream(fileIn);
tempSerObj = (SerializableObject) in.readObject();
System.out.println(tempSerObj + "TEMP");
serObj = tempSerObj.clone();
in.close();
fileIn.close();
} catch (IOException ex) {
} catch (ClassNotFoundException ex) {
}
}
}
note: the serobj reference points properly to the good values, inside the fromFile method
A filechooser class, where the user can chhose the file to load from:
public class FileChooser extends JFileChooser{
private ObjectSerializator serializator;
public FileChooser() {
serializator = new ObjectSerializator();
}
public void load(SerializableObject serObj){
int retValue = showOpenDialog(null);
serializator.fromFile(getSelectedFile().getAbsolutePath(), serObj);
}}
than in my mainfram I call it from a buttonaction
public void load(){
SerializableObject serObj = new SerializableObject(new Vector<int[]>(), new
Vector<int[]>(), 10, 10, 200);
fileChooser.load(serObj);
System.out.println(serObj + " LAST");
}
Here's my output:
3, 2|4, 3| mixes
0, 0|0, 1|0, 0| steps
time: 6000, stepsnum: 3, winstate: 0TEMP
-------------------
mixes
steps
time: 10, stepsnum: 10, winstate: 200 LAST
The object you've deserialized gets lost.
In your fromFile method, you have the following line:
serObj = tempSerObj.clone();
But serObj is an argument to the method. The line above changes the local serObj variable, whereas the original object remains intact. The calling method (load) still holds a reference to the old (original) object.
Your fromFile method shouldn't accept a SerializableObject as an argument; rather, it should return one. Then the FileChooser.load method should return it as well. Finally, the load method of the main frame should look something like:
public void load() {
SerializableObject originalObject = new SerializableObject(new Vector<int[]>(), new Vector<int[]>(), 10, 10, 200);
// Here you can do something with the newly created object, such as save it to a file.
SerializableObject deserializedObject = fileChooser.load();
System.out.println(deserializedObject + " LAST");
}

Categories

Resources