I've created a file using java.io.File, FileInputStream & FileOutputStream. Suppose that I want to change the value of some bytes in the file (for instance from the byte 15 to 35) without changing the size of the file. I've tried creating a RandomAccessFile object and then use RandomAccessFile.seek to move to byte number 15, writing my new bytes and then closing the file. The file has changed its size. What's wrong with this approach, and how can this be done successfully?
Are you sure you are writing a byte to the RandomAccessFile? If you are calling the method:
file.write(35);
Then it is actually writing 35 as an int which is 4 bytes. If you want to write a single byte try:
file.writeByte(35);
Related
I am trying to read a .wav file, convert it into double array and FFT the array.
I have the recorded .wav file in storage but I have no idea how I can read the file and use the data.
I am a beginner in application development so it would be nice if you could lead me through step by step as well as show some sample code.
Appreciate your help.
I can't give you a full code since it's a long solution and I have other things to do. I can give you hints.
First, check this link as reference.
As you see, a .wav or a WAVE file does not only contain the audio samples but it also contains other metadata that describes the contents of the file. To correctly read the audio samples, you'll need the values of these metadata.
To do this, first instantiate a FileInputstream. You will need a File object representing your .wav file to do that.
Next, you'll need to read each field from top to bottom. As you see from the illustration, the number of bytes for each field is indicated. Use the following code when reading a field.
byte[] bytes = new byte[numOfBytes];
fileInputStream.read(bytes, 0, bytes.length);
// The value of current field is now stored in the bytes array
After each read, the fileInputStream will automatically point to the next field. Just repeat the above code until you have reached the start of the audio samples data.
To interpret the obtained values, you'll have to carefully read the description of each field.
To convert field from byte array to ASCII or String, use:
String value = new String(bytes);
To convert field from byte array to a number, use:
ByteBuffer buffer = ByteBuffer.allocate(numOfBytes);
buffer.order(BIG_ENDIAN); // Check the illustration. If it says little endian, use
// LITTLE_ENDIAN
buffer.put(bytes);
buffer.rewind();
If field consists of two bytes:
Short value = buffer.getShort();
If field consists of 4 bytes:
Int value = buffer.getInt();
To read the samples, just continue what you're doing above. But you'll also have to consider the number of bits per sample as given by the BitsPerSample field. For 8 bits, read 1 byte. For 16 bits, read 2 bytes, and so on and so forth. Just repeat to get each sample until you reach the end of file.
To check the end of file, get the returned value from read and check if it is -1:
int read = fileInputSream.read(bytes, 0, bytes.length);
// If read equals -1 then end of file
I'm looking to read an InputStream in sections because I need the first n bytes of the file and last m bytes as well as the contents between.
byte[] beginning = inputStream.readNBytes(16);
This works just fine, but to get the last m bytes, I tried the following:
byte[] middle = inputStream.readNBytes(inputStream.available() - 32);
byte[] end = inputStream.readNBytes(inputStream.available());
The end variable looks how I expect it to but not the middle variable, which ends up cutting out part of the stream.
I'm also a bit confused why the buf parameter size in the input stream doesn't seem to be equal to the byte array size when converting one to the other.
Anyway, I assume this isn't working how I want it to because (inputStream.available() - 32) is not adding up to a value compatible with readNBytes, so part of the stream is lost.
Is there a way to go about doing this?
EDIT: What I ended up doing which seemed to work(mostly) is when creating the file, to prepend both pieces I will later be extracting instead of prepending one and appending the other. That way I can just call inputStream.readAllBytes() on the last piece.
I also had to change where I'm writing to the file. I was writing to a CipherOutputStream when I should've been writing to the FileOutputStream and using that to create the Cipher OS.
Even after doing this I still have an extra 16 bytes at the end of the file, which confuses me, but I can easily ignore that last bit if I can't figure out why it's doing that.
I use java.io.RandomAccessFile to open a file and write few entries in the same at random locations. When I read the file back, is it guaranteed that unwritten bytes in that file (that may be in between two locations which were written earlier) are returned as 0?
I'm writing a program which takes in a byte array of potentially millions of bytes, reads each one from a ByteArrayInputStream, and if the byte is not "printable" (ascii 32-126), that byte is encoded in a certain way and written to a ByteArrayOutputStream instance; if the byte is "printable" it is directly written to that same ByteArrayOutputStream instance.
So from a broader view I am taking in a byte array, and getting back a similar byte array except certain characters have been encoded.
My question is: would it be faster to write my data out to a file or to continuously be writing to this OutputStream?
It will be faster to write the data to your output stream. Writing to a file will involve disk access, which is slower than access to the RAM where the byte array inside the ByteArrayOutputStream lives.
However, if you eventually want to write your byte array out to some other place (say a file) then the intermediate step of the ByteArrayOutputStream is unnecessary and you should just write straight to the end destination e.g. FileOutputStream.
So - I've got a third party library that needs a File as input. I've got a byte array.
I don't want to write the bytes to disk .. I'd like to keep this in memory. Any idea on how I can create a File from the provided byte array (without writing to disk)?
Sorry, not possible. A File is inherently an on-disk entity, unless you have a RAM disk - but that's not something you can create in Java.
That's exactly the reason why APIs should not be based on File objects (or be overloaded to accept an InputStream).
There's one possibility, but it's a real long-shot.
If the API uses new FileReader(file) or new FileInputStream(file) then you're hosed, but...
If it converts the file to a URL or URI (using toURL() or toURI()) then, since File is not final, you can pass in a subclass of File in which you control the construction of the URL/URI and, more importantly, the handler.
But the chances are VERY slim!
So I see there is an accepted answer (and this is old), but I found a way to do this. I was using the IDOL On Demand API and needed to convert a byte array to a File.
Here is an example of taking a byte array of an image and turning into a File:
//imageByte is the byte array that is already defined
BufferedImage image = null;
ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
image = ImageIO.read(bis);
bis.close();
// write the image to a file
File outputfile = new File("image.png");
ImageIO.write(image, "png", outputfile);
And so outputfile is a File that can be used later in your program.