8

I want to read bytes from a wave file into an array. Since the number of bytes read depends upon the size of the wave file, I'm creating a byte array with a maximum size of 1000000. But this is resulting in empty values at the end of the array. So, I wanted to create a dynamically increasing array and I found that ArrayList is the solution. But the read() function of the AudioInputStream class reads bytes only into a byte array! How do I pass the values into an ArrayList instead?

1
  • What's the next steps you want to do with that byte array? Maybe you don't even need that big temporary buffer. Commented Jun 14, 2011 at 8:57

3 Answers 3

37

ArrayList isn't the solution, ByteArrayOutputStream is the solution. Create a ByteArrayOutputStream write your bytes to it, and then invoke toByteArray() to get the bytes.

Example of what your code should look like:

in = new BufferedInputStream(inputStream, 1024*32);
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] dataBuffer = new byte[1024 * 16];
int size = 0;
while ((size = in.read(dataBuffer)) != -1) {
    out.write(dataBuffer, 0, size);
}
byte[] bytes = out.toByteArray();
Sign up to request clarification or add additional context in comments.

1 Comment

This is by far the best and in fact the only actually correct answer that does not read bytes one by one, but for whatever reason it is showing at the bottom of the page for me...
18

You can have an array of byte like:

List<Byte> arrays = new ArrayList<Byte>();

To convert it back to arrays

Byte[] soundBytes = arrays.toArray(new Byte[arrays.size()]);

(Then, you will have to write a converter to transform Byte[] to byte[]).

EDIT: You are using List<Byte> wrong, I'll just show you how to read AudioInputStream simply with ByteArrayOutputStream.

AudioInputStream ais = ....;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int read;

while((read = ais.read()) != -1) {
    baos.write(read);
}

byte[] soundBytes = baos.toByteArray();

PS An IOException is thrown if frameSize is not equal to 1. Hence use a byte buffer to read data, like so:

AudioInputStream ais = ....;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead = 0;

while((bytesRead = ais.read(buffer)) != -1) {
    baos.write(buffer, 0, bytesRead);
}

byte[] soundBytes = baos.toByteArray();

6 Comments

*****.java:41: cannot find symbol symbol : method read(java.util.List<java.lang.Byte>) location: class javax.sound.sampled.AudioInputStream ais.read(buffer);
This doesn't compile: there's no automatic/built-in way to convert a List<Byte> to a byte[]. Apart from that, using a List<Byte> is terribly space-inefficient.
@Joachim Sauer, you're right, I forgot that there needs to be a conversion from Byte to byte. Modifying answer.
I guess I have a new problem now. It is saying 'Cannot read a single byte if the frame size is more than one byte' . I've used getFrameSize() of the Audioformat class and it is returning '4'. So I guess that means the current frame size is four bytes.
I didnt get this error before because I read all the bytes at once into the array. Not one by one using the while loop
|
4

Something like this should do:

List<Byte> myBytes = new ArrayList<Byte>();

//assuming your javax.sound.sampled.AudioInputStream is called ais

while(true) {
  Byte b = ais.read();
  if (b != -1) { //read() returns -1 when the end of the stream is reached
    myBytes.add(b);
  } else {
    break;
  }
}

Sorry if the code is a bit wrong. I haven't done Java for a while.

Also, be careful if you do implement it as a while(true) loop :)

Edit: And here's an alternative way of doing it that reads more bytes each time:

int arrayLength = 1024;
List<Byte> myBytes = new ArrayList<Byte>();

while(true) {

  Byte[] aBytes = new Byte[arrayLength];
  int length = ais.read(aBytes); //length is the number of bytes read

  if (length == -1) {  //read() returns -1 when the end of the stream is reached
    break; //or return if you implement this as a method
  } else if (length == arrayLength) {  //Array is full
    myBytes.addAll(aBytes);
  } else {  //Array has been filled up to length

    for (int i = 0; i < length; i++) {
      myBytes.add(aBytes[i]);
    }
  }
}

Note that both read() methods throw an IOException - handling this is left as an exercise for the reader!

4 Comments

He shouldn't use a List of Byte, and reading byte by byte is very slow.
He wants a List rather than an array. Also, I've provided an alternative example for reading in chunks.
he want's a List because he doesn't know the size up-front. This is the correct solution, even 'though it doesn't use a List.
He wanted a list because he didn't know of better solutions. He wanted to have a byte[] in the end, and didn't care about intermediate steps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.