亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

用Java制作十六進制編輯器

2019-11-18 13:29:38
字體:
來源:轉載
供稿:網友

  本人在用java編制一個網絡應用測試工具的時候,迫切希望能以十六進制方式顯示和編輯socket上傳輸的數據,于是自己動手寫了一個編輯器類,實現基本的十六進制編輯功能。效果如圖一、圖二所示,可以看到,編 
  輯器可以支持常規方式和十六進制兩種方式對數據進行編輯。
  分析:對于同一段數據值,用兩種方式來顯示和編輯,則用MVC(模型-視圖-控制器)模式來作為主結構是再合適不過的了。模型的作用是保存真實的數據值,同時提供若干提取和修改數據的方法;視圖是數據在用戶界面上的表示,控制器定義用戶界面對用戶輸入的響應方式,即把用戶的鍵盤動作和鼠標動作解釋成模型中的數據操作方法。出于簡化的考慮,本例中把視圖和控制器合并到了一起。
  模型的設計:編輯器必須能處理任意字節塊,所以考慮模型內用字節數組來存儲數據;要提供在指定偏移處增加、修改和刪除字節塊的操作;當模型內的數據被改變時要及時通知視圖來刷新用戶界面或其它感愛好的對象;
   用Java制作十六進制編輯器(圖一)
  圖一
   用Java制作十六進制編輯器(圖二)
  圖二
  
  視圖和控制器的設計:
  
  對于常規編輯的視圖,只需把模型中的字節數組轉化成String,使用一個文本區域組件JTextArea來顯示即可。JTextArea本身也是一個遵循MVC模式的Swing組件,它的控制器即可被用來作為我們自己的控制器,監聽它的文本增加、修改和刪除事件,從而控制我們自己的數據模型;
  
  對于16進制編輯的視圖,同樣可以用JTextArea來顯示,只是在顯示之前,要對模型中的數據進行若干加工,如每行顯示16個字節,每行都要加表示偏移量的頭,行尾要加這一行數據的字符串表示形式。它的控制器則不能簡單的利用JTextArea的控制器了,為了保證顯示格式不被打亂,需要監視它的所有光標移動事件、鍵盤擊鍵事件等。同時,為了保持與UltraEdit的十六進制編輯器的功能一致性,對它的數據的增加、刪除功能提供兩個按鈕,詢問用戶操作的字節數,假如增加n個字節,則在輸入光標處插入n個十六進制值為20的字符(字符空格)。
  十六進制編輯器的主要結構請參見下圖,由于篇幅關系,圖中只列出了十六進制編輯部分,常規編輯部分請讀者自行設計:
  用Java制作十六進制編輯器(圖三)
  圖三
  
  下面分別就幾個主要的方法的功能和主要流程加以說明。
  
  HeXPane.displayValue方法,它主要完成數據的顯示工作:
  
  public void diplayValue() {
  
  canvas.setText("");
  
  
  byte[] data = model.getData();
  
  int dataLen = data.length;
  
  
  // 把字節數組按每16個字節為一塊進行分塊;
  
  int lines = dataLen / 16 + 1;
  
  int tails = dataLen % 16;
  
  int offset = 0;
  
  for(int i = 0; i < lines; i ++) {
  
  // 在canvas的新行上加上行標,如“000020:”,表示這是第3行;
  
  canvas.append(lineHead(i));
  
  canvas.append(" ");
  
  // 把數據塊的字節值用Integer.toHexString()轉化成長度為48的字符串,數據塊不足16個字節的,在字符串后用空格補足;把字符串加入canvas的當前行;
  
  for(offset = 0; offset < 16; offset ++) {
  
  canvas.append((i < lines - 1 offset < tails) ? byteHex(data[i * 16 + offset]) : " ");
  
  canvas.append(" ");
  
  }
  
  canvas.append(" ");
  
  
  // 把數據塊構造成字符串,添在canvas的行尾;
  
  canvas.append(bytesToStr(data, i * 16, (i == lines - 1) ? tails : 16));
  
  if(i < lines - 1) ta.append("/n");
  
  };
  
  }
  這里的bytesToStr方法有兩點非凡需要注重的地方,一是不可見字符,假如不屏蔽這些字符,則我們的編輯器的顯示格式會被搞得亂七八糟,一般可以把ASCII值0到0x1F和0x7F的33個字符全部替換成0x2E,即字符小數點。二是中文字符,因為每個中文字符是2個字節,假如數據塊的起始字節一個中文字符的一半(可以用ASCII值大于0x7F來判定)的時候,將會顯示一串亂字符,處理方法是不顯示該字節。
  為敘述方便,我們把canvas中顯示每一行的行標的區域稱為標號區,它寬度固定為8個字符(6個字符顯示標號,一個冒號和一個空格);把canvas中顯示十六進制數據的區域稱為數據區,寬度固定為48個字符(每字節用十六進制顯示為2字符寬,兩兩之間有一個空格,則總寬為16×3);把canvas中每行以字符串形式顯示數據的區域稱為字串值區,寬度不定(最短為8個字符――全中文狀態,最長為16個字符――全英文狀態)。
  
  我們的canvas是一個Swing的文本組件,我們不但用它顯示數據,還顯示標號和字串值,而只有數據才是答應被編輯的,所以我們給canvas增加了CaretListener和KeyListener,當輸入光標落在不答應編輯的區域時,我們要把光標自動移到最近的答應編輯的地方去。
  
  public void caretUpdate(CaretEvent e) { // 這個方法在輸入光標移動時被觸發
  
  int pos = canvas.getCaretPosition(); // 輸入光標相對canvas第0行第0個字符的偏移量
  
  int line = 0;
  
  int startPos = 0;
  
  try {
  
  line = canvas.getLineOfOffset(pos); // 輸入光標位于第幾行
  
  startPos = canvas.getLineStartOffset(line); // 當前行的第0個字符相對canvas第0行第0個字符的偏移量
  
  }catch(BadLocationException exception) { }
  
  if(pos - startPos < 8) // 輸入光標在標號區
  
  canvas.setCaretPosition(startPos + 8); // 移動到數據區第0個字符
  
  else if(pos - startPos > 54) // 輸入光標在字串值區
  
  canvas.setCaretPosition(startPos + 54); // 移動到數據區最后一個字節
  
  else if((pos - startPos - 8) % 3 == 2) { // 在數據區的間隙空格上
  
  canvas.setCaretPosition(pos - 1); // 往前移一個字符
  
  }
  
  }
  public void keyPRessed(KeyEvent e) { // 當鍵盤被按下時觸發
  
  int key = e.getKeyCode();
  
  switch(key) { // 假如是方向鍵則移動輸入光標
  
  case KeyEvent.VK_LEFT:
  
  setCaretPrev();
  
  break;
  
  case KeyEvent.VK_RIGHT:
  
  setCaretNext();
  
  break;
  
  case KeyEvent.VK_UP:
  
  setCaretPrevLine();
  
  break;
  
  case KeyEvent.VK_DOWN:
  
  setCaretNextLine();
  
  break;
  
  default:
  
  return;
  
  }
  
  }
  public void keyTyped(KeyEvent e) { // 在鍵盤的可見字符被輸入時觸發
  
  char ch = e.getKeyChar();
  
  if((ch >= '0' && ch <= '9') (ch >= 'a' && ch <= 'f')
  
   (ch >= 'A' && ch <= 'F')) {
  
  int pos = canvas.getCaretPosition(); // 先獲取光標位置的信息
  
  int line = 0, startPos = 0;
  
  try {
  
  line = canvas.getLineOfOffset(pos);
  
  startPos = canvas.getLineStartOffset(line);
  
  }catch(BadLocationException exception) { }
  
  char c = (char)0;
  
  if((pos - startPos - 8) % 3 == 0) { // 一個字節值的前4位
  
  c = canvas.getText(pos + 1, 1).charAt(0);
  
  model.updateBytes(line * 16 + (pos - startPos - 8) / 3, Byte.parseByte("" + (char)((ch << 4) + c), 16));
  
  }else{ // 一個字節值的后4位
  
  c = canvas.getText(pos - 1, 1).charAt(0);
  
  model.updateBytes(line * 16 + (pos - startPos - 8) / 3, Byte.parseByte("" + (char)((c << 4) + ch), 16));
  
  setCaretNext();
  
  }
  
  }
  
  }
  
  到這里為止,十六進制編輯的顯示和輸入控制已經基本完成了,下面開始解決數據Model的問題。Model是用來保存數據的,并且提供增加、修改和刪除數據的方法,還要維護一個監聽者組,在數據被改變時向監聽者發出通知。這里提供一個簡單的實現版本。
  import javax.swing.event.EventListenerList;
  
  
  public class DefaultBytesModel implements BytesModel{
  
  private EventListenerList listeners = new EventListenerList(); // 監聽者組
  
  private byte[] data = null;
  
  
  public DefaultBytesModel (byte[] bytes) {
  
  data = new byte[bytes.length];
  
  }
  
  
  public void addModelListener(BytesModelListener listener) {
  
  listeners.add(BytesModelListener.class, listener);
  
  }
  
  
  public void removeModelListener(BytesModelListener listener) {
  
  listeners.remove(BytesModelListener.class, listener);
  
  }
  
  
  /**
  
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
海角国产乱辈乱精品视频| 国产激情综合五月久久| 欧美黑人性生活视频| 久久久综合免费视频| 黄色成人av在线| 日韩欧美国产中文字幕| 欧美大码xxxx| 一区二区三区在线播放欧美| 亚洲美女动态图120秒| www.亚洲成人| 国产精品丝袜白浆摸在线| 国产精品久久在线观看| 欧美日本啪啪无遮挡网站| 日本a级片电影一区二区| 热re91久久精品国99热蜜臀| 国产精品电影久久久久电影网| 亚洲精品一二区| 91精品视频在线| 亚洲欧美国产精品va在线观看| 日韩视频永久免费观看| 久久久极品av| 久久久亚洲福利精品午夜| 欧美激情极品视频| 国产精品精品视频| 久久精品99久久久香蕉| 国产精品亚洲一区二区三区| 亚洲a级在线观看| 久久久国产一区二区三区| 欧美肥臀大乳一区二区免费视频| 在线视频一区二区| 日韩动漫免费观看电视剧高清| 久久精品99久久香蕉国产色戒| 久久精品电影网| 精品一区二区三区四区在线| 亚洲视频免费一区| 国产精品永久免费在线| 亚洲男人天堂九九视频| 国产91精品久| 色婷婷av一区二区三区久久| 97精品久久久中文字幕免费| 久久在线观看视频| 国语自产精品视频在线看| 中文字幕日韩视频| 日韩欧美国产黄色| 色yeye香蕉凹凸一区二区av| 欧美巨乳美女视频| 91精品在线播放| 欧美亚洲激情在线| 一区二区三欧美| 国产成人综合一区二区三区| 日韩成人黄色av| 中文字幕最新精品| 在线观看精品自拍私拍| 亚洲综合日韩中文字幕v在线| 日韩亚洲国产中文字幕| 欧美国产日韩一区二区三区| 国产精品偷伦免费视频观看的| 尤物九九久久国产精品的分类| www.xxxx欧美| 亚洲国产高清高潮精品美女| 欧美激情视频三区| 国产精品91在线| 91伊人影院在线播放| 亚洲精品乱码久久久久久按摩观| 日韩av中文在线| 欧美精品国产精品日韩精品| 中文字幕亚洲一区在线观看| 久热精品视频在线免费观看| 国产精品视频最多的网站| 一本大道香蕉久在线播放29| 日本伊人精品一区二区三区介绍| 久久久久久伊人| 亚洲人成电影网站色www| 国产精品永久免费观看| 日韩成人在线播放| 国产成人免费91av在线| 午夜精品久久久久久久99热| 国产小视频91| 日韩免费观看在线观看| 欧美电影免费在线观看| 中文字幕一区日韩电影| 91沈先生作品| 欧美床上激情在线观看| 成人97在线观看视频| 欧美激情综合亚洲一二区| 成人午夜激情网| 亚洲欧美日韩网| 国产一区二区三区高清在线观看| 欧美刺激性大交免费视频| 一个人看的www久久| 91国产视频在线| 欧美激情视频一区二区三区不卡| 国语自产在线不卡| 国产一区二区三区在线播放免费观看| 久久久久久尹人网香蕉| 国产成人精品免费久久久久| 国产精品美女久久久免费| 日韩电影在线观看永久视频免费网站| 欧美激情2020午夜免费观看| 亚洲天堂免费观看| 久久影视电视剧免费网站| 岛国av在线不卡| 不卡av在线播放| 国产精品第100页| 欧美片一区二区三区| 亚洲视频电影图片偷拍一区| 欧美日韩亚洲视频| 色悠悠久久久久| 两个人的视频www国产精品| 视频在线一区二区| 精品国产网站地址| 国产欧美va欧美va香蕉在线| 伊人久久免费视频| 日韩资源在线观看| 欧美亚洲视频在线观看| 精品国产乱码久久久久久婷婷| 久久国产天堂福利天堂| 一区二区三区国产在线观看| 日韩在线小视频| 韩国v欧美v日本v亚洲| 国产成人97精品免费看片| 欧美成人在线影院| 亚洲欧美日韩中文在线制服| 精品成人乱色一区二区| 色综合久久88色综合天天看泰| 久久精品99久久香蕉国产色戒| 亚洲tv在线观看| 精品久久久av| 亚洲国产毛片完整版| 国产成人一区二区| 亚洲自拍高清视频网站| 91在线视频一区| 国自产精品手机在线观看视频| 日韩电视剧免费观看网站| 日韩电影在线观看免费| 亚洲自拍偷拍在线| 91精品国产九九九久久久亚洲| 欧美另类高清videos| 91精品国产电影| 欧美高清视频在线播放| 亚洲欧美日韩国产精品| 青青草一区二区| 久久久久久久一区二区三区| 久久久电影免费观看完整版| 久久色在线播放| 91黑丝在线观看| 国产91精品青草社区| 成人av在线亚洲| 96sao精品视频在线观看| 亚洲精品国精品久久99热一| 俺也去精品视频在线观看| 最近中文字幕2019免费| 亚洲一区二区三区视频| 九九视频这里只有精品| 亚洲精品视频网上网址在线观看| 亚洲日韩中文字幕| 国产亚洲成精品久久| 久久男人资源视频| 伊人久久男人天堂| 91精品国产乱码久久久久久久久| 性日韩欧美在线视频| www.日韩av.com| 国产97色在线| 亚洲一区二区三区乱码aⅴ|