首先我們聊一聊ASCII控制字符,這些控制字符是不可見的,可以理解爲一種特殊字符,而這種字符是可以被存入Oracle表中的。
項目中遇到了這樣一種情況,java程序從Oracle表中取數據並解析爲xml時產生了報錯信息,原因是表內存在無法被解析爲xml的特殊字符,後來導出數據後使用notepad++工具查看時才發現存在ASCII控制字符。注意,這些ASCII控制字符是無法被xml解析的,所以需要想辦法將其過濾。
ASCII控制字符
二進制 | 十進制 | 十六進制 | 縮寫 | 可以顯示的表示法 | 名稱/意義 |
---|---|---|---|---|---|
0000 0000 | 0 | 00 | NUL | ␀ | 空字符(Null) |
0000 0001 | 1 | 01 | SOH | ␁ | 標題開始 |
0000 0010 | 2 | 02 | STX | ␂ | 本文開始 |
0000 0011 | 3 | 03 | ETX | ␃ | 本文結束 |
0000 0100 | 4 | 04 | EOT | ␄ | 傳輸結束 |
0000 0101 | 5 | 05 | ENQ | ␅ | 請求 |
0000 0110 | 6 | 06 | ACK | ␆ | 確認迴應 |
0000 0111 | 7 | 07 | BEL | ␇ | 響鈴 |
0000 1000 | 8 | 08 | BS | ␈ | 退格 |
0000 1001 | 9 | 09 | HT | ␉ | 水平定位符號 |
0000 1010 | 10 | 0A | LF | ␊ | 換行鍵 |
0000 1011 | 11 | 0B | VT | ␋ | 垂直定位符號 |
0000 1100 | 12 | 0C | FF | ␌ | 換頁鍵 |
0000 1101 | 13 | 0D | CR | ␍ | 歸位鍵 |
0000 1110 | 14 | 0E | SO | ␎ | 取消變換(Shift out) |
0000 1111 | 15 | 0F | SI | ␏ | 啓用變換(Shift in) |
0001 0000 | 16 | 10 | DLE | ␐ | 跳出數據通訊 |
0001 0001 | 17 | 11 | DC1 | ␑ | 設備控制一(XON 啓用軟件速度控制) |
0001 0010 | 18 | 12 | DC2 | ␒ | 設備控制二 |
0001 0011 | 19 | 13 | DC3 | ␓ | 設備控制三(XOFF 停用軟件速度控制) |
0001 0100 | 20 | 14 | DC4 | ␔ | 設備控制四 |
0001 0101 | 21 | 15 | NAK | ␕ | 確認失敗迴應 |
0001 0110 | 22 | 16 | SYN | ␖ | 同步用暫停 |
0001 0111 | 23 | 17 | ETB | ␗ | 區塊傳輸結束 |
0001 1000 | 24 | 18 | CAN | ␘ | 取消 |
0001 1001 | 25 | 19 | EM | ␙ | 連接介質中斷 |
0001 1010 | 26 | 1A | SUB | ␚ | 替換 |
0001 1011 | 27 | 1B | ESC | ␛ | 跳出 |
0001 1100 | 28 | 1C | FS | ␜ | 文件分割符 |
0001 1101 | 29 | 1D | GS | ␝ | 組羣分隔符 |
0001 1110 | 30 | 1E | RS | ␞ | 記錄分隔符 |
0001 1111 | 31 | 1F | US | ␟ | 單元分隔符 |
0111 1111 | 127 | 7F | DEL | ␡ | 刪除 |
那麼,如何過濾掉這些ASCII控制字符呢。
方法1:通過java程序直接過濾掉ASCII控制字符。
此方法僅可用於方便變更java代碼的情況,本文不作描述。而當無法動java代碼時,我們就需要從sql的角度去過濾掉這些ASCII控制字符了,可以參考如下方法。
方法2:通過sql去過濾ASCII控制字符。
我們可以通過語句來確認ASCII的序號。
select ascii('') from dual; --此處無法正常顯示,可參考截圖
select chr(2) from dual;
可以得知該ASCII控制字符對應的十進制數爲2。我們將這個特殊字符拷貝至notepad++,發現對應以上表格內的可顯示字符爲'stx',與語句查出來的10進制數一致。
所以我們可以通過translate函數來批量過濾特殊字符:
translate('目標字段',
chr(0)||chr(1)||chr(2)||chr(3)||chr(4)||chr(5)||chr(6)||chr(7)||chr(8)||chr(9)||
chr(10)||chr(11)||chr(12)||chr(13)||chr(14)||chr(15)||chr(16)||chr(17)||chr(18)||chr(19)||
chr(20)||chr(21)||chr(22)||chr(23)||chr(24)||chr(25)||chr(26)||chr(27)||chr(28)||chr(29)||chr(30)||chr(31)
,' ')
注意以上最後一行單引號內有個'空格',如果不加空格將無法實現替換操作。
這樣我們就可以批量的過濾掉ASCII控制字符了。
我們可以通過查詢系統dual表的方式驗證一下語句的準確性:
這樣我們就可以很輕鬆的從數據庫內取值時過濾掉無法解析爲xml字符串的ASCII控制字符了。