-
DataInputStream
Hi,
I have a two player Java game which uses DataInput/OutputStream to send boolean, integer and String (using writeUTF) messages to a server program.
I am trying to write a chat system to go with the game and therefore I have a situation where I dont know what type of message I'll be receiving (the game could be waiting for an integer when player sends a message as a String). I would like to read the stream as a byte array and then convert it to a String to check if it is a chat message and, if not, convert it to an integer or boolean or whatever is expected.
I can't seem to get this to work, I've tried something like:
byte[] b = new Byte[input.available()];
for(int i = 0 ; i < b.length ; i++){
b[i] = dataInputStream.readByte();
String s = new String(new byte[] {b[i]});
}
Add then adding the strings together but, firstly, if two messages come at once it reads them as one message and secondly, there are a lot of unwanted spaces in the message.
As for converting the byte array to an integer or boolean I havent tried yet because I'm not sure I'm going about the problem in the right way.
Thanks in advance!
-
And integer is 32 bits, aka 4 bytes.
A String is made up of 16 bit characters, aka 2 bytes.
If you read by bytes, then you are not getting the entire integer. I suggest having a format for which you send messages.
For example, the first integer determines what type of message it is. The second integer says how many pieces are there in the message, lets say N. The next N integers define what types the pieces are: String, boolean, int, double, etc... The next N data are the actual pieces.
-
Hi, thanks for your reply.
If I understand your idea correctly, I'm not sure it is suitable for my program. I currently have a loop which waits for a String:
String s = dataInputStream.readUTF();
When it receives a message, such as "sending move" or "pass" etc, it runs a different method depending on the message and then returns to the loop. That method may be expecting 2 integers and a String, for example.
int a = input.readInt();
int b = input.readInt();
String c = input.readUTF();
My problem is that if someone sends a chat message while its waiting for one of the integers it will read the message as an integer and inevitably there will be an error somewhere down the line.
What I would like to do is instead of
int a = input.readInt();
int b = input.readInt();
String c = input.readUTF();
is to use something like:
int a = myReadInt();
int b = myReadInt();
String c = myReadString();
Where the "myRead" methods do the following:
private int myReadInt(){
int a = 0;
-read input as bytes-;
String s = -read bytes as String-;
if(First characters of String == "CHAT"){
sendChatMessage();
a = myReadInt();
}
else a = -read bytes as int-;
return a;
}
and something similar for myReadString and myReadBoolean. That way I would know that what I'm trying to convert to an integer is always an integer, but sometimes I will be converting an integer to a String in order to check it. Would that work?
I hope all that makes sense.
Thank you again.
-
The problem is, you don't know how long the input as bytes is. A string could be any number of bytes. The best way is to have your own "protocol" on how data is sent.
My previous example is useful when you don't know how many pieces of data are in the message.
Code:
int msgLength = input.readInt();
Object data[] = new Object[msgLength];
for(int a = 0; a < data.length; a++) {
int type = input.readInt();
switch(type) {
case 0: data[a] = input.readUTF(); break;
case 1: data[a] = new Integer(input.readInt()); break;
case 2: data[a] = new Double(input.readDouble()); break;
//etc...
}
}
There is another example where you know how many pieces of data are in the message by using a header integer.
Code:
int messageType = input.readInt();
switch(messageType) {
case 0: //This could mean it is a chat message
String chat = input.readUTF();
handleChat(chat);
break;
case 1: //This could mean to move a player
int a = input.readInt();
int b = input.readInt();
String c = input.readUTF();
handleMovement(a,b,c);
break;
//etc.... You determine your own system.
}
-
Thank you for the explanation. I thought maybe there would be a way of determining the length of the data. As readUTF, readInt etc. seem to read the entire message automatically, I thought it may be possible. As you've probably guessed I'm quite new to all this.
I see how your idea would work, I'll give it a try. Isn't it possible though that a chat message is received between reading the type = input.readInt() and the data = input.readInt/UTF?
-
readInt() reads 4 bytes of data. readUTF() reads a 2-byte header that gives the length of the string, then it reads the number of bytes specified.
That is only possible if you don't synchronized the sending of data. Your client needs to send things one by one.
-
Thank you very much for your help!
Robs
-