Ok so i'm trying to send files with the sockets. This is the code i got on the server side. The problem is that if i let this code run i will get some strange output liking missing bytes. I tried to add thread.sleep() inside the if statement this seemed to help some and only made the problem appear when it was handling larger files. I also tried to place a breakpoint on the line buffer = setbuffersize(binaryData, i, in); so i stopped after each file. This seemed to help the problem. So i guess the problem is that the code continue to read even if there is nothing to read (the client has had time to send it yet). I'm not really sure how to fix this. I tried to check if BUFFER_SIZE was as big as in.available() but it seems to stop sending after a while and never reach the BUFFER_SIZE.
So how do i get the code to wait for the data to be transmitted before it tries to read it?
while (byteRead != -1) {
commandlengh = msg.length();
binaryData = new byte[Integer.parseInt(ParameterValues.get(ParameterValues.size() - 1))];
in.read();
byte[] buffer = setbuffersize(binaryData, i, in);
while (in.read(buffer) != -1) {
for (int j = 0; j < buffer.length; j++) {
binaryData[i] = buffer[j];
i++;
}
buffer = setbuffersize(binaryData, i, in);
if(buffer.length == 0)
{
Parameters.clear();
ParameterValues.clear();
i = 0;
commandlengh = 0;
break;
}
}
byteRead = in.read();
}
private byte[] setbuffersize(byte[] binaryData, int i, InputStream in) throws IOException
{
int BUFFER_SIZE = 65536;
if(binaryData.length - i < BUFFER_SIZE)
{
BUFFER_SIZE = binaryData.length - i;
}
else
{
BUFFER_SIZE = 65536;
}
byte[] buffer = new byte[BUFFER_SIZE];
return buffer;
}
You are ignoring the count returned by read() and assuming that it filled the buffer. Check the Javadoc. It isn't required to do that.
I can't make much sense of your code. You don't need all that to read from a socket. Just call read, check the result for -1; if so, stop; otherwise process bytes 0..count-1 of the buffer.
Related
In trying to fulfill a partial range request using chrome as the video playback tool, the video playback start playing back but on reaching halfway, it freezes as if the client is still waiting on more data. At this point the server has already sent the entire request. Please observe the following requests and response and the code used to send the range requested:
Range:bytes=0-
Accept-Ranges:bytes
Content-Length:546827
Content-Range:bytes 0-546827/546828
Content-Type:video/webm
Accept-Ranges:bytes
Content-Length:6155
Content-Range:bytes 540672-546827/546828
Content-Type:video/webm
Accept-Ranges:bytes
Content-Length:1
Content-Range:bytes 546827-546827/546828
Content-Type:video/webm
Is the second response handled correctly? Cause it freezes on this request and starts making multiple requests again until the request times out.
Code handling the request:
private static void copyStream (PullBufferStream inputStream, OutputStream outputStream, BytesStreamObject bytesWrittenObj, int from, int to) throws IOException, CodecNotAvailableException {
//export media stream
BufferedOutputStream bout = new BufferedOutputStream (outputStream);
Buffer b = new Buffer();
long skipped =0;
int byteLength = 0;
do {
inputStream.read(b);
int len = b.getLength();
byte[] data = (byte[]) b.getData();
int offset = b.getOffset();
if (len > 0) {
if(skipped < from) {
// skip bytes until reach from position in inputstream
if(skipped + len <= from) {
// skip all bytes just read
skipped += len;
} else {
// skip only some of bytes read
offset += (from - skipped);
len -= (from - skipped);
skipped = from;
}
}
if(to >= 0) {
if(from + byteLength + len <= to) {
// use the full buffer
} else {
// trim len to needed bytes to be read to prevent exceeding the "to" input parameter
len = (to + 1) - (from + byteLength);
}
}
byteLength+= len;
bytesWrittenObj.bytesWritten = byteLength;
bout.write(data, offset, len);
//bout.write(data, from, end);
}
} while (!b.isEOM());
//fileProperties.setBytesLength(byteLength);
//bout.close();
}
I needed to ensure I flush the outputstream but also made some changes on the actual file size rather than using stream.available().
I'm trying to get a BufferedInputStream from an uploaded cvs file.
I'm working with a Multipart derived from the cvs file.
When I first get the Multipart, it's a BufferedInputStream, but the buffer is all null.
But if I look deeper down, there's another buffer in the CoyoteInputStream and that has data.
How can I get at this second buffer? My code is below.
And of course it's throwing a null exception when it gets to
while ((multiPartDataPos = stream.read(buffer)) >= 0)
What am I doing wrong? Am I mistaken that the CoyoteInputStream is the data I want?
public byte[] handleUploadedFile(Multipart multiPart) throws EOFException {
Multipart multiPartData = null;
BufferedInputStream stream = null;
int basicBufferSize = 0x2000;
byte[] buffer = new byte[basicBufferSize];
int bufferPos = 0;
try {
while (multiPart.hasNext()) {
int multiPartDataPos = bufferPos;
multiPartData = (Multipart) multiPart.next();
stream = new BufferedInputStream(multiPartData.getInputStream());
while ((multiPartDataPos = stream.read(buffer)) >= 0) {
int len = stream.read(buffer, multiPartDataPos, buffer.length - multiPartDataPos);
multiPartDataPos += len;
}
bufferPos = bufferPos + multiPartDataPos;
}
} ...
Your code doesn't make any sense.
while ((multiPartDataPos = stream.read(buffer)) >= 0) {
At this point you have read multiPartDataPos bytes into buffer, so that buffer[0..multiPartDataPos-1] contains the data just read.
int len = stream.read(buffer, multiPartDataPos, buffer.length - multiPartDataPos);
At this point you are doing another read, which could return -1, which will otherwise add some data from multiPartPos to multiPartDataPos+len-.
multiPartDataPos += len;
This step is only valid if len > 0.
And you are doing nothing with the buffer; and next time around the loop you will clobber whatever you just read.
The correct way to read any stream in Java is as follows:
while ((count = in.read(buffer)) > 0)
{
// use buffer[9..count-1], for example out.write(buffer, 0, count);
}
I don't understand why you think access to an underlying stream is required or what it's going to give you that you don't already have.
Turns out the better solution was to use move the data from an InputStream to a ByteArrayOutputStream and then return ByteArrayOutputStream.toByteArray()
Multipart multiPartData = null;
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int read;
byte[] input = new byte[4096];
InputStream is;
try {
multiPartData = (Multipart)multipart.next();
is = multiPartData.getInputStream();
while ((read = is.read(input, 0, input.length)) != -1) {
buffer.write(input, 0, read);
}
buffer.flush();
return buffer.toByteArray(); // just a test right now
}
Is there a way to read all InputStream values at once without a need of using some Apache IO lib?
I am reading IR signal and saving it from the InputStream into the byte[] array. While debugging, I have noticed that it works only if I put a delay there, so that I read all bytes at once and then process it.
Is there a smarter way to do it?
CODE:
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[100];
int numberOfBytes;
removeSharedPrefs("mSharedPrefs");
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
numberOfBytes = mmInStream.read(buffer);
Thread.sleep(700); //If I stop it here for a while, all works fine, because array is fully populated
if (numberOfBytes > 90){
// GET AXIS VALUES FROM THE SHARED PREFS
String[] refValues = loadArray("gestureBuffer", context);
if (refValues!=null && refValues.length>90) {
int incorrectPoints;
if ((incorrectPoints = checkIfGesureIsSameAsPrevious(buffer, refValues, numberOfBytes)) < 5) {
//Correct
} else {
//Incorrect
}
}
saveArray(buffer, numberOfBytes);
}else{
System.out.println("Transmission of the data was corrupted.");
}
buffer = new byte[100];
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(Constants.MESSAGE_READ, numberOfBytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
// Start the service over to restart listening mode
BluetoothChatService.this.start();
break;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Edit:
My old answer is wrong, see EJPs comment! Please don't use it. The behaviour of ByteChannels depend on wether InputStreams are blocking or not.
So this is why I would suggest, you just copy IOUtils.read from Apache Commons:
public static int read(final InputStream input, final byte[] buffer) throws IOException {
int remaining = buffer.length;
while (remaining > 0) {
final int location = buffer.length - remaining;
final int count = input.read(buffer, location, remaining);
if (count == -1) { // EOF
break;
}
remaining -= count;
}
return buffer.length - remaining;
}
Old answer:
You can use ByteChannels and read into a ByteBuffer:
ReadableByteChannel c = Channels.newChannel(inputstream);
ByteBuffer buf = ByteBuffer.allocate(numBytesExpected);
int numBytesActuallyRead = c.read(buf);
This read method is attempting to read as many bytes as there is remaining space in the buffer. If the stream ends before the buffer is fully filled, the number of bytes actually read is returned. See JavaDoc.
I would like to execute XOR operation in my code. However I have strange behavior on the output. Sometimes the result is right but sometime it's not.
Here's the situation:
I have file which I already split into two parts and then I created one parity file using xor operation on both file (source files). So now I have three files. Then I deleted one of the source file. I would like to retrieve the missing file within xor operation between parity file and the remaining source file regarding the missing file. I am using hash function to check whether the output is correct or not. If the function is called only one time, everything is fine, but whenever I have many operations to retrieve the missing file on other files, sometimes my function generates the wrong result.
When they generate the wrong results, it's always generating the same file. BUT if I put thread.sleep for 1 second, they always generate the correct result even if I have more than 1000 operations.
Could somebody help me to spot which part of my code is broke?
private byte[] parityByte(byte[] firstByte, byte[] secondByte) {
int size1;
size1 = firstByte.length;
int size2;
size2 = secondByte.length;
byte[] parity;
parity = new byte[size1];
for (int i = 0; i < size2; i++) {
parity[i] = (byte) (firstByte[i] ^ secondByte[i]);
}
for (int i = size2; i < size1; i++) {
parity[i] = firstByte[i];
}
return parity;
}
/**
* get original chunks
*/
public Chunk getOriginal(Chunk parity, Chunk compare, String orig) throws FileNotFoundException, IOException {
File par = new File(parity.getHash());
InputStream parity = new BufferedInputStream(new FileInputStream(parity.getHash()));
InputStream source = new BufferedInputStream(new FileInputStream(compare.getHash()));
int size = (int) par.length();
int bufferSize = size;
byte[] firstBuffer = new byte[size];
byte[] secondBuffer = new byte[size];
long remainSize;
byte[] destByte = new byte[1];
parity.read(destByte, 0, 1);
Integer dest = new Integer(destByte[0]);
remainSize = size - 1 - dest;
OutputStream originalChunk;
originalChunk = new FileOutputStream(orig);
while (remainSize > 0) {
if (remainSize > bufferSize) {
remainSize -= bufferSize;
} else {
bufferSize = (int) remainSize;
firstBuffer = new byte[bufferSize];
secondBuffer = new byte[bufferSize];
remainSize = 0;
}
parity.read(firstBuffer, 0, bufferSize);
source.read(secondBuffer, 0, bufferSize);
originalChunk.write(parityByte(firstBuffer, secondBuffer));
}
originalChunk.flush();
parity.close();
source.close();
originalChunk.close();
Chunk tempChunk = Chunk.newChunk(orig);
return tempChunk;
}
Thank you
sorry for my bad english.
You are assuming that all the reads fill the buffer. Check the Javadoc. The read(byte[] ...) method returns a value, and it is for a reason.
Have a look at DataInputStream.readFully() for a simple solution.
Server side code
public static boolean sendFile() {
int start = Integer.parseInt(startAndEnd[0]) - 1;
int end = Integer.parseInt(startAndEnd[1]) - 1;
int size = (end - start) + 1;
try {
bos = new BufferedOutputStream(initSocket.getOutputStream());
bos.write(byteArr,start,size);
bos.flush();
bos.close();
initSocket.close();
System.out.println("Send file to : " + initSocket);
} catch (IOException e) {
System.out.println(e.getLocalizedMessage());
disconnected();
return false;
}
return true;
}
Client Side
public boolean receiveFile() {
int current = 0;
try {
int bytesRead = bis.read(byteArr,0,byteArr.length);
System.out.println("Receive file from : " + client);
current = bytesRead;
do {
bytesRead =
bis.read(byteArr, current, (byteArr.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead != -1);
bis.close();
bos.write(byteArr, 0 , current);
bos.flush();
bos.close();
} catch (IOException e) {
System.out.println(e.getLocalizedMessage());
disconnected();
return false;
}
return true;
}
Client side is multithreading,server side not use multithreading. I just paste some code that made problem if you want see all code please tell me.
After I debug the code, I found that if I set max thread to any and then the first thread always stuck in this loop. That bis.read(....) always return 0. Although, server had close stream and it not get out of the loop. I don't know why ... But another threads are work correctly.
do {
bytesRead =
bis.read(byteArr, current, (byteArr.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead != -1);
How large is your input file (the one you send?) and how large is "byteArr"?
Also, by the time your check how many bytes are read, you already called bis.read(..) twice:
int bytesRead = bis.read(byteArr,0,byteArr.length);
You probably want to read/send files larger than your buffer, so you probably want to do something like this:
byte [] buffer = new byte[4096];
int bytesRead;
int totalLength = 0;
while(-1 != (bytesRead = is.read(buffer))) {
bos.write(buffer, 0, bytesRead);
totalLength += bytesRead;
}
bos.close();
is.close();
"is" would be a plain InputStream, Peter is right, you do not need to buffer it.
read() will return 0 when you give it a buffer with no room left. (Which appears to be the case here)
I would suggest you use a DataInputStream.readFully() which does this for you.
dis.readFully(byteArr); // keeps reading until the byte[] is full.
If you are only writing large byte[] or only writing one piece of data, using a Buffered Stream just adds overhead. You don't need it.
BTW: When you call close() it will call flush() for you.