Managing file bytes with DataOutput/InputStream - java

I have a program that will go through and create multiple different class instances. I want to write the details of each instance to a file using DataOutputStream (it's a necessary exercise, I'll look at other ways of doing this later), but the problem is I noticed that DataOutputStream overwrites the file each time a new instance is created and written. My first idea was each time a new instance is written, first using DataInputStream to get what's in the file, save it, and then rewrite it with the new instance. This seems like it could get confusing very fast. What would be best practice for something like this? Thanks in advance.
EDIT: I will try and be a bit more specific about what I'm trying to do here.
When I take the class that I want to write to the file, first I'll use an dataInputStream.readFully to get everything in the file. My understanding is that takes all the bytes in the file and stores them in an array. I would like to compare this with the class instance and if the instance matches something already in the file, don't output this particular instance (because it's already there) to the file. Otherwise, append to the file.

Use the FileOutputStream(File file, boolean append) constructor when you open the file for writing. For example:
File f = new File("C:\data.txt");
FileOutputStream fos = new FileOutputStream(f, true); // open file for appending
DataOutputStream dos = new DataOutputStream(fos);
// anything written to dos after this point will be appended
If you just need to serialize your objects, I'd highly recommend using JAXB or another serialization/marshaling API instead of reinventing the wheel. You'll potentially save a ton of time.

Related

use BufferedWriter to write same data to multiple files

I'm interested in writing some data I'm receiving into two different files (same data).
In my code, I'm using BufferedWriter and FileWriter to write the data to files, and I want, as a backup, to write the same data on the local storage and on the SD card.
My question is if I need to implement this with 2 FileWriters and 2 BufferedWriters, or is there a way to use the same BufferedWriter for both files?
Is there a more efficient way to implement this task?
Reusing the same writer isn't possible - unless you spend the time to implement your own special subclass of Writer that writes its output into multiple files at the same point in time. (to then pass an instance of such a CopyingWriter to the ctor of BufferedWriter).
But I suggest to not do that. Instead: write the file once. Then use other, existing technology to copy the output file.
Always aim for simplicity. You intend to create a very special solution, where one writer writes to n files. But there is no need to do that. Write your file once, then copy it n times. This approach doesn't require "innovation" - you just need to use what already exists (see here for example).

Access the same file for read and write random position

Start by saying that I have not great experience in Java and I've done a lot of research. I would please ask you a specific question.
Thank you
I need to open a file for reading and writing from which I read and write a 512-byte blocks.
The file is fixed length and the information to be written will overlap with other existing.
For example, I read the first 512 bytes of the file and if it contains certain values write a block 512 to position 2048.
I tried using FileInputStream and FileOutputStream but every time I open with FileOutputStream the contents of the file are deleted.
It can be done with Java?
Roberto
Use a FileChannel; it allows random access to any part of a file, in read, write or any combination of both.
Example:
final Path path = Paths.get("path/to/the/file");
final FileChannel channel = FileChannel.open(path, relevantOptions);
Optionally, after that, you can use the .map() method.

Is there any reason not to use resource.getInputStream()?

Is it ever favorable to create a FileInputStream, like this:
InputStream fileInputStream = new FileInputStream(resource.getFile());
instead of using the InputStream created by the resource, like this:
InputStream resourceInputStream = resource.getInputStream();
The resource is an org.springframework.core.io.Resource.
A resource does not always come from a File. It may come from a network resource or be dynamically generated by the class loader. If you do that you may be fine 99% of the time, but you could have trouble in specific unexpected situations.
As a general rule it's better not to make assumptions about the concrete implementation of anything.
By using resource.getFile() your making the assumption that the resource comes from a file.
If all you need is the input stream, then there is no reason not to use it. The point of getFile is getting access to the file in ways other than opening a FileInputStream on it, such as reading attributes, moving, deleting, opening it through NIO instead of classic IO, etc.

How to append the contents to the file at the beginning using Java?

I have used Filewriter class. But it will append at the end of the file. Can anyone tell me the method to append the contents to the file at the beginning without overwriting.
You can't, basically. That's not a Java limitation so much as a file system limitation - I can't remember ever seeing an API which allows this.
You'll need to create a new file, write your new data, then append the contents of the original file to it.

How do I write/read to the beginning of a text file?

EDIT
This is my file reader, can I make this read it from bottom to up seeing how difficult it is to make it write from bottom to up.
BufferedReader mainChat = new BufferedReader(new FileReader("./messages/messages.txt"));
String str;
while ((str = mainChat.readLine()) != null)
{
System.out.println(str);
}
mainChat.close();
OR (old question)
How can I make it put the next String at the beginning of the file and then insert an new line(to shift the other lines down)?
FileWriter chatBuffer = new FileWriter("./messages/messages.txt",true);
BufferedWriter mainChat = new BufferedWriter(chatBuffer);
mainChat.write(message);
mainChat.newLine();
mainChat.flush();
mainChat.close();
Someone could correct me, but I'm pretty sure in most operating systems, there is no option but to read the whole file in, then write it back again.
I suppose the main reason is that, in most modern OSs, all files on the disc start at the beginning of a boundary. The problem is, you cannot tell the file allocation table that your file starts earlier than that point.
Therefore, all the later bytes in the file have to be rewritten. I don't know of any OS routines that do this in one step.
So, I would use a BufferedReader to store whole file into a Vector or StringBuffer, then write it all back with the prepended string first.
--
Edit
A way that would save memory for larger files, reading #Saury's randomaccessfile suggestion, would be:
file has N bytes to start with
we want to add on "hello world"
open the file for append
append 11 spaces
i=N
loop {
go back to byte i
read a byte
move to byte i+11
write that byte back
i--
} until i==0
then move to byte 0
write "hello world"
voila
Use FileUtils from Apache Common IO to simplify this if you can. However, it still needs to read the whole file in so it will be slow for large files.
List<String> newList = Arrays.asList("3");
File file = new File("./messages/messages.txt");
newList.addAll(FileUtils.readLines(file));
FileUtils.writeLines(file, newList);
FileUtils also have read/write methods that take care of encoding.
Use RandomAccessFile to read/write the file in reverse order. See following links for more details.
http://www.java2s.com/Code/Java/File-Input-Output/UseRandomAccessFiletoreverseafile.htm
http://download.oracle.com/javase/1.5.0/docs/api/java/io/RandomAccessFile.html
As was suggested here pre-pending to a file is rather difficult and is indeed linked to how files are stored on the hard drive. The operation is not naturally available from the OS so you will have to make it yourself and most obvious answers to this involve reading the whole file and writing it again. this may be fine for you but will incur important costs and could be a bottleneck for your application performance.
Appending would be the natural choice but this would, as far as I understand, make reading the file unnatural.
There are many ways you could tackle this depending on the specificities of your situation.
If writing this file is not time critical in your application and the file does not grow too big you could bite the bullet and read the whole file, prepend the information and write it again. apache's common-io's FileUtils will be of help here simpifying the operation where you can read the file as a list of strings, prepend the new lines to the list and write the list again.
If writing is time critical but have control over the reading or the file. That is, if the file is to be read by another of your programs. you could load the file in a list of lines and reverse the list. Again FileUtils from the common-io library and helper functions in the Collections class in the standard JDK should do the trick nicely.
If writing is time critical but the file is intended to be read through a normal text editor you could create a small class or program that would read the file and write it in another file with the preferred order.

Categories

Resources