4

before you say "Google it", I tried, found a few interesting articles, but nothing worked.

I need to convert a mp3 file from a website to a byte stream, that I can later save into a file locally.

Here is my code (most important parts):

Url url = new Url("someUrl");
URLConnection conn = url.openConnection();
byte[] result = inputStreamToByteArray(conn.getInputStream());
// .... some code here
byteArrayToFile(result, "tmp.mp3");

public byte[] inputStreamToByteArray(InputStream inStream){
    InputStreamReader in = new InputStreamReader(inStream):
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    int next = inStream.read();
    while (next > -1){
        baos.write(next);
        next = in.read();
    }

    byte[] result = baos.toByteArray();
    baos.flush();
    in.close();
    return result;
} 

public void byteArrayToFile(byte[] byteArray, String outFilePath){
    FileOutputStream fos = new FileOutputStream(outFilePath);
    fos.write(byteArray);
    fos.close()
}

The code compiles without errors. Connection to the url is valid. It sends the right response.

The problem is somewhere in the conversion. I also get the new file on disk, after byteArrayToFile(), with appropriate lenght, but I can't play it in any player. It says length 00:00 and will not play.

Btw. I'd like to avoid any 3rd party libs. But if nothing else works...

1 Answer 1

13

(The code you've presented wouldn't compile without errors, by the way. You haven't got required exception handling, and inputStream should be InputStream, just for starters.)

This is the problem:

InputStreamReader in = new InputStreamReader(inStream):

You're trying to read from a binary stream, and convert it into text. It isn't text. You shouldn't be using anything to do with "Reader" or "Writer" for binary data like an MP3 file.

Here's what your inputStreamToByteArray method should look like (or use Guava and its ByteStreams.toByteArray method):

public byte[] inputStreamToByteArray(InputStream inStream) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] buffer = new byte[8192];
    int bytesRead;
    while ((bytesRead = inStream.read(buffer)) > 0) {
        baos.write(buffer, 0, bytesRead);
    }
    return baos.toByteArray();
}

Note that I've left it for the caller to clean up the input stream. Typically whoever fetches the stream also closes it - it would be slightly odd for a method like this to close it itself, IMO. You could do so if you wanted to, but probably in a finally block so you'd know that it would always be closed even if an exception was thrown.

Note that your "writing" code later on won't close the file if there's an exception, either. You should get in the habit of always closing streams in finally blocks.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks a lot. Yes I have exception handling, just didn't write it in code in my post. Btw. anyway to get a dynamic sized buffer? For instance if I use a list and convert it to array on return?
@ZolaKt: You've got a dynamically sized buffer: the ByteArrayOutputStream. The 8K buffer is just there as very temporary storage. Why would you want that to by dynamically sized?
I don't know. I just don't like any "hard-coded" numbers :) But you are right, this is the way to go. Thank you very much.
@ZolaKt: Feel free to make it a constant somewhere, or even put it as a parameter. I suspect 8K is fine for almost all purposes though...
@Jon Skeet: One more thing...how do I reference the stream in the finally block. In my example I get it from the connection object. In your approach I have to create a new instance of the stream first, right?
|

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.