That's not how it works. a java.io.File object is a light wrapper: Check out the source code - it's got a String field that contains the path and that is all it has aside from some bookkeeping stuff.
It is not possible to represent arbitrary data with a java.io.File object. j.i.File objects represent literal files on disk and are not capable of representing anything else.
Files.readAllBytes gets you the contents from the bytes, that's.. why the method has that name.
The usual solution is that a method in some library that takes a File is overloaded; there will also be a method that takes a byte[], or, if that isn't around, a method that takes an InputStream (you can make an IS from a byte[] easily: new ByteArrayInputStream(byteArr) will do the job).
If the API you are using doesn't contain any such methods, it's a bad API and you should either find something else, or grit your teeth and accept that you're using a bad API, with all the workarounds that this implies, including having to save bytes to disk just to satisfy the asinine API.
But look first; I bet there is a byte[] and/or InputStream variant (or possibly URL or ByteBuffer or ByteStream or a few other more exotic variants).
Use Apache Commons IO
FileUtils.writeByteArrayToFile(new File("pathname"), myByteArray)
Or, if you insist on making work for yourself...
try (FileOutputStream fos = new FileOutputStream("pathname")) {
fos.write(myByteArray);
//fos.close(); There is no more need for this line since you had created the instance of "fos" inside the try. And this will automatically close the OutputStream
}
Without any libraries:
try (FileOutputStream stream = new FileOutputStream(path)) {
stream.write(bytes);
}
With Google Guava:
Files.write(bytes, new File(path));
With Apache Commons:
FileUtils.writeByteArrayToFile(new File(path), bytes);
All of these strategies require that you catch an IOException at some point too.
Videos
You're opening a new FileOutputStream on each iteration of the loop. Don't do that. Open it outside the loop, then loop and write as you are doing, then close at the end of the loop. (If you use a try-with-resources statement with your while loop inside it, that'll be fine.)
That's only part of the problem though - you're also doing everything else on each iteration of the loop, including checking for headers. That's going to be a real problem if the byte array you read contains part of the set of headers, or indeed part of the header separator.
Additionally, as noted by EJP, you're ignoring the return value of read apart from using it to tell whether or not you're done. You should always use the return value of read to know how much of the byte array is actually usable data.
Fundamentally, you either need to read the whole response into a byte array to start with - which is easy to do, but potentially inefficient in memory - or accept the fact that you're dealing with a stream, and write more complex code to detect the end of the headers.
Better though, IMO, would be to use an HTTP library which already understands all this header processing, so that you don't need to do it yourself. Unless you're writing a low-level HTTP library yourself, you shouldn't be dealing with low-level HTTP details, you should rely on a good library.
Open the file ahead of the loop.
NB you need to store the result of read() in a variable, and pass that variable to new String() as the length. Otherwise you are converting junk in the buffer beyond what was actually read.
File tempFile = File.createTempFile(prefix, suffix, null);
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(byteArray);
Check out related docs:
File.createTempFile(prefix, suffix, directory);
Reading All Bytes or Lines from a File
Path file = ...;
byte[] fileArray;
fileArray = Files.readAllBytes(file);
Writing All Bytes or Lines to a File
Path file = ...;
byte[] buf = ...;
Files.write(file, buf);
A File object doesn't contain the content of the file. It is only a pointer to the file on your hard drive (or other storage medium, like an SSD, USB drive, network share). So I think what you want is writing it to the hard drive.
You have to write the file using some classes in the Java API
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(yourFile));
bos.write(fileBytes);
bos.flush();
bos.close();
You can also use a Writer instead of an OutputStream. Using a writer will allow you to write text (String, char[]).
BufferedWriter bw = new BufferedWriter(new FileWriter(yourFile));
Since you said you wanted to keep everything in memory and don't want to write anything, you might try to use ByteArrayInputStream. This simulates an InputStream, which you can pass to the most of the classes.
ByteArrayInputStream bais = new ByteArrayInputStream(yourBytes);
public void writeToFile(byte[] data, String fileName) throws IOException{
FileOutputStream out = new FileOutputStream(fileName);
out.write(data);
out.close();
}
Writing the file byte by byte will incur the overhead of a system call for every single byte.
Fortunately, there's an overload of write that takes an entire byte[] and writes it out with far fewer system calls:
try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile)) {
fileOutputStream.write(responseBytes);
}
In your current code, you're writing to the file using a loop:
for (int ii=0; ii<responseBytes.length; ii++) {
fileOutputStream.write(responseBytes, ii, 1);
}
This will write one byte at a time to the file output stream. Each call to fileOutputStream.write() incurs overhead because of method invocation and possibly disk I/O operations. Instead of writing one byte at a time, you can write the entire byte array in a single call:
// Write the entire byte array at once - much faster
try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile){
fileOutputStream.write(responseBytes);
}
However, for even better performance, wrap your FileOutputStream in a BufferedOutputStream as follows:
import java.io.BufferedOutputStream;
// ...
try (BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(outputFile))) {
bufferedOutputStream.write(responseBytes);
}
Finally, I think that you have to go even beyond that and try not to read the entire file into memory, which can cause high memory consumption. you can directly stream the object into file skipping load it into memory.. Here How you can stream it directly into files skipping memory:
// Get the response input stream from S3
ResponseInputStream<GetObjectResponse> s3InputStream = s3Client.getObject(request);
// Define the path to the output file
File outputFile = new File(downloadPath);
try (InputStream inputStream = s3InputStream;
OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile))) {
byte[] buffer = new byte[8192]; // Buffer size can be adjusted
int bytesRead;
// Read and write in chunks
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
// Handle exceptions appropriately
}
You can read images directly from byte streams with the ImageIO class. Assuming of course that you have previously written the image data in a compatible format. Which is hard to say given the fact that in your code you use an intermediary object input stream when reading your byte data. Here's an example of how you can create an image directly from the database without using intermediary files:
bais = new ByteArrayInputStream(resultSet.getBytes("image"));
final BufferedImage image = ImageIO.read(bais);
// pass the image to your Swing layer to be rendered.
And an example of how you would have written the data to the database, in order to be able to use this code:
final ByteArrayOutputStream baos = new ByteArrayOutputStream(64000);
ImageIO.write(image, "PNG", baos);
final byte[] data = baos.toByteArray();
// write data to database
The answer to your question is its platform dependent. From the docs
A file output stream is an output stream for writing data to a File or to a FileDescriptor. Whether or not a file is available or may be created depends upon the underlying platform. Some platforms, in particular, allow a file to be opened for writing by only one FileOutputStream (or other file-writing object) at a time. In such situations the constructors in this class will fail if the file involved is already open.
FileOutputStream is meant for writing streams of raw bytes such as image data. For writing streams of characters, consider using FileWriter.
So if you want to write to a file then file may or may not be created.
If you don't want to create the file and you are just interested in byte[] (content of the file) you can then use solution provided by @Perception or can just pass the inputStream that you have already created.