3

I have a 2D array that I need to be able to convert to a string representation and back to array format. I would like to create a generci method that will handle any array 1d, 2d, 3d etc. so I can reuse the method in future.

What is the best way of going about this?

string[,] _array = new string[_helpTextItemNames.Count, 2];
1
  • That isn't a bad idea can you give any more details? Commented Sep 4, 2010 at 14:59

3 Answers 3

2

If you do not care to much about the structure of the string then the SoapFormatter is an option. Here is a quick and dirty example. Not pretty but it might work for you.

public static class Helpers
{    
  public static string ObjectToString(Array ar)
  {      
    using (MemoryStream ms = new MemoryStream())
    {
      SoapFormatter formatter = new SoapFormatter();
      formatter.Serialize(ms, ar);
      return Encoding.UTF8.GetString(ms.ToArray());
    }
  }

  public static object ObjectFromString(string s)
  {
    using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(s)))
    {
      SoapFormatter formatter = new SoapFormatter();
      return formatter.Deserialize(ms) as Array;
    }
  }

  public static T ObjectFromString<T>(string s)
  {
    return (T)Helpers.ObjectFromString(s);
  }
}

These helpers can be used to transform any Serializable object to a string, including arrays, as long as the elements of the array are serializable.

  // Serialize a 1 dimensional array to a string format
  char[] ar = { '1', '2', '3' };
  Console.WriteLine(Helpers.ObjectToString(ar));

  // Serialize a 2 dimensional array to a string format
  char[,] ar2 = {{ '1', '2', '3' },{ 'a', 'b', 'c' }};
  Console.WriteLine(Helpers.ObjectToString(ar2));

  // Deserialize an array from the string format
  char[,] ar3 = Helpers.ObjectFromString(Helpers.ObjectToString(ar2)) as char[,];
  char[,] ar4 = Helpers.ObjectFromString<char[,]>(Helpers.ObjectToString(ar2));
Sign up to request clarification or add additional context in comments.

3 Comments

@Burt, you need to add a reference to the 'System.Runtime.Serialization.Formatters.Soap' Assembly. Guess you found it :)
Yea :) Just trying out your solution now. Not sure if I will get away with the format but will give it a shot.
This worked I am going to keep the question openb for a while to see if anyone comes up with anything else. Thanks for the help.
1

If you want to determain your own format, the hard part is just walking a rectangular array because Array.GetValue and Array.SetValue expect a specific form. Here is StringFromArray, I'll leave ArrayFromString as an exercise (it's just the reverse with a little parsing). Note that the code below only works on rectangular arrays. If you want to support jagged arrays, that's completely different, but at least much simpler. You can tell if an array is jagged by checking array.GetType() for Array. It also doesn't support arrays whos lower-bounds is anything other than zero. For C# that doesn't mean anything, but it does mean that it may not work as a general library to be used from other languages. This can be fixed, but it's not worth the price of admission IMO. [deleted explative about non-zero-based arrays]

The format used here is simple: [num dimensions]:[length dimension #1]:[length dimension #2]:[...]:[[string length]:string value][[string length]:string value][...]

static string StringFromArray(Array array)
{
    int rank = array.Rank;
    int[] lengths = new int[rank];
    StringBuilder sb = new StringBuilder();
    sb.Append(array.Rank.ToString());
    sb.Append(':');
    for (int dimension = 0; dimension < rank; dimension++)
    {
        if (array.GetLowerBound(dimension) != 0)
            throw new NotSupportedException("Only zero-indexed arrays are supported.");
        int length = array.GetLength(dimension);
        lengths[dimension] = length;
        sb.Append(length);
        sb.Append(':');
    }

    int[] indices = new int[rank];
    bool notDone = true;
    NextRank:
    while (notDone)
    {
        notDone = false;

        string valueString = (array.GetValue(indices) ?? String.Empty).ToString();
        sb.Append(valueString.Length);
        sb.Append(':');
        sb.Append(valueString);

        for (int j = rank - 1; j > -1; j--)
        {
            if (indices[j] < (lengths[j] - 1))
            {
                indices[j]++;
                if (j < (rank - 1))
                {
                    for (int m = j + 1; m < rank; m++)
                        indices[m] = 0;
                }
                notDone = true;
                goto NextRank;
            }
        }

    }
    return sb.ToString();
}

Comments

1

As I know, you have a 2d array[n cols x n rows]. And you want convert it to string, and after that you'd like to convert this string back in to a 2d array. I have an idea as follow:

    //The first method is convert matrix to string
     private void Matrix_to_String()
            {
                String myStr = "";
                Int numRow, numCol;//number of rows and columns of the Matrix
                for (int i = 0; i < numRow; i++)
                {
                    for (int j = 0; j < numCol; j++)
                    {
    //In case you want display this string on a textbox in a form 
    //a b c d . . . .
    //e f g h . . . .
    //i j k l . . . .
    //m n o p . . . .
    //. . . . . . . . 

                       textbox.Text = textbox.Text + " " + Matrix[i,j];
                        if ((j == numCol-1) && (i != numRow-1))
                        {
                            textbox.Text = textbox.Text + Environment.NewLine;
                        }
                    }

                }
    myStr = textbox.text;
    myStr = myStr.Replace(" ", String.Empty);
    myStr = myStr.Replace(Environment.NewLine,String.Empty);
            }

//and the second method convert string back into 2d array

    private void String_to_Matrix()
            {
                int currentPosition = 0;
                Int numRow, numCol;//number of rows and columns of the Matrix
                string Str2 = textbox.Text;

                Str2 = Str2 .Replace(" ", string.Empty);
                Str2 = Str2 .Replace(Environment.NewLine, string.Empty);

                for (int k = 0; k < numRow && currentPosition < Str2 .Length; k++)
                {
                    for (int l = 0; l < numCol && currentPosition < Str2 .Length; l++)
                    {
                        char chr = Str2 [currentPosition];

                            Matrix[k, l] = chr ;                       

                        currentPosition++;
                    }
                }  

            }

Hope this help!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.