Why is ArrayList not being written into "MyCalendar.txt"? Even when I use out.write() it still returns false but does not write to the file.
import java.util.*;
import java.io.*;
public static Boolean addAppointment(ArrayList<String> calendar,
String specifiedDay,
String specifiedTime) {
PrintWriter out = new PrintWriter("myCalendar.txt"); //declare calendar file
for (int i = 0; i<calendar.size(); i++) {
String index = calendar.get(i);
if (index.equals(specifiedDay + "" + specifiedTime))
{
out.println(specifiedDay + "" + specifiedTime);
return false;
}
}
return true;
}
Below 2 are important to flush data to file and close the stream
out.flush();
out.close();
Regards,
you forgot to close it:
out.close()
So, a couple of things here.
If you're using Java 7, you should consider using try-with-resources. This will absolutely ensure that your PrintWriter is closed after you're done.
try (PrintWriter out = new PrintWriter("somefile.txt")) {
// code
} catch (FileNotFoundException e) {
System.out.println("Bang!");
}
Next, there are a few cases in which the file could not be written to, either in part or at all:
calendar.size() == 0
index.equals(specifiedDay + "" + specifiedTime)
If the first condition is met, nothing is written and the method happily returns true. Probably not what you expected.
If the second condition is met, you write the first element, and early return. It would probably be a better idea to place that in your loop condition, and return the return value when you're done looping.
int i = 0;
boolean good = true;
while(good && i < calendar.size()) {
// critical actions
String index = calendar.get(i);
if(index.equals(specifiedDay + "" + specifiedTime)) {
good = false;
}
}
// other code
return good;
If that condition is never met, then nothing is ever written to the file.
The default behavior of PrintWriter is not to automatically flush the buffer. See the PrintWriter Documentation for more details.
Alternatively, you might have a data issue:
String index = calendar.get(i);
if (index.equals(specifiedDay + "" + specifiedTime))
If this condition isn't satisfied, you won't print anything out. Have you made sure this condition is true?
Related
I'm a small java developer currently working on a discord bot that I made in Java. one of the features of my bot is to simply have a leveling system whenever anyone sends a message (and other conditions but this is irrelevant for the problem I'm encountering).
Whenever someone sends a message an event is fired and a thread is created to compute how much exp the user should gain. and eventually, the function to edit the storage file is called.
which works fine when called sparsely. but if two threads try to write on the file at once, the file usually gets deleted or truncated. either of these two cases being undesired behavior
I then tried to make a queuing system that worked for over 24h but still failed once so it is more stable in a way. I only know the basics of how threads work so I may've skipped over an important thing that causes the problem
the function looks like this
Thread editingThread = null;
public boolean editThreadStarted = false;
HashMap<String, String> queue = new HashMap<>();
public final boolean editParameter(String key, String value) {
queue.put(key, value);
if(!editThreadStarted) {
editingThread = new Thread(new Runnable() {
#Override
public void run() {
while(queue.keySet().size() > 0) {
String key = (String) queue.keySet().toArray()[0];
String value = queue.get(key);
File inputFile = getFile();
File tempFile = new File(getFile().getName() + ".temp");
try {
tempFile.createNewFile();
} catch (IOException e) {
DemiConsole.error("Failed to create temp file");
handleTrace(e);
continue;
}
//System.out.println("tempFile.isFile = " + tempFile.isFile());
try (BufferedReader reader = new BufferedReader(new FileReader(inputFile)); BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile))){
String currentLine;
while((currentLine = reader.readLine()) != null) {
String trimmedLine = currentLine.trim();
if(trimmedLine.startsWith(key)) {
writer.write(key + ":" + value + System.getProperty("line.separator"));
continue;
}
writer.write(currentLine + System.getProperty("line.separator"));
}
writer.close();
reader.close();
inputFile.delete();
tempFile.renameTo(inputFile);
} catch (IOException e) {
DemiConsole.error("Caught an IO exception while attempting to edit parameter ("+key+") in file ("+getFile().getName()+"), returning false");
handleTrace(e);
continue;
}
queue.remove(key);
}
editThreadStarted = false;
}
});
editThreadStarted = true;
editingThread.start();
}
return true;
}
getFile() returns the file the function is meant to write to
the file format is
memberid1:expamount
memberid2:expamount
memberid3:expamount
memberid4:expamount
the way the editing works is by creating a temporary file to which i will write all of the original file's data line by line, checking if the memberid matches with what i want to edit, if it does, then instead of writing the original file's line, i will write the new edited line with the new expamount instead, before continuing on with the rest of the lines. Once that is done, the original file is deleted and the temporary file is renamed to the original file, replacing it.
This function will always be called asynchronously so making the whole thing synchronous is not an option.
Thanks in advance
Edit(1) :
I've been suggested to use semaphores and after digging a little into it (i never heard of semaphores before) it seems to be a really good option and would remove the need for a queue, simply aquire in the beginning and release at the end, nothing more required!
I ended up using semaphores as per user207421's suggestions and it seems to work perfectly
I simply put delays between each line write to artificially make the task longer and make it easier to have multiple threads trying to write at once, and they all wait for their turns!
Thanks
So I've got a program that generates large binary sequences, and if the string length goes above 4094 it doesn't print. Here's a code snippet the highlights the problem:
private static void ALStringTest() {
String al = "1";
for (int i = 0; i < 5000; i++) {
al += "1";
System.out.println(al.length());
System.out.println(al);
System.out.println(al.isEmpty());
}
}
What's interesting is the length continues to increase, and the boolean value stays false, but I'm unable to see the strings of length 4095 and above.
It's also not a printing error, as I've attempted to write the strings to xml and they don't appear either, all I get is spaces equal to the strings length.
Edit:
I've tried printing a file using this snippet and I have the same problem:
private static void ALStringTest() throws IOException {
File fout = new File("out.txt");
FileOutputStream fos = new FileOutputStream(fout);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
String al = "1";
for (int i = 0; i < 5000; i++) {
al += "1";
bw.write(al);
bw.newLine();
System.out.println(al.length());
System.out.println(al);
System.out.println(al.isEmpty());
}
bw.close();
}
However, people have confirmed this works on external machines (thanks) (as well as on my own using javac, I'm lead to believe this may be Eclipse specific.
Anyone know why Eclipse might be doing this?
the boolean will stay false as hashcode of al is some value and that of "" is 0, == checks for reference.
So it turns out it was an IDE issue:
Simply copying it to a text editor revealed the strings. I'll update when I find the offending option.
The possible reason of this maybe the defect of console which is rapidly printing output results. So that maybe it's only happening in console output. I've tested those each and the result was sometime it prints false only more than 6 times or sometime it prints only length That shouldn't be happened as scenario. But everything works fine when we use thread and make it sleep even 1 millisecond. The output is fine enough as codes,
class ThreadTest extends Thread {
public ThreadTest() {
super();
}
public void run() {
String al = "1";
for (int i = 0; i < 5000; i++) {
try {
sleep(1);
al += "1";
System.out.println(al.length());
System.out.println(al);
System.out.println(al.equals(""));
} catch (InterruptedException e) {
}
}
}
}
Call this in main method
new ThreadTest().start();
I've got some Java code that runs quite the expected way, but it's taking some amount of time -some seconds- even if the job is just looping through an array.
The input file is a Fasta file as shown in the image below. The file I'm using is 2.9Mo, and there are some other Fasta file that can take up to 20Mo.
And in the code im trying to loop through it by bunches of threes, e.g: AGC TTT TCA ... etc The code has no functional sens for now but what I want is to append each Amino Acid to it's equivalent bunch of Bases. Example :
AGC - Ser / CUG Leu / ... etc
So what's wrong with the code ? and Is there any way to do it better ? Any optimization ? Looping through the whole String is taking some time, maybe just seconds, but need to find a better way to do it.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class fasta {
public static void main(String[] args) throws IOException {
File fastaFile;
FileReader fastaReader;
BufferedReader fastaBuffer = null;
StringBuilder fastaString = new StringBuilder();
try {
fastaFile = new File("res/NC_017108.fna");
fastaReader = new FileReader(fastaFile);
fastaBuffer = new BufferedReader(fastaReader);
String fastaDescription = fastaBuffer.readLine();
String line = fastaBuffer.readLine();
while (line != null) {
fastaString.append(line);
line = fastaBuffer.readLine();
}
System.out.println(fastaDescription);
System.out.println();
String currentFastaAcid;
for (int i = 0; i < fastaString.length(); i+=3) {
currentFastaAcid = fastaString.toString().substring(i, i + 3);
System.out.println(currentFastaAcid);
}
} catch (NullPointerException e) {
System.out.println(e.getMessage());
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
} finally {
fastaBuffer.close();
}
}
}
currentFastaAcid = fastaString.toString().substring(i, i + 3);
Please replace with
currentFastaAcid = fastaString.substring(i, i + 3);
toString method of StringBuilder create new instance of String object every time you call it. It still contain a copy of all your large string. If you call substring directly from StringBuilder it will return a small copy of substring.
Also remove System.out.println if you don't really need it.
The big factor here is you are doing the call to substring over a new String each time.
Instead, use substring directly over the stringbuilder
for (int i = 0; i < fastaString.length(); i+=3){
currentFastaAcid = fastaString.substring(i, i + 3);
System.out.println(currentFastaAcid);
}
Also, instead of print the currentFastaAcid each time, save it into a list and print this list at the end
List<String> acids = new LinkedList<String>();
for (int i = 0; i < fastaString.length(); i+=3){
currentFastaAcid = fastaString.substring(i, i + 3);
acids.add(currentFastaAcid);
}
System.out.println(acids.toString());
Your main problem besides the debug output surely is, that you are creating a new String with your completely read data from the file in each iteration of your loop:
currentFastaAcid = fastaString.toString().substring(i, i + 3);
fastaString.toString() will give the same result in each iteration and therefore is redundant. Get it outside the loop and you will surely save some seconds runtime.
Apart from suggested optimization in the serial code, I will go for parallel processing to reduce time further. If you have really big file, you can divide the work of reading file and processing read-lines, in separate threads. That way, when one thread is busy reading nextline from large file, other thread can process read-lines and print them on console.
If you remove the
System.out.println(currentFastaAcid);
line in the for loop, you will gain quite decent time.
I need some help please writing the output to a file and I can't get it to work. If I use the System.out.println it works. If I create the file stream and Buffered Writer in the actual method, it creates the file but doesn't write anything to it. I'm assuming it's because my method is recursive and creates a new file every time the method calls it self again. So I created another print method and used the string value key[i] as the string parameter and it does nothing.
Any help is appreciated, thank you.
public void print(String s)throws IOException
{
fstream = new FileWriter("out.txt", true);
out = new BufferedWriter(fstream);
try{
out.write("From print: " + s + " ");
out.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
public void generate() throws IOException
{
while (k<randomWordNum())
{
if (randomNum() <= sumOfFreq[0])
{
//System.out.println(getKey[0] + " ");
print(getKey[i]);
i++;
k++;
generate();
}
if (randomNum() >= sumOfFreq[i] && randomNum() <= sumOfFreq[i+1])
{
//System.out.println("From generate: " + getKey[i+1] + " ");
print(getKey[i+1]);
i++;
k++;
generate();
}
else
{
i++;
generate();
}
}//while
}//generate
You need to .close the file to make sure things get written
I think that constructor of FileWriter will overwrite the file. So you'll need to use a code line like this:
fstream = new FileWriter("out.txt", true); // true for appending
Also, always close a file before it goes out of scope, otherwise it might never get flushed or closed if you are unlucky...
And one more thing, assuming that is not some sort of debug/troubleshooting code, "never" catch Exception. If you do catch it, be sure to re-throw it asyou got it after logging or whatever you did with it. But, in general, always catch a more specific exception type.
I have written a program to monitor the status of some hard drives attached to a RAID on Linux. Through this program I execute several command line commands. An interesting error occurs though....the program runs for a good three minutes before it seems that it can no longer correctly execute the command it had been previously executing (for many iterations).
It spits out an array index error (my variable driveLetters[d]) because it appears to miss the drive somehow (even though it found it hundreds of times before).
Other things to note...if I tell it to reset int "d" to "0" if it exceeds the number of drives...the program won't crash and instead will just become stuck in an infinite loop.
Also, the time at which the program crashes varies. It doesn't appear to crash after a set number of intervals. Finally, I don't get any kind of memory leak errors.
Here is some of code that should reveal the error:
public static void scsi_generic() throws IOException, InterruptedException
{
int i =0;
int d =0;
int numberOfDrives = 8;
char driveLetters[] = {'b','c','d','e','f','g','h','i','j','k','l','m'};
String drive = "";
while (i <= numberOfDrives)
{
System.out.println("position 1");
List<String> commands = new ArrayList<String>();
commands.add("cat");
commands.add("/sys/class/scsi_generic/sg"+i+"/device/sas_address");
SystemCommandExecutor commandExecutor = new SystemCommandExecutor(commands);
int driveFound = commandExecutor.executeCommand();
if (driveFound == 0)
{
System.out.println("Folder: sg" + i + " was found." );
StringBuilder stdout = commandExecutor.getStandardOutputFromCommand();
String data = stdout.toString();
String sas = data.substring(11,12);
int sasA = Integer.parseInt(sas,16);
boolean matchedSG = false;
while (matchedSG == false)
{
System.out.println("position2");
List<String> lookSD = new ArrayList<String>();
lookSD.add("test");
lookSD.add("-d");
lookSD.add("/sys/class/scsi_generic/sg"+i+"/device/block:sd" + driveLetters[d]);
SystemCommandExecutor commandSearch = new SystemCommandExecutor(lookSD);
int sdFound = commandSearch.executeCommand();
StringBuilder stdout3 = commandSearch.getStandardOutputFromCommand();
StringBuilder stderr = commandSearch.getStandardErrorFromCommand();
String sdFound2 = stdout3.toString();
if (sdFound == 0)
{
matchedSG = true;
System.out.println("Found the SD drive.");
drive = "sd"+driveLetters[d];
System.out.println(sasA);
hdsas.set(sasA , sas);
d = 0;
i++;
loadDrives(drive , sasA);
}
/* else if (sdFound != )
{
System.out.println("Error:" + sdFound);
System.out.println(d+ " "+ i);
}
*/
else if ( d >= 8)
{
System.out.println("Drive letter: " + driveLetters[d]);
System.out.println("Int: " + i);
// System.out.println(sdFound2);
System.out.println("sd error: "+ sdFound);
// System.out.println(stderr);
//System.out.println(sdFound2 + " m");
}
else
{
d++;
}
}
}
else
{
System.out.println("Folder: sg" + i + " could not be found.");
i++;
}
d =0;
}
}
Any help or suggestions would be awesome! Thanks.
EDIT:
The solution I found was to use the java library for testing if a directory exists rather than doing it through the linux command line.
Ex:
File location = new File("directory");
if (location.exists())
{
}
No idea why it works and doesn't crash, where as the linux command line did after a short period of time, but it does.
This is no direct answer to your question, but it still might help you:
I often have to find bugs in code like yours (very long methods with "global" variables, that is, variables declared at the beginning of a method and used all over then). Just by refactoring the code properly (short methods with a single purpose each), the cause of the bug becomes immediately visible to me and is fixed within a second (while the refactoring itself takes much longer).
I guess that's what everyone trying to offer you help is doing anyway: Refactor your code (probably only in one's head) so that is (much) more easy to understand what's going on.
The solution I found was to use the java library for testing if a directory exists rather than doing it through the linux command line.
Ex:
File location = new File("directory");
if (location.exists())
{
}
No idea why it works and doesn't crash, where as the linux command line did after a short period of time, but it does.