Java - Why while(true){ inputStream.read(incomingData) } does not work? - java

I want to ask simple question. Let's consider this psudo code:
InputStream is = socket.getInputStream();
byte[] incomingData = new byte[1024];
int incomingDataLenght = 0;
while(true) {
incomingDataLenght =is.read(incomingData,0,incomingData.length);
}
does not working.
But if you get byte array inside to while loop like
int incomingDataLenght = 0;
while(true) {
byte[] incomingData = new byte[1024];
incomingDataLenght =is.read(incomingData,0,incomingData.length);
}
everything is working well. The problem that i dont understand, when i declare a byte array, actually i'm declaring pointer. And one tour of while loop, i 'm giving that pointer to read method and it is filling my array which started from my declared pointer and i should use this pointer with fresh data. But in reality that does not work.
Could some one explain why it is not working?
Edit
Sorry for my unclear question. I'm reading media bytes from socket and storing inside ConcurrentLinkedQueue<byte> for some buffering time(that is producer). Then my consumer thread is starting. As i quoeted at above, when i move my array initialitizion inside the while loop, my data is gettin clear and my consumer thread can process my data successfully.
I think my answer is secret from my question. Whenewer i store byte array inside the queue, I'm stroing the same pointer(which is byte[] incomingData's pointer). When i start reading from queue, i'm reading current time's data instead of buffered data.
If this consideration is true, is that the best way to initialize array every while cycle?

although you didn't say what exactly happens with the first way, but there is an obvious difference between these two snippets :
in the second code 'incomingData' gets initialized every cycle!

Both examples will not compile with the error at
incomingDataLenght =is.read(incomingData,0,incomingData.lenght);
Should be
incomingDataLenght =is.read(incomingData,0,incomingData.length);

Your problem is undoubtedly that you are ignoring incomingLength after calling the read() method. Whatever else you're doing in this loop should only use incomingData from index [0] to index [incomingLength-1], and the loop should also break if incomingLength < 0.
A more conventional way to write it would be
while ((incomingLength = is.read(incomingData)) > 0)
{
// ...
}
The different behaviour you are observing will be that with a new buffer every loop iteration you get trailing nulls instead of trailing garbage left over from the previous iteration.

Related

I cannot understand API docs for Java/Android?

Consider the following code snippet for reading a file in Java/Android:
FileInputStream fis = openFileInput("myfile.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
StringBuffer b = new StringBuffer();
while (bis.available()!=0) {
char c = (char) bis.read();
b.append(c);
}
bis.close();
fis.close();
I am talking about available() method in the condition of while loop. I looked the API documentation for that method and I have the following questions:
How the iteration inside the the while loop is happening, i.e. how is the file pointer moving to another chunk of data during each iteration of while loop? This is not specified in the API documentation.
How can I figure out which method of which class should I use to accomplish a task?
The available method returns an int as an estimate of the number of bytes that can be read (or skipped over) from this input stream without blocking by the next invocation of a method for this input stream.
That while loop is iterating till the end of the file essentially, when there is no bytes there is no file.
Here is some documentation: http://docs.oracle.com/javase/7/docs/api/java/io/BufferedInputStream.html
The bis.available functions checks for end of file. in each iteration of the while loop when u do bis.read() the file pointer reads one character and automatically moves on to the next one.
As far as your query about which method to use. just look up the parameters that the function takes. and what u need to accomplish. its not very difficult figuring that out.

Why does FileInputReader.read() only reads 5 bytes at a time (Java)?

OK, so I've been trying to read a ("any") binary file to a byte[] array using FileInputReader.read()...But no matter the file length it only reads 5 bytes at a time...
(btw im using udp to send the array/file)
byte[] array_bytes = new byte[1024];
while((nread=file.read(array_bytes))!=-1){
number_bytesread += array_bytes.length;
socket_udp.send(send_package);
count += 1;
}
-send_package is a datagrampacket using array_bytes to send the message
I've tried to use the function read(byte[], offset, lenght), but if I put the lenght over 5, it occurs this error, at the first time reading, even thought the file is surely bigger than 5 bytes:
nread=file.read(array_bytes, 0, 1024);
no need for offset since i send immediatly after reading.
Exception in thread "main" java.lang.IndexOutOfBoundsException
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:272)
at udp_server2.UDP_Server2.Send_Udp(UDP_Server2.java:122)
at udp_server2.UDP_Server2.main(UDP_Server2.java:77)
Java Result: 1
Thanks in advance for the help,
André
It sounds like your array length isn't actually 1024. I know you've shown code creating it with 1024 bytes, but I suspect your actual code either changes the value somewhere else, or that it's created in a different way.
It would be helpful if you could show a short but complete program demonstrating the problem, but failing that, the first diagnostic step I'd take would be to look at array_bytes.length, either in the debugger or via logging. I strongly suspect that you'll find it's 5. Once you've established that, you need to work out why it's 5, which has nothing to do with the calls to reading from the input stream.
Also note that this line is fundamentally wrong:
number_bytesread += array_bytes.length;
It should be:
number_bytesread += nread;
... because you've just read nread bytes. You're also sending send_package which appears to have nothing to do with the data you've just read.
Additionally, I suggest you start following Java naming conventions, with things like arrayBytes rather than array_bytes. (I'd just use buffer or data, mind you - but I'm pointing out that variable and names in Java are typically camelCased rather than using_underscores_for_word_breaks.)

