How to write part of header using BufferedOutputStream? - java

I want to write a ~20000 bytes to a replace the same number of bytes of file at offset OFFSET using a BufferedOutputStream. I try to do this with the following code:
headerOffset = 12000;
headerSize = 20000;
byte[] ba = new byte[20];
FileOutputStream os;
BufferedOutputStream bos;
try {
os = new FileOutputStream('file.dat');
bos = new BufferedOutputStream(os);
bos.write(ba, headerOffset, headerSize);
os.flush();
} catch (IOException e) { e.printStackTrace(); }
However, this results in the 'file.dat' being overwritten by the contents of ba overwriting the entire file and leaving it only as big as ba. What am I doing wrong?

Related

send images through java android sockets

I want to send images through sockets but I have not been able to do it in android, could someone help me?
System.out.println("iniciooooo");
//converting image to bytes with base64
Bitmap b = BitmapFactory.decodeFile("/sdcard/ajeffer.jpg");
ByteArrayOutputStream byte2= new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.JPEG,70,byte2);
byte[] enbytes = byte2.toByteArray();
String bb = Base64.encodeToString(enbytes,Base64.DEFAULT);
System.out.println(Base64.encodeToString(enbytes,Base64.DEFAULT));
data.writeUTF(bb);
FileOutputStream file;
//receiving the image in bytes to convert it into an image
DataInputStream dain = new DataInputStream(s.getInputStream());
msg = dain.readUTF();
File ff = new File("/sdcard/a2jeffer.jpg");
byte[] deco = Base64.decode(dain.readUTF(),Base64.DEFAULT);
Bitmap bit = BitmapFactory.decodeByteArray(deco,0,deco.length);
file = new FileOutputStream(ff);
bit.compress(Bitmap.CompressFormat.JPEG,70,file);
//the image is not created
I realized that my code did not work because I had to put this android: requestLegacyExternalStorage =" true " in the manifest, also I see that you are right about writeUTF () since in order to send images I must drastically lower the quality but it works If you have an idea on how to improve this, let me know, thank you very much.
You were right, this works great for sending and receiving any file.
Send file
OutputStream outputStream = socket.getOutputStream();
InputStream inputStream = new FileInputStream(file);
byte[] datita = new byte[16*1024];
int count;
while((count = inputStream.read(datita))>0){
outputStream.write(datita,0,count);
}
outputStream.close();
inputStream.close();
Receive file
OutputStream outputStream = new FileOutputStream(file);
InputStream inputStream = s.getInputStream();
byte[] datita = new byte[16*1024];
int count;
while((count = inputStream.read(datita))>0){
outputStream.write(datita,0,count);
}
outputStream.close();
inputStream.close();

reading bytearray upto specified location

Let me allow to describe my problem:
I have created socket server in python and client in java, from java I am sending multiple objects to server by using :
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ByteArrayOutputStream append = new ByteArrayOutputStream();
ObjectOutput out = null;
byte finalarr[]=null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(object);
out.flush();
byte[] objByte = bos.toByteArray();
bos.close();
out.close();
append.write(objByte.length);
append.write(objByte);
bos = new ByteArrayOutputStream();
out = new ObjectOutputStream(bos);
out.writeObject(value);
out.flush();
append.write(bos.toByteArray());
finalarr = append.toByteArray( );
os = sChannel.socket().getOutputStream();
oos = new ObjectOutputStream(os);
oos.write(finalarr);
} finally {
try {
bos.close();
} catch (IOException ex) {
}
}
Now, finalarr contains byte length of object then actual byte[] of object and then byte[] of value. Now in python after receiving this First I want to read length of byte which is written in first position of finalarr then whatever length I get I want to read received array upto that length so that I will get object separately then the remaining part separately.
In python I have done upto this:
total_data=b''
while True:
data = self.clientsocket.recv(1024)
if not data: break
total_data += data
In total_data I am getting entire bytearray, but I don't know how I can read it so that I can get two objects separately as explained.

Upload large files to the Google Drive

In my app, I'm uploading files to the google drive using GD API. It works fine for small file sizes, but when file size is large (ex: 200MB), it throws java.lang.OutOfMemoryError: exception. I know why it crashes it loads the whole data into the memory, can anyone suggest how can I fix this problem?
This is my code:
OutputStream outputStream = result.getDriveContents().getOutputStream();
FileInputStream fis;
try {
fis = new FileInputStream(file.getPath());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[8192];
int n;
while (-1 != (n = fis.read(buf)))
baos.write(buf, 0, n);
byte[] photoBytes = baos.toByteArray();
outputStream.write(photoBytes);
outputStream.close();
outputStream = null;
fis.close();
fis = null;
} catch (FileNotFoundException e) {
}
This line would allocate 200 MB of RAM and can definitely cause OutOfMemoryError exception:
byte[] photoBytes = baos.toByteArray();
Why are you not writing directly to your outputStream:
while (-1 != (n = fis.read(buf)))
outputStream.write(buf, 0, n);

Dynamically stream files into a zip file response

I'm trying to dynamically zip my files as a response for the user, but for some reason they become slightly corrupted on the way. The client can receive them, open the zip folder and browse the files. However, opening or extracting them won't work.
Here's my code:
private void dynamicallyZipFiles(IHTTPSession session) {
try {
// Let's send the headers first
OutputStream os = session.getOutputStream();
PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(os, "UTF-8")), false);
pw.append("HTTP/1.1 200 \r\n");
printHeader(pw, "Connection", "keep-alive");
printHeader(pw, "Content-Type", "application/zip, application/octet-stream");
printHeader(pw, "Content-Disposition", "attachment; filename=\"pack.zip\"");
printHeader(pw, "Transfer-Encoding", "chunked");
pw.append("\r\n");
pw.flush();
// Send all the files from the list of files
ChunkedOutputStream cos = new ChunkedOutputStream(os);
ZipOutputStream zos = new ZipOutputStream(cos);
final LinkedList<String> files = new LinkedList<String>();
files.add("file1.txt");
files.add("file2.txt");
while (!files.isEmpty()) {
String file = files.remove();
File toBeSent = new File(file);
try {
ZipEntry ze = new ZipEntry(file);
zos.putNextEntry(ze);
InputStream is = (InputStream) new FileInputStream(toBeSent);
long BUFFER_SIZE = 16 * 1024;
byte[] buff = new byte[(int) BUFFER_SIZE];
int len;
while ((len = is.read(buff)) > 0) {
zos.write(buff, 0, len);
}
is.close();
zos.flush();
cos.flush();
zos.closeEntry();
} catch (Exception e) {
e.printStackTrace();
}
}
// Files have been sent, send the closing chunk
//cos.write("0\r\n\r\n".getBytes(), 0, "0\r\n\r\n".getBytes().length);
// The above line of code was the problem! Without it, it works!
cos.flush();
zos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// Helper for printing headers
private void printHeader(PrintWriter pw, String key, String value) {
pw.append(key).append(": ").append(value).append("\r\n");
}
I've been struggling for quite some hours already with this. I believe it has to have something to do with the closing chunk or with the closing of the connection?
I'm not sure what's the right order or way to close streams. I believe that when you have kind of "layered" streams and you close the top most one it will automatically close all the ones below too? And how about flush, if you flush a stream, will it flush the streams below it as well?With this I mean that my ZipStream for example, if I close it, will it close all the other streams as well? And if I flush it, will it flush all the other streams as well again?

java client server chat transferred files not received properly

I have my client server chat
Client sends files and server receives them. But, the problem is that, i don't think that files are received properly because when i check the size of the files i see the difference is halfed for some reasons!
I am using GUI to browse for files in the client side, and then i'm sending a command to the server to know that the client is sending a file. But it is not working
Here is the client and server
public void sendFiles(String file) {
try {
BufferedOutputStream outToClient = null;
outToClient = new BufferedOutputStream(sock.getOutputStream());
System.out.println("Sending file...");
if (outToClient != null) {
File myFile = new File( file );
byte[] mybytearray = new byte[(int) myFile.length()];
FileInputStream fis = null;
fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
this.out.println("SF");
bis.read(mybytearray, 0, mybytearray.length);
outToClient.write(mybytearray, 0, mybytearray.length);
this.out.flush();
outToClient.flush();
outToClient.close();
System.out.println("File sent!");
return;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Server
public void recvFile() {
try {
byte[] aByte = new byte[1];
int bytesRead;
InputStream is = null;
is = sock.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (is != null) {
FileOutputStream fos = null;
BufferedOutputStream bos = null;
try {
fos = new FileOutputStream("/Users/Documents/Received.png");
bos = new BufferedOutputStream(fos);
bytesRead = is.read(aByte, 0, aByte.length);
do {
baos.write(aByte);
bytesRead = is.read(aByte);
} while (bytesRead != -1);
bos.write(baos.toByteArray());
bos.flush();
bos.close();
// clientSocket.close();
} catch (IOException ex) {
// Do exception handling
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
Can someone help me with this issue? As i don't know how to properly send and receive files
Thank you
You are using two copy techniques, and they are both wrong.
First:
byte[] mybytearray = new byte[(int) myFile.length()];
bis.read(mybytearray, 0, mybytearray.length);
outToClient.write(mybytearray, 0, mybytearray.length);
Here you are assuming:
That the file fits into memory.
That the file length fits into an int.
That read() fills the buffer.
None of these assumptions is valid.
Second:
byte[] aByte = new byte[1];
bytesRead = is.read(aByte, 0, aByte.length);
do {
baos.write(aByte);
bytesRead = is.read(aByte);
} while (bytesRead != -1);
Here you are:
Using a ridiculously small buffer of one byte.
Writing an extra byte if the file length is zero.
Using a do/while where the situation naturally calls for a while (as 99.99% of situations do), and therefore:
Using two read() calls, and only correctly checking the result of one of them.
Pointlessly using a ByteArrayOutputStream, which, as above, assumes the file fits into memory and that its size fits into an int. It also pointlessly adds latency.
Throw them both away and use this, at both ends:
byte[] buffer = new byte[8192];
int count;
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
where:
in is a FileInputStream in the case of sending the file, or the socket input stream in the case of receiving the file.
out is a FileOutputStream in the case of receiving the file, or the socket output stream in the case of sending the file

Categories