I have a FileInputStream created using Context.openFileInput(). I now want to convert the file into a byte array.
Unfortunately, I can't determine the size of the byte array required for FileInputStream.read(byte[]). The available() method doesn't work, and I can't create a File to check it's length using the specific pathname, probably because the path is inaccessible to non-root users.
I read about ByteArrayOutputStream, and it seems to dynamically adjust the byte array size to fit, but I can't get how to read from the FileInputStream to write to the ByteArrayOutputStream.
This should work.
InputStream is = Context.openFileInput(someFileName);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
while ((int bytesRead = is.read(b)) != -1) {
bos.write(b, 0, bytesRead);
}
byte[] bytes = bos.toByteArray();
This is the easiest way
FileInputStream fis = openFileInput(fileName);
byte[] buffer = new byte[(int) fis.getChannel().size()];
fis.read(buffer);
You can pre-allocate the byte array using
int size = context.getFileStreamPath(filename).length();
This way, you will avoid allocating memory chunks every time your ByteArrayOutputStream fills up.
For the method to work on any device and aplication you just need to replace:
InputStream is = Context.getContentResolver().openInputStream(yourFileURi);
This way you can encode external files as well.
Related
There were few similar topics on stackoverflow but none of them seemed good enough for me. The problem is i have such a snippet of code:
// AudioInputStream in;
final int BUFFER_SIZE = 8192;
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byte[] byteBuffer = new byte[BUFFER_SIZE];
int bytesRead = 0;
while ((bytesRead = in.read(byteBuffer, 0, BUFFER_SIZE)) != -1) {
byteStream.write(byteBuffer, 0, bytesRead);
}
byte[] audioData = byteStream.toByteArray();
This code reads data of mp3 file and saves it to byte array, but takes about 10 seconds. Is there any possibility to store whole mp3 data into buffer in shorter time?
I've tried to avoid passing the size of buffer or extend it but that caused additional problems (e.g. file was not read correctly).
Thanks in advance
You are copying data 3 times, you can avoid that by first checking the file size, allocating a byte array big enough, and reading into that directly.
It also helps a little bit to pre-allocate space in the ByteArrayOutputStream so it doesn't have to be increased in size many times.
If you can't get the file size up front, you can allocate a new byte[] for every block, and put them in a list, until you got them all. Then allocate the final array and copy all of them into the last array. IF you need a byte[] in the end. If you don't, there may be more efficient ways to proceed.
I want to use java(httpurlconnection class) to download a pdf file,but have some thing puzzle,the core code is:
BufferedInputStream inputStream = new BufferedInputStream(httpConn.getInputStream());
OutputStream output = new FileOutputStream("F:/httpclient-tutorial.pdf");
byte[] infoBytes = new byte[BUFFER];
while(inputStream.read(infoBytes) != -1){
output.write(infoBytes, 0, BUFFER);
}
Question:when the BUFFER is 1024,get the pdf file is larger than real one;but the BUFFER is 8,then it's ok. I don't know why it is? Has anyone know about that?
You're unconditionally writing out the whole of the buffer on each iteration. You should only write out as many bytes as you've just read:
int bytesRead;
while((bytesRead = inputStream.read(infoBytes)) != -1){
output.write(infoBytes, 0, bytesRead);
}
I am trying to use the following Java code to compress and uncompress a String. But the line that creates a new GZipInputStream object out of a new ByteArrayInputStream object throws a "java.util.zip.ZipException: Not in GZIP format" exception. Does anyone know how to solve this?
String orig = ".............";
// compress it
ByteArrayOutputStream baostream = new ByteArrayOutputStream();
OutputStream outStream = new GZIPOutputStream(baostream);
outStream.write(orig.getBytes());
outStream.close();
String compressedStr = baostream.toString();
// uncompress it
InputStream inStream = new GZIPInputStream(new ByteArrayInputStream(compressedStr.getBytes()));
ByteArrayOutputStream baoStream2 = new ByteArrayOutputStream();
byte[] buffer = new byte[8192];
int len;
while((len = inStream.read(buffer))>0)
baoStream2.write(buffer, 0, len);
String uncompressedStr = baoStream2.toString();
Mixing String and byte[]; that does never fit. And only works on the the same OS with same encoding. Not every byte[] can be converted to a String, and the conversion back could give other bytes.
The compressedBytes need not represent a String.
Explicitly set the encoding in getBytes and new String.
String orig = ".............";
// Compress it
ByteArrayOutputStream baostream = new ByteArrayOutputStream();
OutputStream outStream = new GZIPOutputStream(baostream);
outStream.write(orig.getBytes("UTF-8"));
outStream.close();
byte[] compressedBytes = baostream.toByteArray(); // toString not always possible
// Uncompress it
InputStream inStream = new GZIPInputStream(
new ByteArrayInputStream(compressedBytes));
ByteArrayOutputStream baoStream2 = new ByteArrayOutputStream();
byte[] buffer = new byte[8192];
int len;
while ((len = inStream.read(buffer)) > 0) {
baoStream2.write(buffer, 0, len);
}
String uncompressedStr = baoStream2.toString("UTF-8");
System.out.println("orig: " + orig);
System.out.println("unc: " + uncompressedStr);
Joop seems to have the solution up there, but I feel I must add this:
Compression in general, and GZIP in particular will produce a binary stream.
You MUST not try to construct a String from this stream - it WILL break.
If you need to take it to a plain text representation, look into Base64 encoding, hex encoding, heck, even simple binary encoding.
In short, String objects are for things that humans read. Byte arrays (and many other things) are for things machines read.
You encoded baostream to a string with your default platform encoding, probably UTF-8. You should be using baostream.getBytes() to work with binary data, not strings.
If you insist on a string, use an 8-bit encoding, e.h. baostream.toString("ISO-8859-1"), and read it back with the same charset.
I want to read bytes from httpresponse coming from server continuosly into an array.
I'm creating a byte array with a maximum size of 2048.
So, I wanted to create a dynamically increasing array and I found that ArrayList is the solution.
How can i overcome this solution?
Any help would be appreciated lot
You can use a ByteArrayOutputStream to accumulate the bytes as you read them from the server. I would not use an ArrayList<Byte> because it requires boxing every byte value in a Byte.
When you want to access the bytes that have been accumulated, just call toByteArray() on the ByteArrayOutputStream.
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()]);
- You can also use ByteArrayInputStream and ByteArrayOutputStream.
Eg:
InputStream inputStream = socket.getInputStream();
// read from the stream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] content = new byte[ 2048 ];
int bytesRead = -1;
while( ( bytesRead = inputStream.read( content ) ) != -1 ) {
baos.write( content, 0, bytesRead );
} // while
// now, as you have baos in hand, I don't think you still need a bais instance
// but, to make it complete,
// now you can generate byte array input stream as below
ByteArrayInputStream bais = new ByteArrayInputStream( baos.toByteArray() );
Im receiving a file trough this code and the "bos.write" are saving it o to my HDD.
Everything working good.
Since im sending the file in a few second i thought i could store the file in memory
instead of HDD.
Now how do i do this?
File path = new File("C://anabella//test1.txt");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path));
int size = 1024;
int val = 0;
byte[] buffer = new byte[1024];
while (fileSize >0) {
val = in.read(buffer, 0, size);
bos.write(buffer, 0, val);
fileSize -= val;
if (fileSize < size)
size = (int) fileSize;
}
Presumably bos is a FileOutputStream? To use an in-memory buffer use a ByteArrayOutputStream instead.
If you know the size in advance you don't even need a ByteArrayOutputStream
InputStream is = socket.getInputStream(); // or where ever the inputstream comes from.
DataInputStream in = new DataInputStream(is);
byte[] bytes = new byte[fileSize];
in.readFully(bytes);
to send the bytes to any OutputStream like
OutputStream os = ...
os.write(bytes);
The bytes will contain the contents of the file.