从输入流中读取行和byte []

时间:2015-10-15 13:31:24

标签: java sockets character-encoding stream bufferedreader

我有一个网络套接字,可以收到以下类型的消息:(大约每秒24个)

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

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

所以我需要一个能够读取行和byte []的流的Reader。问题是,BufferedReader转换了charset,这对于图像非常非常非常糟糕,所以读取字符串并将其转换为byte似乎不是一种选择。

我试图将一个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 []和字符串?
  • 将所有内容写入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);
  ...

2 个答案:

答案 0 :(得分:1)

更改视点可以提供帮助:将其视为根据需要转换为字符串的字节流。

在我的情况下,我有一个TCP客户端/服务器对,必须处理包含几个ASCII控制字符的消息,包括CR& LF(= java"换行符"在Windows上) - 一切都必须通过"按原样#34;。

字符串可用于构建带有嵌入式控制代码的消息,但嵌入任何"换行符"字符(例如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 );                                             

答案 1 :(得分:0)

首先使用InputStream接受all作为二进制数据。

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上创建Reader。 对于控件,您可能会使用单独的方法并尝试使用资源。 BufferedInputStream可能正在包装二进制数据的原始InputStream。