Search code examples
c#character-encoding

Implementing six bit character code in C#


I have a string which is alphanumeric. From this string I created a byte array:

var endoding = Encoding.ASCII.GetBytes("123abcABC");

The length of the string is equal to the length of the ASCII byte array encoding.Length , that is 9.

I want to squeeze this encoded array length to less than 9. So I am looking for Six-bit corrector code techniques

I wrote a sample (row) function based on the my understanding but it is failing for cap letters.

  • test case 1.
    string input = "ABCDEFGH"; // length = 8

    var Bytes1 = ConvertToEightBitCode(input ); // length = 6

    var output = GetRxString(Bytes1); // input == output 
  • test case 2
    string input = "ABCDEFGH123"; // length = 11

    var rxBytes1 = ConvertToEightBitCode(input ); // length = 9

    var output = GetRxString(Bytes1); // input == output 
  • test case 3 (failed)
      string input = "abcABC123"; // length = 9 

      var rxBytes1 = ConvertToEightBitCode(input ); // length = 8 

      var output =  GetRxString(Bytes1); // input != output

This function needs much improvement.

public static byte[] ConvertToEightBitCode(string rxNumber)
    {
        var asciiBytes = Encoding.ASCII.GetBytes(rxNumber);
        //Console.WriteLine("Actual ASCII rx bytes [{0}]", string.Join(", ", asciiBytes));
        byte[] newasciiByte = new byte[asciiBytes.Length];
        byte tt = 32;
        for (int i = 0; i < asciiBytes.Length; i++)
        {
            newasciiByte[i] = (byte)(asciiBytes[i] - tt);
        }
        //Console.WriteLine("Converted ASCII rx bytes [{0}]", string.Join(", ", newasciiByte));

        string datastring = "";
        foreach (var item in newasciiByte)
        {
            var e = Convert.ToString(item, 2);
            var pe = e.Length == 6 ? e : e.PadLeft(6, '0');
            datastring += pe;
        }
        //Console.WriteLine("Binary string [{0}]", datastring);
        int factor = GetDevideNum(datastring.Length, 8);
        List<string> new8Binary = new List<string>();
        for (int i = 0; i < factor; i++)
        {
            var s = GetCharString(datastring.ToCharArray(), i * 8, 8);
            if (!string.IsNullOrEmpty(s))
            {
                new8Binary.Add(s);
            }
        }
        //Console.WriteLine("New eight block binary string array [{0}]", string.Join(", ", new8Binary));

        List<byte> new8bytes = new List<byte>();
        foreach (var item in new8Binary)
        {
            var ii = Convert.ToByte(item, 2);
            new8bytes.Add(ii);
        }
        //Console.WriteLine("New Ascii bytes values for rx [{0}]", string.Join(", ", new8bytes));
        return new8bytes.ToArray();
    }

    public static string GetRxString(byte[] rxarray)
    {

        //Console.WriteLine("Input Ascii rx array values for rx [{0}]", string.Join(", ", rxarray));

        List<string> eightpadBinarystringArray = new List<string>();
        for (int i = 0; i < rxarray.Length; i++)
        {
            var ss = Convert.ToString(rxarray[i], 2);
            if (i == rxarray.Length - 1 && ss != "0")
                eightpadBinarystringArray.Add(GetExactBinary(ss));
            else
                eightpadBinarystringArray.Add(ss.PadLeft(8, '0'));
        }

        //Console.WriteLine("Converted eight block binary string array [{0}]", string.Join(", ", eightpadBinarystringArray));

        string eightpadBinarystring = string.Join("", eightpadBinarystringArray);
        //Console.WriteLine("Converted binary string array [{0}]", string.Join(", ", eightpadBinarystring));
        int factor = GetDevideNum(eightpadBinarystring.Length, 6);

        //eightpadBinarystring = 100001100010100011100100100101100110100111
        List<string> sixpadBinarystringArray = new List<string>();
        for (int i = 0; i < factor; i++)
        {
            var sixxx = GetCharString(eightpadBinarystring.ToCharArray(), i * 6, 6);
            if (!string.IsNullOrEmpty(sixxx))
            {
                sixpadBinarystringArray.Add(sixxx);
            }
        }

        //Console.WriteLine("Converted six pad block binary string array [{0}]", string.Join(", ", sixpadBinarystringArray));

        List<byte> result = new List<byte>();
        foreach (var item in sixpadBinarystringArray)
        {
            var rr = Convert.ToByte(item, 2);
            var bbr = (byte)(rr + 32);
            result.Add(bbr);
        }

        //Console.WriteLine("Converted ascii array [{0}]", string.Join(", ", result));

        StringBuilder rxNumber = new StringBuilder();
        foreach (var item in result)
        {
            if (item != 32)
            {
                char c = (char)item;
                rxNumber.Append(c);
            }
        }
        //Console.WriteLine("Converted char array [{0}]", string.Join(", ", clist));

        return rxNumber.ToString();
    }

    private static int GetDevideNum(int length, int f)
    {
        if (length % f == 0)
        {
            return length / f;
        }
        else
        {
            return length / f + 1;
        }
    }
   
    private static string GetExactBinary(string ss)
    {
        return ss.TrimStart(new char[] { '0' });
    }

    private static string GetCharString(char[] array, int start, int length)
    {
        int e = start + length;
        char[] dd = new char[length];
        for (int i = 0; i < length; i++)
        {
            dd[i] = ' ';
        }
        if (e <= array.Length)
        {
            Array.Copy(array, start, dd, 0, length);
            return string.Join("", dd);
        }
        else
        {
            int ne = array.Length - start;
            if (ne == 0)
            {
                return "";
            }
            Array.Copy(array, start, dd, 0, ne);
            var data = string.Join("", dd).Trim();

            string rdata = data.PadLeft(length, '0');
            return rdata;
        }
    }

Solution

  • I use six bit encoding from wiki table CDC 1612 printer codes (business applications)

    input is ABC1234

    A - 31 = hex to binary = 0011 0001 - six bit - 110001 -- six bit padding

    B - 32 = hex to binary = 0011 0010 - six bit - 110010

    C - 33 = hex to binary = 0011 0011 - six bit - 110011

    1- 01 = hex to binary = 0000 0001 - six bit - 000001

    2-02 = hex to binary = 0000 0010 - six bit - 000010

    3- 03 = hex to binary = 0000 0011 - six bit - 000011

    4 -03 = hex to binary = 0000 0100 - six bit - 000100

    New six bit 110001110010110011000001000010000011000100

    New eight bit pading 000000110001110010110011000001000010000011000100

    Eight bit array

    00000011 - binary to dec - 3

    00011100 - binary to dec - 28

    10110011 - binary to dec - 179

    00000100 - binary to dec - 4

    00100000 - binary to dec - 32

    11000100 - binary to dec - 196


    New aaray 3 -- dec to binary - 00000011 -- eight bit padding

    28 -- dec to binary - 00011100

    179 -- dec to binary - 10110011

    4 -- dec to binary - 00000100

    32 -- dec to binary - 00100000

    196 -- dec to binary - 11000100

    8 bit String 000000110001110010110011000001000010000011000100

    Six bit padding 000000110001110010110011000001000010000011000100

    000000 -- binary to hex -- 0 -- first ignore

    110001 -- binary to hex -- 31 -- A

    110010 -- binary to hex -- 32 -- B

    110011 -- binary to hex -- 33 -- C

    000001 -- binary to hex -- 01 -- 1

    000010 -- binary to hex -- 02 -- 2

    000011 -- binary to hex -- 03 -- 3

    000100 -- binary to hex -- 04 -- 4

    my c# code for this

    namespace NewApproachSixBitEncodeApp
    {
        class Program
        {
            static int maxLength = 28;
            static void Main(string[] args)
            {
                try
                {
                    string input = args[0];//"::AB:C1234::AB:C1234::AB:C12";
                    if (args.Length <= 0
                        || string.IsNullOrEmpty(args[0]))
                    {
                        throw new Exception("Input not correct please enter valid rx string.");
                    }
                    byte[] encode = Encode(input);
                    string output = Decode(encode);
                    Console.WriteLine("\ninput: [{0}] \ninput ecoded array [{1}] \ninput rx length: [{2}] \noutput encode array: [{3}] \noutput.encoded.length: [{4}] \noutput decoded: [{5}]",
                        input, string.Join(", ", Encoding.ASCII.GetBytes(input)), input.Length, string.Join(", ", encode), encode.Length, output);
    
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error : " + ex.Message);
                }
                Console.ReadLine();
            }
    
            static ReferenceTable referenceTable = ReferenceTableValue.Create();
    
            public static string Decode(byte[] encode)
            {
                string binary = "";
                foreach (var item in encode)
                {
                    binary += Convert.ToString(item, 2).PadLeft(8, '0');
                }
                while (binary.Length % 6 != 0)
                    binary = "0" + binary;
    
                var sixPadBitbinaryArray = Enumerable.Range(0, binary.Length / 6).
                Select(pos => binary.Substring(pos * 6, 6)
                          ).ToArray();
    
                StringBuilder result = new StringBuilder();
                int count = 0;
                foreach (var item in sixPadBitbinaryArray)
                {
                    string element = Convert.ToInt32(item, 2).ToString("X").PadLeft(2, '0');
                    if (element == "00" && count == 0)
                    {
                        count++;
                        continue;
                    }
                    count++;
                    result.Append(referenceTable.GetChar(element[0].ToString(), element[1].ToString()));
                }
                return result.ToString();
            }
    
            public static byte[] Encode(string input)
            {
                if (!referenceTable.IsValidString(input))
                {
                    throw new Exception("invalid string. use char from table" + input);
                }
                string eightPadBitbinary = "";
                foreach (var item in input.ToCharArray())
                    eightPadBitbinary += hex2binaryWithSixPadding(referenceTable[item]);
    
                while (eightPadBitbinary.Length % 8 != 0)
                    eightPadBitbinary = "0" + eightPadBitbinary;
    
                var eightPadBitbinaryArray = Enumerable.Range(0, eightPadBitbinary.Length / 8).
                Select(pos => Convert.ToByte(eightPadBitbinary.Substring(pos * 8, 8),
                              2)
                          ).ToArray();
    
                return eightPadBitbinaryArray;
            }
    
            static string hex2binaryWithSixPadding(string hexvalue)
            {
                var hexToBin = String.Join(String.Empty, hexvalue.Select(c => Convert.ToString(Convert.ToUInt32(c.ToString(), 16), 2).PadLeft(4, '0')));
    
                string result = hexToBin;
                while (result.Length > 6 && result.StartsWith("0"))
                    result = hexToBin.TrimStart(new char[] { '0' }); ;
                if (result.Length > 6)
                    throw new Exception("hex to bin length error HexValue = " + hexvalue);
                else
                    result = result.PadLeft(6, '0');
                return result;
            }
        }
    
        public class ReferenceTableValue
        {
            //CDC 1612 printer codes (business applications)
    
            private ReferenceTableValue()
            {
    
            }
    
            public string GetAllChar()
            {
                return string.Join("", list);
            }
            static List<string> list = new List<string>();
    
            public static ReferenceTable Create()
            {
                ReferenceTable t = new ReferenceTable();
                t.ReferenceTableValues = new List<ReferenceTableValue>();
                list.Add(":1234567890=≠≤![");
                list.Add(" /STUVWXYZ],(→≡~");
                list.Add("-JKLMNOPQR%$*↑↓>");
                list.Add("+ABCDEFGHI<.)≥?;");
    
                for (int row = 0; row <= 3; row++)
                {
                    for (int col = 0; col <= 15; col++)
                    {
                        char cc = list[row].Substring(col, 1).ToCharArray()[0];
                        ReferenceTableValue rf = new ReferenceTableValue(
                            String.Format("{0:X}", row),
                            String.Format("{0:X}", col),
                            cc);
    
                        t.ReferenceTableValues.Add(rf);
                    }
                }
                return t;
            }
    
            public ReferenceTableValue(string x, string y, char charector)
            {
                this.X = x;
                this.Y = y;
                this.Charector = charector;
            }
            public string X { get; set; }
            public string Y { get; set; }
            public char Charector { get; set; }
        }
    
        public class ReferenceTable
        {
            public List<ReferenceTableValue> ReferenceTableValues { get; set; }
    
            public bool IsValidString(string input)
            {
                if (string.IsNullOrWhiteSpace(input)
                    || ReferenceTableValues == null
                    || ReferenceTableValues.Count == 0)
                    return false;
    
                var refval = ReferenceTableValues[0];
                string allStringChar = refval.GetAllChar();
                foreach (var item in input.ToCharArray())
                {
                    if (!allStringChar.Contains(item))
                    {
                        return false;
                    }
                }
                return true;
            }
    
            public string this[char val]
            {
                get
                {
                    if (ReferenceTableValues == null) return null;
    
                    foreach (var item in ReferenceTableValues)
                    {
                        if ((int)item.Charector == (int)val)
                        {
                            return item.X + item.Y;
                        }
                    }
                    throw new Exception(string.Format("Value not found for char [{0}]",  val.ToString()));
                }
            }
    
            public char GetChar(string _x, string _y)
            {
                if (ReferenceTableValues == null)
                    return '\0';
                foreach (var item in ReferenceTableValues)
                {
                    if (item.X == _x && item.Y == _y)
                        return item.Charector;
                }
                throw new Exception(string.Format("value not found."));
            }
        }
    }