2013-02-14 103 views
1

我想寫一個類用於Java和C++之間的通信在Java中過濾ASCII流

有很多關於Java和C++通信的討論。在這裏,我沒有要求如何溝通,我知道如何。

我創建了一個

OutputStream os = socketChannel.socket().getOutputStream(); 
OutputStreamWriter osw = new OutputStreamWriter(os); 
BufferedWriter wr = new BufferedWriter(osw); 

然後我寫

String data= dataArea.getText(); 

wr.write(dataArea.getText()); 
wr.write('\0');//here is the wire with C++ 
wr.flush(); // flushes the stream 

我發送一些文字:

Hi this is a test 
i send also 
character as dollar $ ... 
or other stange é*"£$%&/(()=?'^ìì[]@!<>#òùèé+* 
and so on 

所以讀取原始文本的兩種系統之間傳遞,我看到:

00000000 48 69 20 74 68 69 73 20 69 73 20 61 20 74 65 73 Hi this is a tes 
00000010 74 0A 69 20 73 65 6E 64 20 61 6C 73 6F 20 0A 63 t.i send also .c 
00000020 68 61 72 61 63 74 65 72 20 61 73 20 64 6F 6C 6C haracter as doll 
00000030 61 72 20 24 20 2E 2E 2E 0A 6F 72 20 6F 74 68 65 ar $ ... .or othe 
00000040 72 20 73 74 61 6E 67 65 20 C3 A9 2A 22 C2 A3 24 r stange ..*"..$ 
00000050 25 26 2F 28 28 29 3D 3F 27 5E C3 AC C3 AC 5B 5D %&/(()=? '^....[] 
00000060 40 21 3C 3E 23 C3 B2 C3 B9 C3 A8 C3 A9 2B 2A 0A @!<>#... .....+*. 
00000070 61 6E 64 20 73 6F 20 6F 6E 00      and so o n. 

這是靠近解決方案。

改變CHARSET 「US-ASCII」 我獲得

Hi this is a test 
    i send also 
    character as dollar $ ... 
    or other stange é*"£$%&/(()=?'^ìì[]@!<>#òùèé+* 
    and so on 


00000000 48 69 20 74 68 69 73 20 69 73 20 61 20 74 65 73 Hi this is a tes 
00000010 74 0A 20 20 20 20 69 20 73 65 6E 64 20 61 6C 73 t. i send als 
00000020 6F 20 0A 20 20 20 20 63 68 61 72 61 63 74 65 72 o . c haracter 
00000030 20 61 73 20 64 6F 6C 6C 61 72 20 24 20 2E 2E 2E as doll ar $ ... 
00000040 0A 20 20 20 20 6F 72 20 6F 74 68 65 72 20 73 74 . or other st 
00000050 61 6E 67 65 20 3F 2A 22 3F 24 25 26 2F 28 28 29 ange ?*" ?$%&/(() 
00000060 3D 3F 27 5E 3F 3F 5B 5D 40 21 3C 3E 23 3F 3F 3F =?'^??[] @!<>#??? 
00000070 3F 2B 2A 0A 20 20 20 20 61 6E 64 20 73 6F 20 6F ?+*.  and so o 
00000080 6E 00 

這是靠近我的目的。


我需要擴展字符「E」只傳輸ASCII - > E8

然後我需要把「\ 0」在字符串的結尾。

'\ 0'是消息終止符。

現在的問題:使用Java我喜歡創建一個Writer或流寫入器來輸出特定的二進制數據格式。

OutputStreamWriterBufferedWriter的正確工作級別,我應該從頭開始重寫還是使用某個庫? 一些例子都圍繞着我喜歡做什麼? 我會做同樣的輸入

我喜歡寫在這種形式,因爲明天當我重寫C++服務器在Java我使用兩端DataOutputStream。

使用while不是一個好的解決方案我更喜歡更多的Java集成解決方案。

回答

1

如您所願,此流可啓用自動刷新和US-ASCII。

OutputStream os = socketChannel.socket().getOutputStream(); 
PrintStream ps = new PrintStream(os, true, "US-ASCII"); 
ps.print("tange é*"£$%&/(()=?'^ìì[]@!<>#òùèé+*"); 
os.write((byte)0); // end-of-message 
+0

我添加了要使用的正確編碼。 我想擴展PrintStream,因爲我想添加一個ps.printMessage(「xxxx」); //在結尾添加\ 0。 ps.readMessage(); //讀到最後的異常或\ 0。 – user1594895 2013-02-15 09:27:00

1

我已經做基於的BufferedWriter和BufferedReader一個可能的解決方案,我用ISO-8859-1這是正確的ASCII擴展字符編碼。


OutputStream os = socketChannel.socket().getOutputStream(); 
OutputStreamWriter osw = new OutputStreamWriter(os, "ISO-8859-1"); 
TBufferedWriter bw = new TBufferedWriter (osw); 
bw.writeTMessageFlushing(dataArea.getText()); 


InputStream is = socketChannel.socket().getInputStream(); 
InputStreamReader isr= new InputStreamReader(is, "ISO-8859-1") ; 
TBufferedReader br= new TBufferedReader(isr); 
// wait for response 
String responseLine = br.readTMessage(); 

我只是打開的BufferedWriter源和BufferedReader andlooked如何獲取我的相互作用。

BufferedReader不能簡單地擴展,因爲使用了一些函數(它應該從java Boys重寫)。它擴展緩衝閱讀器,但無用


import java.io.BufferedWriter; 
import java.io.IOException; 
import java.io.Writer; 


public class TBufferedWriter extends BufferedWriter { 


    public TBufferedWriter(Writer out){ 
     super(out); 
    } 
    public TBufferedWriter(Writer out, int sz){ 
     super(out, sz); 
    } 

    public void writeTMessage(String message) throws IOException { 
     synchronized (lock) { 
       super.write(message); 
       super.write('\0'); 
     } 
    } 
    public void writeTMessageFlushing(String message) throws IOException { 
     synchronized (lock) { 
       super.write(message); 
       super.write('\0'); 
       super.flush(); 
     } 
    } 

} 

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.Reader; 


public class TBufferedReader extends BufferedReader { 
    private Reader in; 
    private char cb[]; 
    private int nChars, nextChar; 
    private static final int INVALIDATED = -2; 
    private static final int UNMARKED = -1; 
    private int markedChar = UNMARKED; 
    private int readAheadLimit = 0; /* Valid only when markedChar > 0 */ 

    /** If the next character is a line feed, skip it */ 
    private boolean skipNUL = false; 
    /** The skipLF flag when the mark was set */ 
    private boolean markedSkipLF = false; 
    private static int defaultCharBufferSize = 8192; 
    private static int defaultExpectedLineLength = 80; 


    /** 
    * Creates a buffering character-input stream that uses an input buffer of 
    * the specified size. 
    * 
    * @param in A Reader 
    * @param sz Input-buffer size 
    * 
    * @exception IllegalArgumentException If sz is <= 0 
    */ 
    public TBufferedReader(Reader in, int sz) { 
     super(in); 
     if (sz <= 0) { 
      throw new IllegalArgumentException("Buffer size <= 0"); 
     } 
     this.in = in; 
     cb = new char[ sz ]; 
     nextChar = nChars = 0; 
    } 


    /** 
    * Creates a buffering character-input stream that uses a default-sized 
    * input buffer. 
    * 
    * @param in A Reader 
    */ 
    public TBufferedReader(Reader in) { 
     this(in, defaultCharBufferSize); 
    } 


    /** Checks to make sure that the stream has not been closed */ 
    private void ensureOpen() throws IOException { 
     if (in == null) { 
      throw new IOException("Stream closed"); 
     } 
    } 


    /** 
    * Fills the input buffer, taking the mark into account if it is valid. 
    */ 
    private void fill() throws IOException { 
     int dst; 
     if (markedChar <= UNMARKED) { 
      /* No mark */ 
      dst = 0; 
     } else { 
      /* Marked */ 
      int delta = nextChar - markedChar; 
      if (delta >= readAheadLimit) { 
       /* Gone past read-ahead limit: Invalidate mark */ 
       markedChar = INVALIDATED; 
       readAheadLimit = 0; 
       dst = 0; 
      } else { 
       if (readAheadLimit <= cb.length) { 
        /* Shuffle in the current buffer */ 
        System.arraycopy(cb, markedChar, cb, 0, delta); 
        markedChar = 0; 
        dst = delta; 
       } else { 
        /* Reallocate buffer to accommodate read-ahead limit */ 
        char ncb[] = new char[ readAheadLimit ]; 
        System.arraycopy(cb, markedChar, ncb, 0, delta); 
        cb = ncb; 
        markedChar = 0; 
        dst = delta; 
       } 
       nextChar = nChars = delta; 
      } 
     } 

     int n; 
     do { 
      n = in.read(cb, dst, cb.length - dst); 
     } while (n == 0); 
     if (n > 0) { 
      nChars = dst + n; 
      nextChar = dst; 
     } 
    } 


    /** 
    * Reads a line of text. A line is considered to be terminated by any one 
    * of a line feed ('\0') 
    * 
    * @param  ignoreNUL If true, the next '\0' will be skipped 
    * 
    * @return  A String containing the contents of the line, not including 
    *    any line-termination characters, or null if the end of the 
    *    stream has been reached 
    * 
    * @see  java.io.LineNumberReader#readLine() 
    * 
    * @exception IOException If an I/O error occurs 
    */ 
    String readTMessage(boolean ignoreNUL) throws IOException { 
     StringBuffer s = null; 
     int startChar; 

     synchronized (lock) { 
      ensureOpen(); 
      boolean omitNUL = ignoreNUL || skipNUL; 
bufferLoop:  for (;;) { 
        if (nextChar >= nChars) { 
         fill(); 
        } 
        if (nextChar >= nChars) { /* EOF */ 
         if (s != null && s.length() > 0) { 
          return s.toString(); 
         } else { 
          return null; 
         } 
        } 
        boolean eol = false; 
        char c = 0; 
        int i; 

        /* Skip a leftover '\0', if necessary */ 
        if (omitNUL && (cb[nextChar] == '\0')) { 
         nextChar++; 
        } 
        skipNUL = false; 
        omitNUL = false; 

charLoop:    for (i = nextChar; i < nChars; i++) { 
          c = cb[i]; 
          if ((c == '\0')) { 
           eol = true; 
           break charLoop; 
          } 
         } 

        startChar = nextChar; 
        nextChar = i; 

        if (eol) { 
         String str; 
         if (s == null) { 
          str = new String(cb, startChar, i - startChar); 
         } else { 
          s.append(cb, startChar, i - startChar); 
          str = s.toString(); 
         } 
         nextChar++; 
         if (c == '\0') { 
          skipNUL = true; 
         } 
         return str; 
        } 

        if (s == null) { 
         s = new StringBuffer(defaultExpectedLineLength); 
        } 
        s.append(cb, startChar, i - startChar); 
       } 
     } 
    } 


    /** 
    * Reads a line of text. A line is considered to be terminated by any one 
    * of a line feed ('\n'), a carriage return ('\r'), or a carriage return 
    * followed immediately by a linefeed. 
    * 
    * @return  A String containing the contents of the line, not including 
    *    any line-termination characters, or null if the end of the 
    *    stream has been reached 
    * 
    * @exception IOException If an I/O error occurs 
    * 
    * @see java.nio.file.Files#readAllLines 
    */ 
    public String readTMessage() throws IOException { 
     return readTMessage(false); 
    } 
} 

其他有趣類是

http://www.ibm.com/developerworks/java/zos/javadoc/jzos/index.html?com/ibm/jzos/TranscodingPrintStream.html

org.apache.james.util.CharTerminatedInputStream


我增加約CharTerminatedInputStream一些消息。使用thtat類很危險,因爲您需要管理正在使用的正確字符集。 outputStream更高級別,可以插入InputStreamReader。