从输入流读取行和字节[] [英] Reading Lines and byte[] from input stream
问题描述
我有一个网络套接字接收以下类型的消息:(每秒约24个)
-
命令EG:
[Pos,1,2,3,4,1,2,3,4] \\\
<
图片: [IMG,36000] \\\
(byte [36000]是一个36000字节的数组)
byte [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控制代码
pre>
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);
}
远端获取发送的内容(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屋!