从输入流读取行和字节[] [英] Reading Lines and byte[] from input stream

查看:153
本文介绍了从输入流读取行和字节[]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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




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


  • <

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




所以我需要一个读取器来读取行和byte []。问题是,BufferedReader转换字符集,这是非常,非常非常糟糕的图像,所以读取字符串并将其转换为字节似乎不是一个选项。



我试图连接一个DataInputStreamReader和BufferedReader到流,但它似乎在读者第一次更改后中断,但我不确定是什么导致的问题。



显而易见的解决方案是:

  char c; 
String s =;
do {
c =(char)read.read(); //也许charset转换在这里
s + = c;
} while(c!=\\\
);
if(s.startsWith([IMG)){
int len = Integer.parseInt(s.split(,)[1]);
byte [] img = new byte [len];
read.read(img);
...

但我正在寻找一个更好的,




  • 处理这个问题的建议方法是什么?

  • 是否有一种方式
    将两个或多个读取器连接到输入流?

  • 是否有可读取byte []和字符串的读取器?

  • 将所有内容写入byte []并从中读取? (我怎么知道,什么时候停止阅读?)

  • 我可以防止将字节[]混乱的chartype转换吗? (我可以使用缓冲读取器)



在最简单的情况下,我可以写这个代码: 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);
...


解决方案

help:将它看作一个字节流,根据需要转换为字符串。



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



字符串可以用于构建具有嵌入控制代码的消息,但嵌入任何换行字符(例如VT)意味着字符串不能用于发送或接收message - 解决方法是将数据作为字节传递。



它是我做的(在服务器和客户端)的本质:

  // ASCII控制代码

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等。
String incomingData =;
String outgoingData =;

ServerSocket servSock = new ServerSocket );
Socket clntSock = servSock.accept();

InputStream incomingData = clntSock.getInputStream();
OutputStream outgoingData = clntSock.getOutputStream();

while(true)
{
characterCount = in.read(byteBuffer); //块,等待远程机器

incomingData = new String(byteBuffer,characterSet) ; //忽略第二个参数使用默认编码

outgoingData = SOH + STX +无论是什么+ CRLF + CRLF + CRLF +你需要+ CRLF +

byteBuffer = outgoingData.getBytes(CharacterSet);

out.write(byteBuffer);
}
pre>

远端获取发送的内容(38个字符):SOH + STX +无论是什么+ CRLF + CRLF + CRLF + CRLF +to do+ ETX



最后一想:如果有一个方法/方法来指定I / O包使用的newline应该是可能的:

  //我的第一次尝试是一个功能等同于System.out的扫描器, 
//自动调整到SYSTEM-DEPENDENT换行符:
//
// String LineSeparator = System.getProperty(line.separator);
// String MessageSeparator = Pattern.quote(LineSeparator);
// Pattern EndOfMessageRegEx = Pattern.compile(MessageSeparator);

String MessageEndsWith =+ STX + ETX; //将它改为任何你想要的东西
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);


I have a network socket which recieves the following types of messages: (about 24 per second)

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

  • Images: [IMG,36000]\nbyte[36000] (byte[36000] is an array of 36000 bytes)

So I would need an Reader for that stream that is able to read lines and byte[]. The problem is, that the BufferedReader converts the charset, which is very, very, very bad for images, so reading a string and converting it to byte seems not to be an option.

I tried to connect a DataInputStreamReader and a BufferedReader to the stream but it seems to break after the first change of the reader, but I am not really sure about what caused the problem there.

The obvious solution is:

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);
  ...   

But I am searching for a better one where I need to do less manually.

  • What is the recommended way to deal with this problem?
  • Is there a way to connect two or more readers to an input stream?
  • Is there a reader which can read byte[] and strings?
  • Is it probably easier to write everything to byte[] and read from that? (How do I know then, when to stop reading?)
  • Can I prevent the chartype conversion which messes the byte[] up? (Then i could use the Buffered Reader)

In the easiest case I could write that code: (Which is actually not much more :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);
  ...

解决方案

Changing the viewpoint can help: Look at it as a byte stream that gets converted to strings as needed.

In my case I have a TCP client/server pair that must handle messages containing several ASCII control characters including CR & LF (= the java "newline" on Windows) - and everything must be passed through "as is".

A string can be used to build a message with embedded control codes but embedding any "newline" character (e.g. VT) means that a string cannot be used send or receive the message - the workaround is to pass the data as bytes instead.

Heres the essence of what I did (on server and client) :

// 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 );
}

The far end gets exactly what was sent (38 characters): SOH + STX + "Whatever it is" + CRLF + CRLF + CRLF + "you need" + CRLF + "to do" + ETX

A final thought : If there was a way/method to specify the "newline" used by the I/O packages something like this should be possible:

//   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 );                                             

这篇关于从输入流读取行和字节[]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