Writing an expanding array

I have a piece of code that waits for data to come from a shaky network. The machine that runs the code could also go down at any moment.
So I am writing in-coming data to the disk as the program runs. If the system goes down, I would have data up to that point. I can save each data object in a separate JSON file but that would end up with hundreds of thousands of files.
What I would like to do is to append to one JSON file that can be read back as an array or list. Each time the data comes in it is written to the end without re-writing the older data. What is the best way to do that?
You can create a FileWriter, with true as the second constructor argument. This makes a FileWriter that will append to an existing file, instead of replacing it (see http://docs.oracle.com/javase/7/docs/api/java/io/FileWriter.html).
The method does not change the value of OrigArray; all it does is store a clone of a clone in it, so in effect the value isn't changed.
I think what you want is this:
public void expand() {
String[] newArray = new String[OrigArray.length + 1];
System.arraycopy(OrigArray, 0, newArray, 0, OrigArray.length);
//an alternative to using System.arraycopy would be a for-loop:
// for(int i = 0; i < OrigArray.length; i++)
// newArray[i] = OrigArray[i];
OrigArray = newArray;
}
This creates an array that has a size 1 greater than OrigArray, copies the content of OrigArray into it and assigns that array to OrrigArray. Unless you want to remember how many times expand() has been called, there shouldn't be a reason to have the variable size.

When should I use a 'while loop'?

I just stumbled upon this question Are "while(true)" loops so bad?
They made me think what do I normally do.And to my surprise I realised that I have almost never used a while loop in my professional code(or work code) .
Front end frameworks e.g faces etc do not count.
So When should I use a 'while loop'? and
How often do you use while loop? It's is a real question please do not close as being subjective I really am after a concrete example.where it can not be replaced with a better alternate.
One place where I might use it is where you need to treat the first element of a sequence differently to the rest. That makes a foreach loop awkward, but a while loop works well:
Iterator<String> iterator = foo.iterator();
// Handle the first item specially
if (!iterator.hasNext()) {
throw new SomeException("foo shouldn't be empty");
}
SomeResult result = new SomeResult(iterator.next());
// Now deal with the rest
while (iterator.hasNext())
{
String item = iterator.next();
result.addItem(item);
}
Also I use a while loop as one of the few places where I'll also include an assignment in a condition:
String line;
while ((line = reader.readLine()) != null)
{
// Handle the line
}
or with an InputStream:
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1)
{
// Handle the buffer
}
java.util.Scanner scanner = //...
while(scanner.hasNextLine()) {
String line = scanner.nextLine();
//..do sth with the line
}
In fact every while loop can be replaced with for. But e.g. in the code above it would be less readable - and that's the point: use while when it fits better to the nature of the problem.
You should use it to loop while some condition holds true.
Simple never-stopping backend logic:
while (true) {
consumeMessage();
}
Or also
for (;;) {
consumeMessage();
}
You should use it when you dont know how many iterations will be needed.
You only know that you want to do something while your condition is met. It could be itereated 2, 100, 0... times.
Of course you can always rewrite a while loop into a for loop, but often it is uglier, meaning that parts of the for (..;..;..) are left blank - mainly the initialization. Findbugs also gives a warning in this case: similar to "simple for loop detected, rewrite it as a while loop".
The main application of the while loop is that you do not need an initialization, or want to treat the first loop iteration (e.g. first element of an enumeration) specially, in which case you do the initialization beforehand, too.
Use it when you have a main loop in your code which you want to run until something changes.
When you dont need a counter, and when you dont need to iterate over a collection (because then you need a counter).
Using a for(;whatever;) is ugly code, thats where you have to use a while.
Also the variation, do ... while allows you to do something at least once and then possibly many times.

