Writing to a text file within a jar file - java

I was recently trying to export my game to a jar file, and I ran into a problem with converting files to input and output streams. With the regular code that was not exported, I was able to read and write to text files by simply calling the Scanner and PrintStream constructor with the File location. This didn't work inside the jar because apparently these were no longer considered as files. I was able to work around the input stream one by doing this:
Scanner infile = new Scanner(this.getClass().getResourceAsStream("Resources/leaderboard.txt"));
as opposed to,
Scanner infile = new Scanner("Resources/leaderboard.txt");
And I am trying to utilize PrintStream, but so far I have not found an equivalent function that will take in a String location and return an OutputStream for the PrintStream constructor. Should I use a different method for writing to text files in a jar, is there a function or method of converting it to an OutputStream that I have yet to see, or should I avoid printing to a text file altogether?
Thanks in advance.

You shouldn't and for practical purposes can't write to a "file" within a jar file. Yes, there are kludges that allow you to get around this, but they shouldn't be implemented. Instead all files that the program might change should be outside of the jar and should be separate files.

Related

Time-efficient way to append to existing header in existing CSV file in Java?

I'd like to modify the first line or header, of an existing csv file by adding a string to the end of that line.
I've tried using BufferedWriter to do so, but I can only get it to append at the end of the file.
My working code:
public static void writeStringtoCsvFile(String filePath, String input) throws IOException {
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(filePath, true)));
out.append(input);
out.close();
}
It seems OpenCsv doesnt have an available method to append to an existing file either. The file I need to process is at least 160mb or 1+mil records in size, would the alternative method:
BufferedReader to read all the lines
Append whatever is needed to first line
BufferedWriter to write everything to a new file
be too slow? Is there a more elegant solution to this? Thanks!
File systems do not allow you to insert bytes into or delete bytes from the middle of a file without rewriting all of the bytes after the insertion / deletion point.
Since the file system doesn't support it, the Java file I/O APIs can't support it.
Since the Java file I/O APIs don't support it, neither can the OpenCvs APIs. (Or at least not without rewriting the file under the covers.)
So, the answer is that there isn't a more efficient way than reading writing all of the lines of the file.
Notes:
While it is technically possible to do an in-place rewrite of a file, it is safer (and possibly more efficient) to create a new file, write to it and rename it when the writing is completed.
Reading and writing a line at a time (using BufferedReader / BufferedWriter) is better than reading all lines into memory at the same time, then writing them all out. Especially if the files are large.

Java: edit/remove a specific line (with streams) directly into the original file

This is my scenario: I have a huge .txt file (~16GB) that contains some lines that have to be removed (that can easily be found with a .contains()).
Obviously the idea of loading the whole file on RAM and explore it with a Scanner, then saving the results in a new .txt file is unfeasible (since I have 16GB of RAM).
I also know that with the streams I'm able to read the file line by line, avoiding the memory leak. What I don't know (and haven't been able to find) is wether it is possible to edit that specific line and put it back in its place into the file.
Otherwise, is it possible to just rewrite a new .txt file with just the "correct" lines in a similar way to the one that allows me to read line by line, so without loading the whole file in memory, since before or after it will become as huge as the original one?
Set up a Stream Reader that will be reading your file line by line, and a Stream writer that will be outputting to the new file. If the reader doesn't find the line to edit the writer simply writes that line to the new file. If the reader spots the line it wishes to edit, create a method to manipulate the line and return it, then have the Writer write that manipulated line rather than the original one.
You won't be allowed to access the same file with a Streamreader and Streamwriter.

appending mat file in java

I have a question about the com.jmatio.io package that I was hoping someone could answer. I am looking to write to a .mat file (using java) that may or may not already exist.
If it exists I would like to append the information to the end but if the file is not created I would like to create a new file and just add the contents to that.
My second write is overwriting the first but I would not like it to do this.
Any suggestions or solutions is gladly appreciated.
If you want to write multiple arrays to a new file you can achieve it using the MatFileIncrementalWriter. As it's explained in it's javadoc
An updated writer which allows adding variables incrementally for the life of the writer. This is necessary to allow large variables to be written without having to hold onto then longer than is necessary.
And it states clearly that you can't append to an existing file.
If you want to append to an existing file you might need
read variables from the existing file
write the existing variables back to the file using a MatFileIncrementalWriter
add new variables to the incremental writer
You need to write in append mode so the content get appended to the end to the file instead of overwriting.
File out = new File("out.mat");
try(FileWriter fw = new FileWriter(out, true); // true is for append
BufferedWriter bw = new BufferedWriter(fw)) {
// ...
}
If the file does not exist, it will be created.

Java Serialization save object in files

In java when serializing objects
FileOutputStream fileOut =
new FileOutputStream("src/employee.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(em);
out.close();
fileOut.close();
Can we use any kind of extensions .bin,.txtas output file. why .seris most prefereable?
.ser is a shorthand from Serializable and the common 3 letter file extension. You can use any other extension you like or no extension altogether. The file will be created with no problem. Test it. After you test it and demonstrate to yourself this is possible, I would recommend defining the proper extension for the generated files, or just keep using ser since it's common Serialized binary data for Java developers.
Imagine you use txt as extension rather than ser or a custom extension. Another non-developer user of the PC accidentally enters to the folder containing your binary data file with a txt extension (probably on a Windows or Mac environment and hardly but not impossible on Linux :) ) and opens it and see gibberish because, after all, is serialized data. This user may do nothing for seeing gibberish or may think the file is corrupted and deletes it. IMO this is why it would be better to use a non-common extension for your files containing binary data.
Note: you can open any file with almost any program despite its extension and see it choke for not recognizing the format or displaying gibberish, but that's outside of the question.

Why doesn't java.io.File have a close method?

While java.io.RandomAccessFile does have a close() method java.io.File doesn't. Why is that? Is the file closed automatically on finalization or something?
The javadoc of the File class describes the class as:
An abstract representation of file and directory pathnames.
File is only a representation of a pathname, with a few methods concerning the filesystem (like exists()) and directory handling but actual streaming input and output is done elsewhere. Streams can be opened and closed, files cannot.
(My personal opinion is that it's rather unfortunate that Sun then went on to create RandomAccessFile, causing much confusion with its inconsistent naming.)
java.io.File doesn't represent an open file, it represents a path in the filesystem. Therefore having close method on it doesn't make sense.
Actually, this class was misnamed by the library authors, it should be called something like Path.
Essentially random access file wraps input and output streams in order to manage the random access. You don't open and close a file, you open and close streams to a file.
A BufferedReader can be opened and closed but a File is never opened, it just represents a path in the filesystem.
Say suppose, you have
File f = new File("SomeFile");
f.length();
You need not close the Files, because its just the representation of a path.
You should always consider to close only reader/writers and in fact streams.
As already stated, the File class does not have a closing method as it's merely a path or a reference to the actual File.
You will usually use this File class as a helper to open the actual file with a FileReader class which you can close. That said, it does close itself on exit but if you read a file from your program and then try to do something to this file externally, it could result in an error on that external call, so it's better to close it
File path = new File(/some/path/file.txt);
FileReader actualFile = new FileReader(path);
...<
if(imDoneWithTheFile)
actualFile.close();

Categories