How to load streamed data directly into a BufferedImage - java

I am using the code provided by this accepted answer to send a list of files over a socket in Java. My goal is to be receiving a list of images. What I would like to do is read these images directly into memory as BufferedImages before writing them to disk. However, my first attempts, which was to use ImageIO.read(bis) (again, see the attached question) failed, as it attempted to continue reading beyond the end of the first image file.
My current idea is to write the data from the socket to a new output stream, then read that stream from an intput stream that is passed to ImageIO.read(). This way, I can write it byte by byte as the program is currently doing, but send it to the BufferedImage rather than the file. however I'm not sure how to link the output stream to an input stream.
Can anyone recommend simple edits to the code above, or provide another method of doing this?

In order to read the image before writing it to disk, you'll need to use a ByteArrayInputStream. http://docs.oracle.com/javase/6/docs/api/java/io/ByteArrayInputStream.html
Basically, it creates a inputstream that reads from a specified byte array. So, you'd read the image length, then it's name, then the length-amount of bytes, create the ByteArrayInputStream, and pass it to ImageIO.read
Example snippet:
long fileLength = dis.readLong();
String fileName = dis.readUTF();
byte[] bytes = new byte[fileLength];
dis.readFully(bytes);
BufferedImage bimage = ImageIO.read(new ByteArrayInputStream(bytes));
Or using the code from the other answer you cited:
String dirPath = ...;
ServerSocket serverSocket = ...;
Socket socket = serverSocket.accept();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
DataInputStream dis = new DataInputStream(bis);
int filesCount = dis.readInt();
File[] files = new File[filesCount];
for(int i = 0; i < filesCount; i++)
{
long fileLength = dis.readLong();
String fileName = dis.readUTF();
byte[] bytes = new byte[fileLength];
dis.readFully(bytes);
BufferedImage bimage = ImageIO.read(new ByteArrayInputStream(bytes));
//do some shit with your bufferedimage or whatever
files[i] = new File(dirPath + "/" + fileName);
FileOutputStream fos = new FileOutputStream(files[i]);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write(bytes, 0, fileLength);
bos.close();
}
dis.close();

Related

Convert file to byte array in reverse order

byte[] bFile = new byte[(int) file.length()];
FileInputStream fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
fileInputStream.close();
This code let's me convert file to byte array, am looking for reading file from end to start (in reverse order)
Edit : i dont wan't to read entire file. A part at the end (Example around 1000 bytes)
File file = new File(/*file path*/);
byte[] bFile = new byte[1000];
RandomAccessFile fileInputStream = new RandomAccessFile(file, "r");
fileInputStream.seek(fileInputStream.length() - bFile[0].length);
fileInputStream.read(bFile, 0, bFile.length);
fileInputStream.close();
I just figured it out, reading last 1000 bytes of a file

Incorrect upload file use FileOutputStream. Incorrect size

When I try upload the file from server, I use this code. I get the file size of 500kb, when the original file size about 300kb.
What am I doing wrong?
attachmentContent = applicationApi.getApplicationAttachmentContent(applicationame);
InputStream in = new BufferedInputStream(attachmentContent.getAttachmentContent().getInputStream());
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n=0;
while (-1 !=(n=in.read(buf)))
{
out.write(buf,0,n);
}
out.close();
in.close();
byte[] response = out.toByteArray();
File transferredFile = new File(attachmentName);
FileOutputStream outStream = new FileOutputStream(transferredFile);
attachmentContent.getAttachmentContent().writeTo(outStream);
outStream.write(response);
outStream.close();
Simplify. The same result:
File transferredFile = new File(attachmentName);
FileOutputStream outStream = new FileOutputStream(transferredFile);
attachmentContent.getAttachmentContent().writeTo(outStream);
outStream.close();
The ByteArrayOutputStream is a complete waste of time and space. You're reading the attachment twice, and writing it twice too. Just read from the attachment and write directly to the file. Simplify, simplify. You don't need 90% of this.

Java: Error creating a GZIPInputStream: Not in GZIP format

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.

FileInputStream to byte array in Android application

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.

java server/client save a downloadad file NOT to HDD

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.

Categories