Java FileInputStream ObjectInputStream reaches end of file EOF

I am trying to read the number of line in a binary file using readObject, but I get IOException EOF. Am I doing this the right way?
FileInputStream istream = new FileInputStream(fileName);
ObjectInputStream ois = new ObjectInputStream(istream);
/** calculate number of items **/
int line_count = 0;
while( (String)ois.readObject() != null){
line_count++;
}
readObject() doesn't return null at EOF. You could catch the EOFException and interpret it as EOF, but this would fail to detect distinguish a normal EOF from a file that has been truncated.
A better approach would be to use some meta-data. That is, rather than asking the ObjectInput how many objects are in the stream, you should store the count somewhere. For example, you could create a meta-data class that records the count and other meta-data and store an instance as the first object in each file. Or you could create a special EOF marker class and store an instance as the last object in each file.
I had the same problem today. Although the question is quite old, the problem remains and there was no clean solution provided. Ignoring EOFException should be avoided as it may be thrown when some object was not saved correctly. Writing null obviously prevents you from using null values for any other purposes. Finally using available() on the objects stream always returns zero, as the number of objects is unknown.
My solution is quite simple. ObjectInputStream is just a wrapper for some other stream, such as FileInputStream. Although ObjectInputStream.available () returns zero, the FileInputStream.available will return some value.
FileInputStream istream = new FileInputStream(fileName);
ObjectInputStream ois = new ObjectInputStream(istream);
/** calculate number of items **/
int line_count = 0;
while( istream.available() > 0) // check if the file stream is at the end
{
(String)ois.readObject(); // read from the object stream,
// which wraps the file stream
line_count++;
}
No. Catch EOFException and use that to terminate the loop.
If you write a null object at the end of the file, when you read it back you will get a null value and can terminate your loop.
Just add:
out.writeObject(null);
when you serialize the data.
It's curious that the API doesn't supply a more elegant solution to this. I guess the EOFException would work but I've always been encouraged to see exceptions as unexpected events whereas here you would often expect the object stream to come to an end.
I tried to work around this by writing a kind of "marker" object to signify the end of the object stream:
import java.io.Serializable;
public enum ObjectStreamStatus implements Serializable {
EOF
}
Then in the code reading the object i checked for this EOF object in the object reading loop.
No, you need to know how many objects there is in the binary file. You could write the number of objects at the beginning of the file (using writeInt for example) and read it while loading it.
Another option is to call ois.available() and loop until it returns 0. However, I am not sure if this is 100% sure.
It looks like the problem is with the data that you wrote out. Assuming the data is written as expected by this code, there shouldn't be a problem.
(I see you are reading Strings. This ObectInputStream isn't for reading text files. Use InputStreamReader and BufferedReader.readLine for that. Similarly if you have written the file with DataOutputSteam.writeUTF, read it with DataInputStream.readUTF)
The available method of ObjectInputStream cannot used to terminate the loop as it returns 0 even if there are objects to be read in a file. Writing a null to a file doen't seem to be a good solution either since objects can be null which then would be interpreted as the end of file. I think catching the EOFException to terminate the loops is a better practice since if EOFException occurs(either because you reached the end of the file or some other reason), you have to terminate the loop anyway.
The best possible way to end the loop could be done by adding a null object at the end. While reading the null object can be used as a boundary condition to exit the loop. Catching the EOFException also solves the purpose but it takes few m

Categories