Hex Dump

kata programming

مساله:

در محاسبات، hex dump یک نما از داده های کامپیوتر (بر روی کاغذ یا صفحه نمایش) در RAM‌ یا یک فایل یا دستگاه ذخیره سازی اطلاعات، به صورت hexadecimal است. نگاه به hex dump داده ها معمولا برای دیباگ کردن قسمتی از برنامه یا مهندسی معکوس استفاده می شود.

در یک hex dump هر بایت (۸بیت) با دو عدد hexadecimal نمایش داده می شود. hex dump ها عموما به صورت ردیف های ۸ یا 16 بایتی که گاهی با فاصله خالی از هم جدا می شوند، سازماندهی می شوند. برخی از hex dump ها آدرس حافظه hexadecimal در ابتدا و/یا checksum بایت ها در انتها را دارند.

(منبع: https://en.wikipedia.org/wiki/Hex_dump)

وظیفه شما:

وظیفه شما کامل کردن تابع های hexdump و dehex است:

تابع hexdump یک آرایه از بایت ها را از ورودی می گیرد و یک رشته به صورت hex dump به صورت فرمت زیر برمی گرداند:

  • آدرس حافظه به صورت عدد hexadecimal و ۸ عددی می باشد(شروع از 00000000) که به صورت : یا فاصله آورده می شود.
  • 16 بایت به صورت عددهای 2 تایی hexadecimal که به وسیله فاصله جدا می شوند نمایش داده می شود
  • دو فاصله
  • ترجمه ASCII اگر مقادیر ASCII بین 32 تا 126 باشد (هر دو شامل می شوند) انجام می شود، غیر این صورت نقطه کامل (.)

توجه: همه مقادیر hexadecimal (داده ها و آدرس ها) باید با حروف کوچک نشان داده شوند

اگر خط آخر کوتاهتر از 16 بایت باشد، مقادیر بایت را با فاصله جایگزین کنید، اما فاصله های انتهایی را حذف کنید.

برای مثال:

00000000: 1d c4 15 25 91 e6 09 59 04 99 15 29 0a 45 21 29  ...%...Y...).E!)
00000010: 26 8e 74 a0 1a be 75 68 06 dd 70 33 a4 77 7a 5d  &.t...uh..p3.wz]
00000020: b1 ba 22 a7 cf cc f7 ef b1 e3 13 ed f1 89 ad ad  ..".............
00000030: b8 2a 52 32 65 79 43 99 6f c8 d3 8e b2 5f 50 c9  .*R2eyC.o...._P.
00000040: 08 4a 12 25 79 c2 dd 31 6b b8 77 74 4b 68 4b d4  .J.%y..1k.wtKhK.
00000050: db 4e 92 09 d5 4c 9f 0b fd a9 d1                 .N...L.....

dehex یک رشته ورودی، با همان فرمت خروجی که در بالا توضیح داده شد، می گیرد و یک آرایه بایت را برمی گرداند.



In computing, a hex dump is a hexadecimal view (on screen or paper) of computer data, from RAM or from a file or storage device. Looking at a hex dump of data is commonly done as a part of debugging, or of reverse engineering.

In a hex dump, each byte (8-bits) is represented as a two-digit hexadecimal number. Hex dumps are commonly organized into rows of 8 or 16 bytes, sometimes separated by whitespaces. Some hex dumps have the hexadecimal memory address at the beginning and/or a checksum byte at the end of each line.

