The first time I save a file, even if it exists, I get the result I want. The file is overwritten. Now If I save again the text is appended to the file instead of overwriting. I have tried applying the approaches from similar questions I found answered here but none solve this. This is not answered by the possible duplicate. When I save a file the first time the behavior is what I want, the file is overwritten. However, all subsequent saves with the java window open append. That is incorrect. I suspect the file may not be closing after writing.
Edits:
This is a javafx package so the minimal amount of code to run is going to be a bit long but here it goes.
MainController:
public class MainController{
/** Holder of a switchable vista. */
#FXML public StackPane vistaHolder;
#FXML
public void programExit(){System.exit(0);}
public void permutationAnalyzer(){VistaNavigator.loadVista(VistaNavigator.VISTA_3);}
#FXML
public void saveFile() throws IOException {
OptionsDataCollector.generateOptionsFile();
}
public void setVista(Node node) {
vistaHolder.getChildren().setAll(node);
}
}
The data being saved:
public class OptionsDataCollector{
public static void generateOptionsFile() throws IOException {
StringBuilder moduleData = new StringBuilder();
moduleData.append("--target_perm_group_size\t").append(targetGroupSize).append("\n");
moduleData.append("--prog_check\t").append(progCheck).append("\n");
FileSaveUtility.fileSaveWindow(moduleData.toString());
//The next line is the answer.
moduleData.setLength(0);
}
}
FileSave:
public class FileSaveUtility {
private static void saveFile(String content, File file) throws IOException {
FileWriter fileWriter = new FileWriter(file.getAbsoluteFile(), false);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write(content);
bufferedWriter.close();
//fileWriter.write(content);
//fileWriter.close();
}
public static void fileSaveWindow(String outFileData) throws IOException {
Stage primaryStage = new Stage();
FileChooser fileChooser = new FileChooser();
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("TXT files (*.txt)", "*.txt");
fileChooser.getExtensionFilters().add(extFilter);
fileChooser.setInitialFileName("run_Volundr.txt");
File file = fileChooser.showSaveDialog(primaryStage);
if(file != null){
saveFile(outFileData, file);
//primaryStage.close();
}
}
}
I have not included the FXML files or the MainApp that generates it. I can add them if anyone wants. I have tried closing the stage, using StandardOpenOptions.Truncate_Exsisting and Files.deleteIfExsists. There is an object or stream not closing somewhere.
Related
I would expect exception to be thrown in this code at line: charSink.write("hi world"); since the file is set to be non writable. But this code executes without any exceptions. How to make CharSink respect file permissions?
public class CharSinkWritingNonWritableFile {
public static void main(String[] args) throws Exception {
final File file = getNewFile();
file.setWritable(false, false);
val charSink = Files.asCharSink(file, Charsets.UTF_8, FileWriteMode.APPEND);
file.setWritable(false, false);
charSink.write("hi world");
Files.readLines(file, Charsets.UTF_8).forEach(line -> {
System.out.println(line);
});
}
private static File getNewFile() {
final File file = new File("/tmp/hi-world");
if (file.exists()) {
file.delete();
}
return file;
}
}
Edit:
OS: MacOS 12.4
so I was reading Java tutorials on this website: http://www.java2s.com/Tutorials/Java/JavaFX/0555__JavaFX_FileChooser.htm
and this code:
FileChooser fileChooser1 = new FileChooser();
fileChooser1.setTitle("Save Image");
System.out.println(pic.getId());
File file = fileChooser1.showSaveDialog(stage);
System.out.println(file);
was for saving files. But this code doens't work at all on my Eclipse (and I use Mac), I have no idea what pic.getId() is supposed to do. I googled everywhere and couldn't get the answer.
The System.out.println(pic.getId()); is doesn't matter. Since it is only a debug information. So you can comment this line. And you want the codes work, you should follow this example which can be found in the tutorial.
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(final Stage primaryStage) {
FileChooser fileChooser1 = new FileChooser();
fileChooser1.setTitle("Save Image");
//System.out.println(pic.getId());
File file = fileChooser1.showSaveDialog(primaryState);
System.out.println(file);
}
}
I am new to Java. I am sorry if this is a stupid question. I'd like to hand in a parameter that can either be a File or a string that I can then use to create a File. This is what I have so far:
public class DefaultOptions {
public File setChooser(JFileChooser chooser, dir) {
}
}
DefaultOptions dOptions = new DefaultOptions() {
public File setChooser(chooser, dir) {
if (!(dir instanceof java.io.File)) {
String ds = dir.toString();
File wd = new File(ds);
} else {
wd = (File) dir;
}
chooser.setCurrentDirectory(wd);
}
}
What signature can I use for this line:
public File setChooser(JFileChooser chooser, dir)
If there is no way to do this, how can I simplify this?
Use Object:
public File setChooser(JFileChooser chooser, Object dir) {
// ...
}
However, as pointed out in the comments, method overloading would probably definitely be better:
public File setChooser(JFileChooser chooser, String dir) {
// handle String case
}
public File setChooser(JFileChooser chooser, File dir) {
// handle File case
}
Here are the two java classes:
package je3.io;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* Created by IDEA on 31/01/15.
*/
public class DirWalker {
private List<File> recursiveList = new ArrayList<File>();
public void walkDir(String pathname) {
File d = new File(pathname);
recursiveList.add(d);
if(d.isDirectory()) {
for(String f : d.list()) {
walkDir(f);
}
}
}
public void reset() {
recursiveList.clear();
}
public List<File> getRecursiveList() {
return recursiveList;
}
public static void main(String[] args) {
DirWalker dirWalker = new DirWalker();
dirWalker.walkDir("/tmp");
dirWalker.getRecursiveList().forEach(System.out::println);
}
}
package je3.io;
import java.io.File;
/**
* Created by IDEA on 31/01/15.
*/
public class DirSummariser {
private DirWalker dirWalker = new DirWalker();
private long dirSize = 0;
public DirSummariser(String pathname) {
dirWalker.reset();
dirWalker.walkDir(pathname);
}
public DirSummariser(File file) {
this(file.getAbsolutePath());
}
public long calculateDirSize() {
for(File f : dirWalker.getRecursiveList()) {
dirSize += f.length();
}
return dirSize;
}
public static void main(String[] args) {
DirSummariser dirSummariser = new DirSummariser("/Users/hualin/Downloads/pdf");
System.out.println(dirSummariser.calculateDirSize());
}
}
In the main method of the second class, I was trying to calculate the total size of the pdf folder, which should be around 30MB. The java program compiles without error, but says the size of the folder is only 1600 bytes.
The problem is in DirWalker:
public void walkDir(String pathname) {
File d = new File(pathname);
recursiveList.add(d);
if(d.isDirectory()) {
for(String f : d.list()) { // <-- here
walkDir(f); // <--
}
}
}
The strings returned by d.list() are just the file names, without a path attached to them. If you find, for example, a file some_directory/foo.txt, the string you'll pull out of the list is foo.txt, and since foo.txt is not in the current working directory, the File object you construct from it will be invalid (or describe a different file).
You'll have to make the path you're trying to inspect part of the recursion to make this work properly, for example like this:
walkDir(pathname + File.separator + f);
Or, as #Adam mentions in the comments, by passing the File object that describes the parent directory into the recursion and using the File(parent, child) constructor, as in
// new parameter here: parent directory
public void walkDir(String pathname, File parent) {
System.out.println(pathname);
File d = new File(parent, pathname); // <-- File constructor with parent
recursiveList.add(d);
if(d.isDirectory()) {
for(String f : d.list()) {
walkDir(f, d); // passing parent here
}
}
}
// entry point, to keep old interface.
public void walkDir(String pathname) {
walkDir(pathname, null);
}
Note: This answer, I think this should be mentioned, is rather tailored to OP's use case of an exercise, so I mainly tried to explain why his code didn't work and suggested ways to make it work. If you're a stray visitor in the future and looking for ways to walk through a directory with Java, look at #fge's answer for a better way.
Use the java.nio.file API, it's much better at doing things like this.
Here is an example, also using throwing-lambdas, calculating the total size of all files in a directory, recursively:
final Path theDirectory = Paths.get("path/to/your/directory");
final long totalSize = Files.walk(theDirectory)
.filter(Files::isRegularFile)
.mapToLong(Functions.rethrow(Files::size))
.sum();
If you don't have Java 8, use Files.walkFileTree().
I'm trying to write a test for a Mule flow that will involve dropping a file in a location, waiting for it to be processed by my flow and compare the output to see if it has been transformed correctly. My flow looks as follows:
<flow name="mainFlow" processingStrategy="synchronous">
<file:inbound-endpoint name="fileIn" path="${inboundPath}">
<file:filename-regex-filter pattern="myFile.csv" caseSensitive="true"/>
</file:inbound-endpoint>
...
<file:outbound-endpoint path="${outboundPath}" outputPattern="out.csv"/>
</flow>
Is there a way I can access the inboundPath and outboundPath Mule properties inside of my test class so that I can drop files and wait for output in the correct places?
The test class I'm using is:
public class MappingTest extends BaseFileToFileFunctionalTest {
#Override
protected String getConfigResources() {
return "mappingtest.xml";
}
#Test
public void testMapping() throws Exception {
dropInputFileIntoPlace("myFile.csv");
waitForOutputFile("out.csv", 100);
assertEquals(getExpectedOutputFile("expected-out.csv"), getActualOutputFile("out.csv"));
}
}
Which extends this class:
public abstract class BaseFileToFileFunctionalTest extends FunctionalTestCase {
private static final File INPUT_DIR = new File("/tmp/muletest/input");
private static final File OUTPUT_DIR = new File("/tmp/muletest/output");
private static final Charset CHARSET = Charsets.UTF_8;
#Before
public void setup() {
new File("/tmp/muletest/input").mkdirs();
new File("/tmp/muletest/output").mkdirs();
empty(INPUT_DIR);
empty(OUTPUT_DIR);
}
private void empty(File inputDir) {
for (File file : inputDir.listFiles()) {
file.delete();
}
}
protected File waitForOutputFile(String expectedFileName, int retryAttempts) throws InterruptedException {
boolean polling = true;
int attemptsRemaining = retryAttempts;
File outputFile = new File(OUTPUT_DIR, expectedFileName);
while (polling) {
Thread.sleep(100L);
if (outputFile.exists()) {
polling = false;
}
if (attemptsRemaining == 0) {
VisibleAssertions.fail("Output file did not appear within expected time");
}
attemptsRemaining--;
}
outputFile.deleteOnExit();
return outputFile;
}
protected void dropInputFileIntoPlace(String inputFileResourceName) throws IOException {
File inputFile = new File(INPUT_DIR, inputFileResourceName);
Files.copy(Resources.newInputStreamSupplier(Resources.getResource(inputFileResourceName)), inputFile);
inputFile.deleteOnExit();
}
protected String getActualOutputFile(String outputFileName) throws IOException {
File outputFile = new File(OUTPUT_DIR, outputFileName);
return Files.toString(outputFile, CHARSET);
}
protected String getExpectedOutputFile(String resourceName) throws IOException {
return Resources.toString(Resources.getResource(resourceName), CHARSET);
}
}
As you can see I'm currently creating temporary input/output directories. I'd like to make this part read from the Mule properties if possible? Thanks in advance.
After observing your test classes and code I could see that you want to dynamically create temp folders place files in them. And the flow should read the files from Temp Directory and write output to another Temp directory. Point to be noted is that Mule's Endpoints are created when the configuration is loaded. So the ${inbound} and ${outbound} should be provided to the mule flow by the time they are provided.
So one option can be to create a dummy flow pointing to the temp folders for testing.
or
Create a test properties file pointing to the temp folders and load that to your flow config, so that your flow endpoints will get the temp folder paths.
In any way path cannot be provided to the flow inbound endpoints after they have been created(on config load).
Update1:
As per your comment the solution with option would be like the following.
Seperate the properties loading part of the config into another config.
Like "mapping-core-config.xml,mappingtest.xml" where the mapping-core-config will have the tags to load the properties file.
Now create a test config file for the mapping-core-config.xml file which loads the test properties file. This should be used in your test config. This way without modifying or disturbing your main code, you can test your flows pointing to temp folders.
"mapping-core-test-config.xml,mappingtest.xml"
Note: The test config can reside in the src/test/resources folders.
Hope this helps.