我有一个网络套接字,它接收以下类型的消息:(大约每秒24条)
-
命令例如:
[Pos,1,2,3,4,1,2,3,4]n
-
Images:
[IMG,36000]nbyte[36000]
(byte[36000]是一个36000字节的数组)
所以我需要一个Reader来读取行和byte[]。问题是,BufferedReader转换字符集,这对于图像来说非常非常非常糟糕,所以读取字符串并将其转换为字节似乎不是一个选项。
我试图将DataInputStreamReader和BufferedReader连接到流,但它似乎在阅读器的第一次更改后中断,但我不确定是什么导致了那里的问题。
显而易见的解决方案是:
char c;
String s = "";
do{
c= (char)read.read(); //maybe charset conversion here
s+=c;
}while(c!= "n");
if(s.startsWith("[IMG")){
int len = Integer.parseInt(s.split(",")[1]);
byte[] img = new byte[len];
read.read(img);
...
但我正在寻找一个更好的,我需要做更少的手工。
- 建议用什么方法来处理这个问题?
- 有没有办法要将两个或多个阅读器连接到一个输入流?
- 是否有一个读取器可以读取字节[]和字符串?
- 它可能更容易写入所有的byte[],并从中读取?(我怎么知道,什么时候停止阅读?)
- 我可以防止混淆字节[]的字符转换吗?(然后我可以使用缓冲阅读器)
在最简单的情况下,我可以这样写:(这实际上并不多:D)
String s = read.readLine();
String[] parts = s.split(",");
if(parts[0].equals("[IMG")){
byte[] img = new byte[Integer.parseInt(parts[1])];
read.readByte(img);
...
改变视点可以有所帮助:将其视为根据需要转换为字符串的字节流。
在我的情况下,我有一个TCP客户端/服务器对必须处理包含几个ASCII控制字符的消息,包括CR &LF (= Windows上的java"换行符")-所有内容都必须"按原样"传递。
字符串可以用来构建嵌入控制代码的消息,但是嵌入任何"换行符"字符(例如VT)意味着字符串不能用来发送或接收消息-解决方法是将数据作为字节传递。
以下是我所做的(在服务器端和客户端):// ASCII control codes
char SOH = (char) 0x01;
char STX = (char) 0x02;
char ETX = (char) 0x03;
String CRLF = "" + (char) 0x0D + (char) 0x0A;
int characterCount = 0;
String characterSet = "US-ASCII"; // "UTF-8", UTF-16", etc.
String incomingData = "";
String outgoingData = "";
ServerSocket servSock = new ServerSocket( servPort );
Socket clntSock = servSock.accept();
InputStream incomingData = clntSock.getInputStream();
OutputStream outgoingData = clntSock.getOutputStream();
while ( true )
{
characterCount = in.read( byteBuffer ); // blocks, waiting for remote machine
incomingData = new String( byteBuffer, characterSet ); // omit 2nd parameter to use default encoding
outgoingData = SOH + STX + "Whatever it is" + CRLF + CRLF + CRLF + "you need" + CRLF + "to do" + ETX;
byteBuffer = outgoingData.getBytes( CharacterSet );
out.write( byteBuffer );
}
远端完全得到发送的内容(38个字符):SOH + STX +"Whatever it is"+ CRLF + CRLF + CRLF +"you need"+ CRLF +"to do"+ ETX
最后的想法:如果有一种方式/方法可以指定I/O包使用的"换行符",那么应该可以这样做:
// My first attempt was for a scanner that is functionally equivalent to System.out but
// automatically adjusts itself to the SYSTEM-DEPENDENT newline:
//
//String LineSeparator = System.getProperty( "line.separator" );
//String MessageSeparator = Pattern.quote( LineSeparator );
//Pattern EndOfMessageRegEx = Pattern.compile( MessageSeparator );
String MessageEndsWith = "" + STX + ETX; // Change this to whatever you need
String MessageSeparator = Pattern.quote( MessageEndsWith );
Pattern EndOfMessageRegEx = Pattern.compile( MessageSeparator );
ServerSocket thisMachine = new ServerSocket( portNumber );
Socket otherMachine = thisMachine.accept();
PrintWriter messageToClient = new PrintWriter( otherMachine.getOutputStream(), true );
BufferedReader messageFromClient = new BufferedReader(
new DataInputStreamReader( otherMachine.getInputStream(),
CharacterEncoding ) );
Scanner ReceivedData = new Scanner( messageFromClient ).useDelimiter( EndOfMessageRegEx );
首先接受所有二进制数据,使用InputStream。
InputStream stream = ...
然后在识别文本时读取:
int b = stream.read();
if (b == (byte)'E') { // Text stream recognized.
BufferedReader reader = new BufferedReader(
new InputStreamReader(stream, charset));
... use read no longer stream
}
你可以在已经读过的输入流上创建一个Reader。对于控件,您可能会使用单独的方法并尝试使用资源。BufferedInputStream可以包装二进制数据的原始InputStream。