Java FileWriter Windows Issues - java

I'm writing a Java program that prints information to a text file as it runs. When testing my program on my Mac in Eclipse, it works properly--both creating the text file and writing to it. I exported my program to a .jar file to test on different computers, and when I run the .jar file on other Mac computers, everything works as it should. However, when I run the program on a Windows computer, a file is created but nothing is written to it. I have searched for Filewriter issues on different operating systems, but haven't come up with anything so far--thoughts?
Below is the code I use to write to the file. It's within a timer task and writes an angle value and a time stamp to the file on each execution. Everything else within the timer task works properly on all operating systems, so that isn't the issue. If it helps, here is an example of a file might look like:
1 270
2 30
3 26
4 29
etc. with the first column containing the time count and the second column containing an angle value.
The code:
public AnAngleTimerTask(Model newModel, int newCounter, int newEndAnalysis,
int newSampleEvery) {
model = newModel;
counter = newCounter;
endAnalysis = newEndAnalysis;
sampleEvery = newSampleEvery;
angles = new int[(int) Math
.floor((endAnalysis - counter) / sampleEvery)];
times = new int[(int) Math.floor((endAnalysis - counter) / sampleEvery)];
file = newFile();
}
#Override
public void run() {
PrintWriter out;
System.out.println(counter);
// get angle and write to file
if (!model.getTimer().getPaused()) {
int usbAngle = retrieveAngle();
times[i] = counter;
angles[i] = usbAngle;
try {
out = new PrintWriter(new BufferedWriter(new FileWriter(file, true)));
out.printf("%-10d %-10d\n", counter, usbAngle);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
model.setAngle(usbAngle);
i++;
counter = counter + sampleEvery;
}
if (counter == endAnalysis) {
model.setMeanAngle(angles);
model.setR(angles);
System.out.println("End Analysis");
cancel();
}
}
public File newFile() {
String nameString;
Date myDate = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd:HH-mm-ss");
String myDateString = sdf.format(myDate);
if (model.getArenaName() == null) {
nameString = "Arena" + model.getName() + "Tracker";
} else {
nameString = model.getArenaName();
}
File file = new File(model.getPath() + "/" + nameString + "_"
+ model.getName() + "_" + myDateString + ".txt");
model.setLastDataRecordedToFile(file.getAbsolutePath());
return file;
}
Please let me know if you need any other information or code for context.

Is the file empty? Or is the output not as expected. Depending on that, changing from
out.printf("%-10d %-10d\n", counter, usbAngle);
to
out.printf("%-10d %-10d%n", counter, usbAngle);
might help. With the first one it sends a raw line feed. Second one does the platform specific conversion and generate a \r\n on windows

PrintWriter swallows exceptions, and you aren't calling checkError() to see if one happened. Try it with a BufferedWriter. You'll have to use something other than printf() of course.

After some trial and tribulation, I discovered that the issue was actually that I was using a file name with a colon in it (generated by the SimpleDateFormat), which is permitted on Macs but not on Windows. Got rid of the colon and everything works as it should!

Related

Editing a file using async threads in Java

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

How can I update contents of a text file

My assignment requires me to make a simple mathGame that generates random math problems. The program has to record the amount correct and the amount incorrect in a text file. It also has to update the statistics of an existing file instead of overwrite them.
This is how I am creating each file:
try {
writer = new FileWriter(userName + " Stats.txt", true);
outputfile = new PrintWriter (writer);
} catch (IOException e) {
}
Here is what is being written to the file:
public static void saveStats () {
outputfile.println();
outputfile.println("Correct Answers:"+ correct);
outputfile.println("Incorrect Answers:" + incorrect);
if (money > 0) {
outputfile.printf("Earnings: $%.2f", money);
outputfile.println();
}
else {
float moneyNegative = Math.abs(money);
outputfile.printf("Earnings: -$%.2f", moneyNegative);
outputfile.println();
}
outputfile.flush();
}
Here is a sample output of the text file after quitting the program:
Correct Answers:0
Incorrect Answers:1
Earnings: -$0.03
correct, incorrect, and money are all global variables and are initialized to 0. If I restart the program, my file will still exist but the values of Correct Answers, Incorrect Answers, and Earnings will be overwritten or a new entry to the file will be added. I just want to update it.
Here is all of my code: https://pastebin.com/1Cmg5Rt8
Have you tried getting the original text first, then writing it before you start writing what you need to?
Basically, you take the input from the file you have at the beginning
Scanner s = new Scanner(new File("FileName.txt"));
Then, you can loop through it and write to the file.
while(s.hasNextLine())
{
outputfile.println(s.nextLine());
}
After you have all of your previous file rewritten into the text, you can run the rest of your code and not have the information overwritten.
Also, instead of try-catch you can just throw IOException

Different output is produced as a result of Java program when executed from windows

I am running a Java program to compute all paths in a tree. When I run it form eclipse on windows as I see an output1, but when I run the same program from jar or Mac, I notice different output. There are lots of diffs. Even file sizes are different. Does buffer writer behave differently when depending on platform?
So, I have a same output when executed from the jar or executed on Mac Eclipse, but different output when executed from windows eclipse.
Here is the code thats writing to the file:
Member Variable:
public HashMap&ltString, HashSet&ltString>> nodeListFromFile = new HashMap&ltString, HashSet&ltString>>();
Funciton:
public void getAllPaths(String root, String path){
//Since we are assuming there are approximately 12-16 levels
//And we are expecting a LCA in less than 16 steps
//All paths evaluated are of max size of 16 using this counter
int stepCounter = 0;
File file = new File(outPutfilePath);
try{
if(!file.exists()){
file.createNewFile();
}
FileWriter fw = new FileWriter(file,true);
BufferedWriter bw = new BufferedWriter(fw);
//Iterate over each child node
for(String childNode: nodeListFromFile.get(root)){
String tempPath = path;
if((tempPath.indexOf(childNode) grandChildSet = nodeListFromFile.get(childNode);
boolean goodGrandChild = true;
for(String gc: grandChildSet){
if(!path.contains(gc))
goodGrandChild = false;
}
if(grandChildSet.size()==0 || goodGrandChild){
bw.write(tempPath+System.getProperty("line.separator"));
bw.flush();
}
}
}
//End iteration of children
}
catch (Exception e) {
// TODO: handle exception
}
finally{
}
}//End of function
You use line.separator, which is system dependent.
It is \r\n for Windows.
It is \r for Mac.
Also (bit related),
It is \n for OSX and Linux
So, you get different outputs.
Another solution to define the "separator" is by
File.separator
Example:
// Removing directories
int lastDirectory = fileName.lastIndexOf(File.separator);
fileName = fileName.substring(lastDirectory+1);

Java: checking if a file is present

Can somebody help me with this scenario?
I have a method which when run generates a number of files. The files can take anywhere from a couple of seconds to a minute to be generated so instead of just waiting for 2 minutes everytime I am trying to look at the number of files in the folder then check every second up to 2 minutes for the file count to go up.
If the file count doesn't go up in that 2 minutes I just want to carry on with the rest of the method instead of throwing an exception and exiting.
The problem is the first time it runs when it gets to new File(generatedFilesFolder).listFiles().length; it throws a null pointer exception because the generatedFilesFolder is empty at this point.
I could do this check after the generate.next() but then I would have to sleep which would defeat the point of what I am trying to archive.
Please can anyone tell me a better way? I tried changing the int to an Integer instead but it still threw an exception.
int actualFilesGenerated = new File(generatedFilesFolder).listFiles().length;
generate.next();
// / Now I want to give each file 2 minutes to generate otherwise catch and
// carry on with rest of method.
try {
int currentFilesGenerated = new File(generatedFilesFolder).listFiles().length;
int counter = 0;
while ((currentFilesGenerated < actualFilesGenerated) & counter < 120) {
Thread.sleep(1000);
currentFilesGenerated = new File(generatedFilesFolder).listFiles().length;
counter++;
System.out.println("actualFilesGenerated: " + actualFilesGenerated
+ " currentFilesGenerated: " + currentFilesGenerated + "counter: "
+ counter);
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
///rest of method here
You can use File.exists() to check the existence of a File
File f = new File(generatedFilesFolder)
if(f.exists()) {
// file exists and do the operation
}
else {
f.createNewFile(); //or f.mkdir() to create directory
}
The problem is the first time it runs when it gets to new File(generatedFilesFolder).listFiles().length; it throws a null pointer exception because the generatedFilesFolder is empty at this point.
This cannot be true. If generatedFilesFolder is effectively a path to a directory but there are no files in it, this will not throw an NPE but will return an empty array.
Therefore you need to generate your directory before going any further:
final File file = new File(generatedFilesFolder);
if (file.exists()) {
if (!file.isDirectory())
throw new IllegalStateException("not a directory");
} else {
if (!files.mkdirs())
throw new IllegalStateException("cannot create directory");
}
// go on
Finally: if you use Java 7, forget about File. Use Files. Which has a directory watcher...
you can use exists() method of File class to check if that file is present,
e.g.
File f=new File(path);
if(f.exists()) {
.....
}
there is exist method. So check if derectory exist before you get list of files
make a check before using it like.
File file = new File(generatedFilesFolder);
if(file.exists() && file.isDirectory()) {
// do something
}

Process Builder Incrementing Error

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.

Categories

Resources