2015-10-15 86 views
0

我有临危以下类型的消息的网络套接字:(每秒约24)读取线和字节[]从输入流

  • 命令EG:[Pos,1,2,3,4,1,2,3,4]\n

  • 图片:[IMG,36000]\nbyte[36000] (字节[36000]为36000个字节的数组)

因此,我需要一个读卡器该流,其能够读取线和字节[]。问题是,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); 
    ... 

回答

0

首先接受所有的二进制数据,使用一个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 
} 

您可以创建在一个InputStream一个阅读器从已经被读取。 对于控件,您可能会使用单独的方法并尝试使用资源。 BufferedInputStream可能会包装原始InputStream以获取二进制数据。

+0

问题是,我每秒会收到至少24条这样的消息,因此即使接受所有消息的部分也变得困难,我仍然需要读取帧并检查它们的行结束符,如果它们包含一个,我可以解析该命令,然后读取指定的长度,并将其余的缓冲区添加到读取数据的前面,这是我想要省下的努力。 –

+0

HTTP会有类似Content-Type这样的空行的标题行,然后是二进制或文本数据。 –

1

更改视点可以提供帮助:将其视为需要时转换为字符串的字节流。在我的情况下,我有一个TCP客户端/服务器对,它必须处理包含几个ASCII控制字符(包括CR & LF(= Windows上的java“newline”))的消息 - 并且所有内容都必须按照“原样”传递。

一个字符串可以用来构建一个带有嵌入式控制代码的消息,但是嵌入任何“换行”字符(例如,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 + “不管它是什么” + CRLF + CRLF + CRLF +“你需要”+ CRLF +“做”+ 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);