I need to write application which will be reeding data from InputStream. In short: my app will firstly connect to Bluetooth device. After connection my app will be reeding data From InputStream continuously. I mean that the device will send data for 20 milisec and app will be receive this data working for 24 hour maybe even more. For now I read this data in that way:
while((bytesReceived = is.read(buffer))>-1) {
//things to do with data
}
This loop receive data when it is in stream and stops when inputstream is close. My problem is that I think it is not optimal solution. After is.read(buffer) receive data it blocks waiting for next data what consume a lot of processor. Do you know any better way to read data what consume least processor power. Thanks for any help.
BTW. I write my app in Java on Android.
A blocking read does not consume CPU. The OS will put the calling thread/process to sleep.
That loop is fine.
Related
I am trying to read data from 5 devices connected serially. My Java code is running fine if the device is healthy, if not then inputstream.read() hangs the program and does not allow further execution.
I have tried using inputstream.available(), BufferedInputStream... but nothing works.
What I want to do is: if a device does not respond my code, it should end itself and let the control go to the main program where it will go to the next device. The socket remains open for one cycle of polling.
Socket es = new Socket("10.12.90.153",4001);
OutputStream osnew= es.getOutputStream();
InputStream isnew = new BufferedInputStream(es.getInputStream());
This is done in the task program, then I pass osnew and isnew to each device at a gap of one second for further action. The osnew writes some data to which the device responds. Then I read from isnew...This where the program hangs.
InputStream is designed to block when you try and read data and none is available. You could call the available() method to see whether any data is available to read without blocking, but this only works one way - if available() returns non-zero you know you can read without blocking, but if it returns zero you won't necessarily be blocked. It is perfectly valid for an input stream to always return zero from available().
You may wish to look into the non-blocking I/O APIs of java.nio instead of using streams.
You could handle each device in a separate thread. That way your program will stay responsive even when the devices aren't. But be aware of the pitfalls of multithreaded programming.
More information about multi-threaded programming in Java can be found on http://docs.oracle.com/javase/tutorial/essential/concurrency/
How are you reading from the device? I'll assume you're using some form of FileInputStream to do it. That class looks to be suitable for reading from a filesystem to me, but a device, which could block for a long period of time is likely to lock up the Java thread until the device does respond. You need to make some kind of timed read request of the device, and I don't know of any Java class that does that.
Best suggestion I have is to write some JNI code that talks nicely and doesn't block when your devices stop responding. This is what I did when I was talking to a USB device. If I were coding this (for Linux) I would use select (which has a time period argument) to wait of an input from any of the devices.
I am having what feels like should be a solved problem. An Android application I'm writing sends a message much like SMS where a user can attach a file. I'm using an HttpUrlConnection to send this data to my server which basically boils down to a java.io.OutputStream (I'm wrapping it in a DataOutputStream).
Being on a mobile device, sometimes network connectivity can be downright terrible and a send may take way too long. I have the following two fundamental problems:
The user has no way of knowing the progress of the upload
If the network is terrible and progress abysmal - I'd rather just abort or have some reasonable timeout rather than sit there and try for 5-10 minutes.
Problem 1:
I have tried to show upload progress based on my outputstream write() calls which I'm doing with 4K buffers:
buffer = new byte[4096];
long totalBytes = 0;
while ((bytesRead = fis.read(buffer)) > -1) {
totalBytes += bytesRead;
dos.write(buffer, 0, bytesRead);
if(showProgress){
updateProgressBar(totalBytes);
}
}
While this shows me progress, it seems it just shows me how fast the app can transfer the file buffer to the OS network stack buffer. The progress bar finishes very quickly even on slow network and then sits there for another large amount of time before I finally get the JSON back from my server telling me the status of the send. Surely there is some way to get some progress from the time I pass it to the OS to the time my server tells me it received it?
Problem 2:
Sometimes network connectivity is bad but not bad enough that the hardware radio triggers the callback for no connection found (in this case I go into an offline mode). So when it's bad but not off my app will just sit there at a sending dialog until the cows come home. This is connected to problem 1 in that I need to somehow be aware of the actual throughput since OutputStream doesn't provide a timeout mechanism natively. If it fell below some threshhold I could cancel the connection and inform the user that they need to get somewhere with decent reception.
Side Note: Asynchronous send / output queue is not an option for me because I cannot persist a message to disk and therefore cannot guarantee the drafted message is indefinitely in case it fails to send at some later point. I need/want to block on send, I just need to be smarter about giving up and/or informing the user about what is going on.
it seems it just shows me how fast the app can transfer the file buffer to the OS network stack buffer.
It's worse than that. It shows you how fast the app can transfer your data into the HttpURLConnection's internal ByteArrayOutputStream, which it is writing to so it can see the content length and set the header before writing any content.
Fortunately it's also better that than. If you know in advance how long the data is, set fixed-length transfer mode. If you don't, set chunked transfer mode with a lowish chunk size like 1024.
You will then be seeing how quickly your application can move data into the socket send buffer; in the case of chunked transfer mode, in units of the chunk size. However once the socket send buffer fills up your writes will then block and you will be seeing actual network transfers, at least until you have done the last write. Writing and closing are both asynchronous from that point on, so your display will pop down earlier, but everybody has that problem.
Re problem 2, once the transfer has settled down to network speed as above you can then compute your own throughput and react accordingly if it is poor.
I have several questions-
1. I have two computers connected by socket connection. When the program executes
outputStream.writeInt(value);
outputStream.flush();
what actually happens? Does the program wait until the other computer reads the integer value?
2. How can I empty the outputStream or inputStream? Meaning, when emptying
the outputStream or inputStream, whatever is written to that stream gets removed.
(please don't suggest to do it by closing the connection!)
I tried to empty the inputStream this way-
byte[] eatup=new byte[20*1024];
int available=0;
while(true)
{
available=serverInputStream.available();
if(available==0)
break;
serverInputStream.read(eatup,0,available);
}
eatup=null;
String fileName=(String)serverInputStream.readObject();
Program should not process the line as nothing else is being written on the outputStream .
But my program executes it anyway and throws a java.io.OptionalDataException error.
Note: I am working on a client-server file transfer project. The client sends files to
the server. The second code is for server terminal. If 'cancel button' is pressed on server
end then it stops reading bytes from the serverInputStream and sends a signal(I used int -1)
to the client. When client receieves this signal it stops sending data to the server, but I've
noticed that serverInputStream is not empty. So I need to empty this serverInputStream so that
the client computer is able to send the server computer files again(That's why I can't manage a lock
from read method)
1 - No. On the flush() the data will be written to the OS kernel which will likely immediately hand it to the network card driver, which in turn will send it to the receiving end. In a nutshell the send is fire and forget.
2 - As Jeffrey commented available() is not reliable for this sort of operation. If doing blocking IO then as he suggests you should just use read() speculatively. However it should be said that you really need to define a protocol on top of the raw streams, even if it's just using DataInput/DataOutputStream. When using raw write/read the golden rule is one write != one read. For example if you were to write 10 bytes on one side and had a reading loop on the other there is no guarantee that one read will read all 10 bytes. It may be "read" as any combination of chunks. Similarly two writes of 10 bytes might appear as one read of 20 bytes on the receiving side. Put another way there is no concept of a "packet" unless you create a higher level protocol on top of the raw bytes to do packets. An example would be each send is prefixed by a byte length so the receiving side knows how much data to expect in the current packet.
If you do need to do anything more complicated than a basic apps I strongly encourage you to investigate some higher level libraries that have solved many of the gnarly issues of network IO. I would recommend Netty which I use for production apps. However it is quite a big leap in understanding from a simple IO stream to Netty's more event based system. There may be other libraries somewhere in the middle.
I have an FFmpeg-based video-playing app which is able to play content from any arbitrary InputStream.
It is important that the app is able to play a video file which is in the process of being downloaded. What I seem to need for this is a special kind of FileInputStream that will (a) share file access with the downloading thread, and (b) if it reaches the end of the downloaded portion, will quietly block until more content becomes available.
(a) seems easy enough thanks to RandomAccessFile, but I'm a bit puzzled about (b). I can probably hack something up that will work, but I am wondering if there's a standard approach to implementing this. Thinking about it in detail gives me a feeling that I may be missing something obvious.
Any thoughts? How would you guys do this?
If you can push the data not in the file but into a OutputStream (or maybe write simulataneously to both FileOutputStream and other shared PipedOutputStream), this would be the easiest solution:
Use PipedOutputStream and PipedInputStream. This will allow you to implement both A and B, however you will need to somehow implement video buffering on the viewer side.
Basically your downloader thread will write every bit of data it gets to the PipedOutputStream. The write() method is not blocking, as the data is pushed to the internal buffer of the pipe.
Your viewer thread will simply read() from the pipedInputStream, as here is what the API says: This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.
You have to poll the length of the file. There is no way to block waiting for the length of the file to change using the file alone. You can busy poll, or poll every 10 or 100 ms.
If the writer and reader are in the same process, you can use locking/synchronized blocks to notify the reader when more data has been added.
With multiple processes, you could use a socket to either send the data, or at least notify when the length has changed allowing the reader to block.
In case you do not control the download process, and want to play just ANY downloading file (even by some other downloaders) then you can Watch directory for changes.
It needs to be mentioned that this method is cross-platform and cross-filesystem. Here's quote from the same article:
Most file system implementations have native support for file change notification. The Watch Service API takes advantage of this support where available. However, when a file system does not support this mechanism, the Watch Service will poll the file system, waiting for events.
I believe there is no real answer to this question. I've got something which works, but it looks like inelegant hacking to me. Perhaps sometimes that's inevitable.
On sending data over bluetooth from PC to my mobile(N73), the Input Stream seems to hang up.
InputStream is derived from StreamConnection.
PC software is built in VB.net.
Mobile in Java ME.
Does the InputStream have an internal buffer that needs to be emptied while reading large chunks of data?
Data is being received in chunks of 10Kb to 15Kb range, and the reading stops after receiving the 3rd chunk.
Strangely I am not receiving any exceptions.
I browsed through the InputStream class API documentation and couldn't find any InputStream clear or empty method.
There is only a reset() method, I don't know what its used for?
InputStream.reset() is a method you would call sometime after having used Inpustream.mark() to force the InputStream to create an internal buffer that would allow you to read the same data multiple times, assuming the InputStream supports it by returning true when calling InputStream.markSupported().
As far as the data transmission issue, we're talking about a handset running Series60 3rd edition on top of Symbian OS 9.1. Given how extensive the Symbian testing of JSR-82 was, an implementation bug as simple as a 40k limit on the InputStream seems unlikely.
Does the handset behavior change if the server sends smaller chunks at a much lower bitrate?
Does the handset process received data before reading some more?
What else is the MIDlet doing? Is everything else working as expected even after the bluetooth InputStream blocks?
I do remember a fairly important bug in the JSR-82 implementation that might have been fixed only after the initial N73 firmwares were created: do not use bluetooth at all in any event dispatching thread (not from any method like MIDlet.startApp(), Canvas.keyPressed(), CommandListener.commandAction(), PlayerListener.playerUpdate()...).
You are better off only using bluetooth from inside a Thread.run() method you wrote yourself.