(source: https://en.wikipedia.org/wiki/Hex_dump)

Your Task

Your task is to complete the functions hexdump and dehex:

hexdump takes a byte array and returns a hex dump (as a string) in the following format:

the memory address displayed as an 8-digit hexadecimal number (starting from 00000000), followed by a colon (:) and a space,

16 bytes displayed as 2-digit hexadecimal numbers, separated by a space,

two spaces,

the ASCII translation of the bytes if the ASCII values are between 32 and 126 (both included), otherwise a full stop (.)

Note: all hexadecimal values (data and addresses) should be presented in lowercase

If the last line is shorter than 16 bytes, then replace the byte values with spaces, but trim the trailing spaces from the end of the line.

For example:

00000000: 1d c4 15 25 91 e6 09 59 04 99 15 29 0a 45 21 29  ...%...Y...).E!)
00000010: 26 8e 74 a0 1a be 75 68 06 dd 70 33 a4 77 7a 5d  &.t...uh..p3.wz]
00000020: b1 ba 22 a7 cf cc f7 ef b1 e3 13 ed f1 89 ad ad  ..".............
00000030: b8 2a 52 32 65 79 43 99 6f c8 d3 8e b2 5f 50 c9  .*R2eyC.o...._P.
00000040: 08 4a 12 25 79 c2 dd 31 6b b8 77 74 4b 68 4b d4  .J.%y..1k.wtKhK.
00000050: db 4e 92 09 d5 4c 9f 0b fd a9 d1                 .N...L.....

dehex takes a string input, in the same format as the output described above, and returns byte array.

Note: all inputs will be valid, so validating it is not necessary.


import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

public class Solution {
  public static String hexdump(byte[] data) {
    Integer address = 0;
    StringBuilder sb = null;
    List<String> resultList = new ArrayList<String>();
    String hexadecimalAddress = "";
    try {
      for (int i = 0; i < data.length; i += 16) {
        int length = (i + 16 > data.length) ? data.length : i + 16;
        byte[] splitData = Arrays.copyOfRange(data, i, length);
        String hexAddress = String.format("%02X", address).toLowerCase();

        String fullAddress = ("00000000" + hexAddress).substring(hexAddress.length()) + ": ";
        sb = new StringBuilder(fullAddress);
        hexadecimalAddress = "";
        for (int j = 0; j < 16; j++) {
          if (j < splitData.length)
            hexadecimalAddress += (String.format("%02X ", splitData[j]).toLowerCase());
          else
            hexadecimalAddress += ("   ");
        }

        hexadecimalAddress = StringUtils.rightPad(hexadecimalAddress, 48, " ");

        sb.append(hexadecimalAddress);
        sb.append(" ");
        for (byte b : splitData) {
          if (b >= 32 && b <= 126) {
            String text = new String(new byte[] { b }, StandardCharsets.US_ASCII);
            sb.append(text);
          } else {
            sb.append(".");
          }
        }
        address += 16;
        resultList.add(sb.toString());
      }
    } catch (Exception e) {
      System.out.println(sb + hexadecimalAddress);
    }
    return StringUtils.join(resultList, "\n");
  }

  public static byte[] dehex(String text) {
    List<Byte> integerBytes = new ArrayList<Byte>();
    try {
      String[] lines = text.split("\n");
      for (String line : lines) {
        String chars = line.substring(line.indexOf(": ") + 2, line.indexOf("  "));
        for (String ch : chars.split(" ")) {
          integerBytes.add((byte) (char) Integer.parseInt(ch, 16));
        }
      }

    } catch (Exception e) {
      System.out.println("asdasd");
    }
    Byte[] bytes = integerBytes.toArray(new Byte[integerBytes.size()]);
    return ArrayUtils.toPrimitive(bytes);
  }
}
import java.io.*;
import java.util.*;

public class Solution {
  
    public static String hexdump(byte[] data) {
      
      ByteArrayOutputStream array = new ByteArrayOutputStream();
      PrintWriter out = new PrintWriter(array);
  
      for(int offset = 0; offset < data.length; offset += 16){
        
        int i;      
        StringBuffer char_content = new StringBuffer();
        
        out.printf("%08x:", offset);
        char_content.append("  ");
  
        for(i = 0; i < 16 && offset + i < data.length; i++){
       
          int b = data[offset + i] & 0xFF;
          
          out.printf(" %02x", b);
          
          char_content.append( b >= 32 && b <= 126 ? (char) b : '.');
        }
        
        for(; i < 16; i++) out.printf("   ");
        
        out.print(char_content);
        
        if(offset + 16 < data.length) out.println();
      }
     
      out.flush();
      return array.toString();
    }

