簡體   English   中英

從輸入流中讀取行和byte []

[英]Reading Lines and byte[] from input stream

我有一個網絡套接字,它接收以下類型的消息:(大約每秒24條)

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

  • 圖片: [IMG,36000]\\nbyte[36000] (byte [36000]是36000個字節的數組)

因此,我需要一個能夠讀取行和byte []的流的Reader。 問題在於,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 []和字符串的讀取器?
  • 將所有內容寫入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);
  ...

更改視點可能會有所幫助:將其視為字節流,可以根據需要將其轉換為字符串。

在我的情況下,我有一個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 );                                             

首先使用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上創建一個Reader。 對於控件,您可能會使用單獨的方法和try-with-resources。 BufferedInputStream可能將原始InputStream包裝為二進制數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM