locked
Strings.Chr not giving desired output RRS feed

  • Question

  • Hey all, I'm running into a bit that is getting very frustrating.  I'm in the process of converting VB6 apps to C# apps, and I am hitting something that is causing data alignment issues.

     

    In my old VB6 app I call up 

    strCommandString = Chr(chrArrayHeader[index])
    

    when the array has an integer value of 31 or less, it was giving me an unprintable byte, i.e. : carriage returns, bold, what have you.

     

    I am using

    strCommandString = Strings.Chr(chrArrayHeader[index])
    

    This works for all values of 32 and higher, but the lower values are giving me 2 byte returns of "\b, \0, \f" and the like.  This obviously isn't going to work if my send/receive functions are capped at expecting 10 bytes of data.  

     

    My question, is there something equivalent in C# to give me a single byte return on Chr for integer values of 31 and lower?

    Tuesday, November 30, 2010 3:01 PM

Answers

  • Well you're not using Encoding.Default as per my example above. You should try that.

    You're running into problems because you're using a unicode string to store ascii characters - and of course it doesn't work. All strings in C# (and VB for .Net) are utf16.

    You don't show us what you're doing with the string once you've constructed it...

    However, what happens if you try this:

    Instead of:

     while (idx < 10)
     {
     shutdownStr = shutdownStr + Strings.Chr(shutdownByteArray[idx]);
     idx = idx + 1;
     }
    

    Try this:

    shutdownStr = Encoding.Default.GetString(shutdownByteArray);
    
    • Marked as answer by Alan_chen Thursday, December 9, 2010 1:25 AM
    Wednesday, December 1, 2010 3:51 PM
  • Thanks for all the help guys.  I am just going to rewrite the comm section to return the byte instead of a char that needs to be encoded/decoded.
    • Marked as answer by Alan_chen Thursday, December 9, 2010 1:25 AM
    Wednesday, December 1, 2010 6:14 PM

All replies

  • I think it's easier to send your data as binary, or change your array to HexString (BitConverter). 
    Tuesday, November 30, 2010 3:24 PM
  • No can do.  The messaging handler DLL, which I am not allowed to touch, requires things to remain as they are.  I need a way to keep the data structure as 10 bytes, not refactor the entire system.
    Tuesday, November 30, 2010 3:38 PM
  • Have you tried simple cast?

    char a = (char)b;

    Tuesday, November 30, 2010 3:46 PM
  • Is this not simply a Unicode versus Ansi issue?

    In which case, use a Text.Encoding.Default to convert the string to an array of Ansi bytes and send that data.

    Tuesday, November 30, 2010 3:50 PM
  • Simple cast doesn't work, that again returns a 2 byte char instead of the unprintable 1 byte.
    Tuesday, November 30, 2010 4:30 PM
  • I've tried forcing an Ansi encoding set, done conversion using Ansi set.  It seems to continue to force the 2 byte char.
    Tuesday, November 30, 2010 4:31 PM
  • Cast to byte instead of char.
    Tuesday, November 30, 2010 5:11 PM
  • Casting directly to a byte is simply returning the value of the input, not giving me byte data.
    Tuesday, November 30, 2010 10:12 PM
  • have tried:

     

    (char)

    (byte)

    Convert.ToChar

    Convert.ToByte

    changed encoding to Ascii, changed encoding to UTF-X

    System.Text.Encoding.Ascii

    System.Text.Encoding.Unicode

     

    and so on, every return value for values 0-31 is giving me " \(something)".

     

    is there no way to get a single return?  

     

    just tried 

     

        public static char Chr(byte src)
        {
          return (System.Text.Encoding.GetEncoding("iso-8859-1").GetChars(new byte[] { src })[0]);
        }

    which is also returning "\(something)"

     

    also tried 

                string laString = Strings.Chr(10).ToString();

                testByte = System.Text.Encoding.ASCII.GetBytes(newArray);

                string myStr13 = System.Text.Encoding.ASCII.GetString(myBytes13);


    same deal.

    • Edited by KevinMarsalla Tuesday, November 30, 2010 10:51 PM new stuff I tried
    Tuesday, November 30, 2010 10:26 PM
  • '\b' is a single character. As is 'a'.

    '\b' is a two-byte value. As is 'a'.

    Wednesday, December 1, 2010 1:21 AM
  • If you run the following program, the output is:

    Unicode: 31 0
    ANSI: 31

    Isn't that the desired result? There is only one byte being output for the ANSI version of a char with code 31:

    using System;
    using System.Text;
    
    namespace Demo
    {
      class Program
      {
        static void Main(string[] args)
        {
          char testChar = (char)31;
          string testString = new string(testChar, 1);
    
          byte[] asUnicode = Encoding.Unicode.GetBytes(testString);
          print("Unicode", asUnicode);
    
          byte[] asAnsi = Encoding.Default.GetBytes(testString);
          print("ANSI", asAnsi);
        }
    
        private static void print(string title, byte[] bytes)
        {
          Console.Write(title + ": ");
    
          foreach (byte b in bytes)
          {
            Console.Write(b + " ");
          }
    
          Console.WriteLine();
        }
      }
    }
    
    

    Wednesday, December 1, 2010 9:44 AM
  • Ok, let me try again.

    A simple program in VB6 that is basically doing what my C# program is doing.

    Private Sub Command1_Click()
    Dim shutdownStr As String
    
    Dim shutdownByteArray(1 To 10) As Byte
    Dim idx As Integer
    idx = 1
    
    shutdownByteArray(1) = 2
    shutdownByteArray(2) = 3
    shutdownByteArray(3) = 4
    shutdownByteArray(4) = 8
    shutdownByteArray(5) = 13
    shutdownByteArray(6) = 18
    shutdownByteArray(7) = 31
    shutdownByteArray(8) = 11
    shutdownByteArray(9) = 16
    shutdownByteArray(10) = 18
    
    While (idx < 10)
      shutdownStr = shutdownStr + chr(shutdownByteArray(idx))
      idx = idx + 1
    Wend
    
    MsgBox (shutdownStr)
    
    End Sub
    
    
    When I breakpoint shutdownStr and paste the value of shutdownStr into Notepad++ and convert to HEX-16 it looks like:

    "000000000  22 02 03 04 08 20 12 1F-0B 10 22 0D 0A 0D 0A 22   |.  ......|"

    the characters in the string are not showing, but they are:
    .[stx][etx][eot][bs] [dc2][us][vt][dle]


    When I do the same thing in C# I get:
          string shutdownStr = null;
    
          byte[] shutdownByteArray = new byte[10];
          int idx;
    
          idx = 0;
    
          shutdownByteArray[0] = 2;
          shutdownByteArray[1] = 3;
          shutdownByteArray[2] = 4;
          shutdownByteArray[3] = 8;
          shutdownByteArray[4] = 13;
          shutdownByteArray[5] = 18;
          shutdownByteArray[6] = 31;
          shutdownByteArray[7] = 11;
          shutdownByteArray[8] = 16;
          shutdownByteArray[9] = 18;
    
          while (idx < 10)
          {
            shutdownStr = shutdownStr + Strings.Chr(shutdownByteArray[idx]);
            idx = idx + 1;
          }
          
    
          MessageBox.Show(shutdownStr);


    "000000010  02 03 04 5C 62 5C 72 12-1F 5C 76 10 12 22         |\b\r\v.  |"
    again, the "unprintable" chars are not showing, but I am getting
    [stx][etx][eot]\b\r[dc2][us]\v[dle][dc2].

    the trouble is coming from the \b \r \v \whatevers.

    the [thing] is a single block, black background white text thing, cannot edit it.  I don't have a better description than that besides to copy the code and see the output for yourself.

    Wednesday, December 1, 2010 2:25 PM
  • Well you're not using Encoding.Default as per my example above. You should try that.

    You're running into problems because you're using a unicode string to store ascii characters - and of course it doesn't work. All strings in C# (and VB for .Net) are utf16.

    You don't show us what you're doing with the string once you've constructed it...

    However, what happens if you try this:

    Instead of:

     while (idx < 10)
     {
     shutdownStr = shutdownStr + Strings.Chr(shutdownByteArray[idx]);
     idx = idx + 1;
     }
    

    Try this:

    shutdownStr = Encoding.Default.GetString(shutdownByteArray);
    
    • Marked as answer by Alan_chen Thursday, December 9, 2010 1:25 AM
    Wednesday, December 1, 2010 3:51 PM
  • If I understand correctly, you copy the value shown by the debugger, including the escaped characters. The problem doesn't come from the string. It comes from the way you put it in Notepad++.

    Save it in a file, and open the file in Notepad++ and you should get the bytes you're expecting.

    Wednesday, December 1, 2010 3:57 PM
  • Thanks for all the help guys.  I am just going to rewrite the comm section to return the byte instead of a char that needs to be encoded/decoded.
    • Marked as answer by Alan_chen Thursday, December 9, 2010 1:25 AM
    Wednesday, December 1, 2010 6:14 PM