    public static byte[] dehex(String text) {
      
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      
      for(String line : text.split("\n")){
        
        for(String s : line.split(":")[1].split("  ")[0].trim().split(" ")){

          out.write(Integer.parseInt(s, 16) & 0xFF);
        }
      }
      
      return out.toByteArray();
    }
}
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;

public class Solution {
    public static String hexdump(byte[] data) {
      StringBuilder sb = new StringBuilder();
      int idx = 0;
      StringBuilder rowAscii = new StringBuilder();
      while (idx < data.length) {
        if (idx % 16 == 0) {
          if (idx > 0) {
            sb.append("\n");
          }
          insertAddress(sb, idx);
        }

        insertByte(sb, data[idx], rowAscii);
        
        if (idx % 16 == 15) {
          sb.append("  ");
          sb.append(rowAscii);
          rowAscii.setLength(0);
        }
        
        idx++;
      }
      
      if (rowAscii.length() > 0) {
        insertPad(sb, 3*(16-rowAscii.length()), ' ');
        sb.append("  ");
        sb.append(rowAscii);
      }
      
      return sb.toString();
    }
  
    private static void insertAddress(StringBuilder sb, int idx) {
      String addr = Integer.toHexString(idx);
      insertPad(sb, 8-addr.length(), '0');
      sb.append(addr);
      sb.append(":");
    }
  
    private static void insertPad(StringBuilder sb, int num, char ch) {
      for(int i = 0; i < num; i++) {
        sb.append(ch);
      }
    }
  
    private static void insertByte(StringBuilder sb, byte data, StringBuilder rowAscii) {
      int bData = data & 0xff;
      String hex = Integer.toHexString(bData);
      sb.append(' ');
      insertPad(sb, 2-hex.length(), '0');
      sb.append(hex);
      
      if (data >= 32 && data <= 126) {
        rowAscii.append((char)data);
      } else {
        rowAscii.append('.');
      }
    }

    public static byte[] dehex(String text) {
      ByteArrayOutputStream res = new ByteArrayOutputStream();
      
      int idx = 0;
      int state = 0;
      int nb = 0;
      while (idx < text.length()) {
        switch(state) {
            case 0:
              idx += 9;
              state = 1;
              nb = 0;
              break;
            case 1:
              idx++;
              try {
                byte b = (byte)Integer.parseInt(text.substring(idx, idx+2), 16);
                res.write(b);
              } catch(NumberFormatException e) {
                idx = text.length();
                break;
              }
              nb++;
              idx += 2;
              if (nb == 16) {
                state = 2;
              }
              break;
            case 2:
              if (text.charAt(idx) == '\n') {
                state = 0;
              }
              idx++;
              break;
        }
      }
      
      return res.toByteArray();
    }
}
import java.util.List;
import java.util.ArrayList;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;

public class Solution {
    private static final int lineLength = 16;

    public static String hexdump(byte[] data) {
        ByteBuffer bb = ByteBuffer.wrap(data);
    StringBuilder sb = new StringBuilder();

        for (int offset = 0; offset < data.length; offset += lineLength) {
            final int dataLength = (data.length - offset) >= lineLength ? lineLength : data.length - offset;
            byte[] line = new byte[dataLength];
            bb.get(line, 0, dataLength);
            //System.out.println(String.format("바이트 버퍼 초기 값 : %s", bb));
            //System.out.println("[" + new String(line, StandardCharsets.UTF_8) +"]");

            String address = String.format("%08x: ", offset);
      sb.append(address);
            String hexDump = getHexDumpString(line);
      sb.append(hexDump);
            String chars = getChars(line);
      sb.append(chars);
      sb.append("\n");
        }
        sb.deleteCharAt(sb.length() - 1);

        return sb.toString();
    }

  private static String getChars(byte[] line) {
    StringBuilder sb = new StringBuilder();
        char chars[] = new char[line.length];

        for (int i = 0; i < line.length; i++) {
            if ((char)line[i] >= 0x20 && (char)line[i] < 0x7f) chars[i] = (char)line[i];
            else chars[i] = '.';
        }

        return new String(chars);
    }

  private static String getHexDumpString(byte[] line) {
    StringBuilder sb = new StringBuilder();
        for (int i = 0; i < line.length; i++) {
      sb.append(String.format("%02x ", line[i]));
        }
        for (int i = 0; i < lineLength - line.length; i++){
      sb.append("   ");
        }
    sb.append(" ");

        return sb.toString();
    }

   public static byte[] dehex(String text) {
       List<Byte> byteObjects = new ArrayList<>();

       text.lines().forEach(line -> {
           String hexString = getHexString(line);
           //System.out.println(hexString);

           byte[] val = new byte[hexString.length() / 2];
           for (int i = 0; i < hexString.length() / 2; i++) {
               int index = i * 2;
               int hex = Integer.parseInt(hexString.substring(index, index + 2), 16);
               val[i] = (byte) hex;
           }

           for (byte b: val)
               byteObjects.add(b); // Autoboxing
       });

       int j=0;
       // Unboxing Byte values. (Byte[] to byte[])
       Byte[] array = byteObjects.toArray(new Byte[0]);
       byte[] bytes = new byte[array.length];
       for (Byte b: array)
           bytes[j++] = b.byteValue();
       return bytes;
   }

    private static String getHexString(String text) {
        final int offsetHex = 10;
        final int offsetText = 59;
        String address = text.substring(0, offsetHex - 2);
        String hex = text.substring(offsetHex, offsetText - 2);
        String content = text.substring(offsetText);
        System.out.println("[" + address + "] [" + hex + "] [" +  content + "]");

        return hex.replace(" ", "");
    }        
}
import java.math.BigInteger;
import java.util.Arrays;
public class Solution {

  public static String hexdump(byte[] data) {
    StringBuilder result = new StringBuilder();
    for (int i = 0; i < data.length / 16 + (data.length % 16 == 0 ? 0 : 1); i++) {
      int intAddress = i * 16;
      int rowStartIndex = i * 16;

      String addressString = String.format("%1$8s", Integer.toHexString(intAddress)).replaceAll(" ", "0");
      result.append(addressString).append(":");
      String asciiTranslation = "";
      for (int j = rowStartIndex; j < rowStartIndex + 16; j++) {
        if (j >= data.length) {
          result.append("   ");
          continue;
        }
        int intValue = Byte.toUnsignedInt(data[j]);
        String hexString = Integer.toHexString(intValue);
        result.append(" ").append(hexString.length() == 2 ? hexString : "0".concat(hexString));
        asciiTranslation += intValue >= 32 && intValue <= 126 ? (char) (intValue) : ".";
      }
      result.append("  ").append(asciiTranslation);
      if (i + 1 < data.length / 16 + (data.length % 16 == 0 ? 0 : 1)) result.append("\n");
    }

    return result.toString();
  }

  public static byte[] dehex(String text) {
    String hexString = "";
    for (String line : text.split("\n")) {
      hexString += line.substring(line.indexOf(':') + 2, line.indexOf("  "));
      hexString += " ";
    }
    return toByteArray(hexString);
  }

  private static byte[] toByteArray(String hexString) {
    String[] hexValues = hexString.split(" ");
    byte[] result = new byte[hexValues.length];
    int i = 0;
    for (String hex : hexValues) {
      byte[] hexInBytes = new BigInteger(hex, 16).toByteArray();
      result[i] = hexInBytes.length > 1 ? hexInBytes[1] : hexInBytes[0];
      i++;
    }
    return result;
  }

}

دیدگاهتان را بنویسید