Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Serialization C#&;T-SQL字符串[]打包/解包实用程序函数_Serialization - Fatal编程技术网

Serialization C#&;T-SQL字符串[]打包/解包实用程序函数

Serialization C#&;T-SQL字符串[]打包/解包实用程序函数,serialization,Serialization,熟悉t-sql的任何人都可以为这些C#数组打包和解包实用程序方法创建表值函数,这些方法通过往返编码转义分隔符并保留空数组、空数组和空数组吗 通过将任何种类的字符串数组打包到一个字符串中,您可以将这些(小)数组作为参数传递给SQL,这在某些情况下非常有用 static class ArrayUtil { public static string Pack(string[] original) { return Pack(original, '|', '0', '~'

熟悉t-sql的任何人都可以为这些C#数组打包和解包实用程序方法创建表值函数,这些方法通过往返编码转义分隔符并保留空数组、空数组和空数组吗

通过将任何种类的字符串数组打包到一个字符串中,您可以将这些(小)数组作为参数传递给SQL,这在某些情况下非常有用

static class ArrayUtil
{
    public static string Pack(string[] original)
    {
        return Pack(original, '|', '0', '~');
    }

    public static string[] Unpack(string original)
    {
        return Unpack(original, '|', '0', '~');
    }

    public static string Pack(string[] original, char delimiter, char zed, char escape)
    {
        if (delimiter == escape ||
            zed == escape ||
            delimiter == zed) throw new ArgumentException("special characters must be distinct");

        // Null array returns a null string
        if (original == null) return null;

        // Empty array returns an empty string
        if (original.Length == 0) return string.Empty;

        // Arrays with a single empty element are represented as just the escape character
        // to differentiate from an empty array
        if (original.Length == 1 && original[0] == string.Empty) return escape.ToString();

        // Otherwise
        StringBuilder sb = new StringBuilder();

        for (int i = 0, ol = original.Length; i < ol; i++)
        {
            string s = original[i];

            if (s == null)
            {
                sb.Append(zed); // zed == null
            }
            else
            {
                for (int j = 0, sl = s.Length; j < sl; j++)
                {
                    char c = s[j];

                    // escape literal delimiters, escapes, and leading zeds
                    if (c == delimiter ||
                        c == escape ||
                        (c == zed && j == 0)) sb.Append(escape);

                    sb.Append(c);
                }
            }

            if (i != ol - 1) sb.Append(delimiter); // no trailing delimiter
        }

        return sb.ToString();
    }

    public static string[] Unpack(string original, char delimiter, char zed, char escape)
    {
        if (delimiter == escape ||
            zed == escape ||
            delimiter == zed) throw new ArgumentException("special characters must be distinct");

        // Null string returns a null array
        if (original == null) return null;

        // Empty string returns an empty array
        if (original == string.Empty) return new string[] { };

        // A single escape character represents an array with a single empty element
        // to differentiate from an empty array
        if (original == escape.ToString()) return new string[] { string.Empty };

        // Otherwise
        StringBuilder sb = new StringBuilder(); // A place to store the current element
        StringReader sr = new StringReader(original); // A stream of the original string
        List<string> unpacked = new List<string>(); // The finished elements
        int next;

        while ((next = sr.Read()) >= 0)
        {
            char c = (char)next;

            if (c == zed && sb.Length == 0)
            {
                unpacked.Add(null);

                if ((next = sr.Peek()) >= 0 && (char)next != delimiter)
                    throw new ArgumentException("An element's leading zed character must be escaped or must alone be the element", "original");

                sb = null;
            }
            else if (c == delimiter)
            {
                if (sb != null) unpacked.Add(sb.ToString());

                sb = new StringBuilder();
            }
            else if (c == escape)
            {
                if ((next = sr.Read()) >= 0)
                {
                    sb.Append((char)next);
                }
                else
                    throw new ArgumentException("Escapee expected", "original");
            }
            else
            {
                sb.Append(c);
            }
        }

        // A final zed character will make sb = null, but otherwise we have an additional element
        if (sb != null) unpacked.Add(sb.ToString());

        return unpacked.ToArray();
    }
}
一些特殊情况(由PEX发现)


下面是T-SQL解包的一个尝试:

CREATE FUNCTION [dbo].[UnpackStrings]
(
      @original nvarchar(4000), 
      @delimiter nchar(1),
      @zed nchar(1),
      @escape nchar(1)
)
RETURNS 
@unpacked TABLE 
(
      elementNumber INT IDENTITY(1,1), 
      element nvarchar(4000)
)
AS
BEGIN
      DECLARE @next int;
      DECLARE @c nchar(1);
      DECLARE @pos int;
      DECLARE @sb nvarchar(4000);

      -- Special characters must be distinct.
      IF ( (@delimiter = @escape) OR 
             (@zed = @escape) OR 
             (@delimiter = @zed) )
            RETURN;
      -- Null string return a null array
      IF (@original IS NULL)
            RETURN;
      -- A single escape character represents an array with a single 
      -- empty element to differentiate from an empty array.
      IF (@original = @escape)
      BEGIN
            INSERT @unpacked (element) VALUES ('');
            RETURN;
      END
      -- Otherwise read through the string and unpack.
      SET @pos = 1;
      SET @sb = '';
      SET @next = 0;
      -- Fill the table variable with the rows for your result set
      WHILE(  (@pos <= LEN(@original)) AND @next IS NOT NULL )
      BEGIN
            SET @next = UNICODE(SUBSTRING(@original, @pos, 1));
            IF (@next IS NULL)
            BEGIN
                  IF (LEN(@sb) > 0)
                        INSERT @unpacked (element) VALUES (@sb);
                        SET @sb = '';
                  CONTINUE;
            END
            ELSE
            BEGIN
                  SET @c = NCHAR(@next);
                  IF ( @c = @zed AND (LEN(@sb) = 0 OR LEN(@sb) IS NULL) )
                  BEGIN
                        INSERT @unpacked (element) VALUES (NULL);
                        -- need to peek at next character,
                        SET @next = UNICODE(SUBSTRING(@original, @pos+1, 1));
                        IF (@next IS NOT NULL)
                        BEGIN
                              SET @c = NCHAR(@next);
                              IF ( @c != @delimiter )
                              BEGIN
                                    -- Peek at next character and it not delimiter,
                                    -- bad format encountered.
                                    BREAK;
                              END
                        END                     
                        SET @sb = NULL;
                  END
                  ELSE
                  BEGIN
                        IF ( @c = @delimiter )
                        BEGIN
                              IF (LEN(@sb) > 0 )
                                    INSERT @unpacked (element) VALUES (@sb);
                              SET @sb = '';
                        END
                        ELSE
                        BEGIN
                              IF ( @c = @escape )
                              BEGIN
                                    SET @pos = @pos + 1;
                                    SET @next = UNICODE(SUBSTRING(@original, @pos, 1));
                                    IF (@next IS NULL )
                                    BEGIN
                                          CONTINUE;
                                    END
                                    ELSE 
                                    BEGIN 
                                          SET @sb =  @sb +  NCHAR(@next);
                                    END
                              END
                              ELSE
                              BEGIN
                                    SET @sb =  @sb + @c; 
                              END 
                        END
                  END
                  --
            END
            SET @pos = @pos + 1;
      END   
      --
      -- Likely not needed.  This is handled above.
      --
      -- A final zed character will made sb = null,
      -- but otherwise we have an additional element.
      IF (@sb IS NOT NULL )
            INSERT @unpacked (element) VALUES (@sb);

      RETURN 
END
CREATE函数[dbo].[unpack字符串]
(
@原始nvarchar(4000),
@分隔符nchar(1),
@zed nchar(1),
@逃逸中心(1)
)
返回
@未打包的桌子
(
元素编号整数标识(1,1),
元素nvarchar(4000)
)
作为
开始
声明@next int;
声明@c nchar(1);
声明@pos int;
宣布@sb nvarchar(4000);
--特殊字符必须是不同的。
如果(@delimiter=@escape)或
(@zed=@escape)或
(@delimiter=@zed))
返回;
--空字符串返回空数组
如果(@original为空)
返回;
--单个转义字符表示具有单个
--空元素以区别于空数组。
如果(@original=@escape)
开始
插入@未包装(元素)值(“”);
返回;
结束
--否则,请通读字符串并解压缩。
设置@pos=1;
设置@sb='';
设置@next=0;
--用结果集的行填充表变量
而(@pos 0)
插入@unpacket(元素)值(@sb);
设置@sb='';
继续;
结束
其他的
开始
设置@c=NCHAR(@next);
如果(@c=@zed和(LEN(@sb)=0或LEN(@sb)为空))
开始
插入@unpacket(元素)值(NULL);
--需要偷看下一个角色,
设置@next=UNICODE(子字符串(@original,@pos+1,1));
IF(@next不为空)
开始
设置@c=NCHAR(@next);
IF(@c!=@分隔符)
开始
--看下一个字符,它不是分隔符,
--遇到错误的格式。
打破
结束
结束
设置@sb=NULL;
结束
其他的
开始
IF(@c=@delimiter)
开始
如果(LEN(@sb)>0)
插入@unpacket(元素)值(@sb);
设置@sb='';
结束
其他的
开始
IF(@c=@escape)
开始
设置@pos=@pos+1;
设置@next=UNICODE(子字符串(@original,@pos,1));
如果(@next为空)
开始
继续;
结束
其他的
开始
设置@sb=@sb+NCHAR(@next);
结束
结束
其他的
开始
设置@sb=@sb+@c;
结束
结束
结束
--
结束
设置@pos=@pos+1;
结束
--
--可能不需要。这在上面处理。
--
--最后一个zed字符将使sb=null,
--但除此之外,我们还有一个额外的因素。
如果(@sb不为空)
插入@unpacket(元素)值(@sb);
返回
结束

这是一个小错误。这里更新了GIST:,并改进了C#
null -> null
[null] -> "0"
[null, null] -> "0|0"
[] -> ""
[""] -> "~"
["", ""] -> "|"
["|", "|"] -> "~||~|"
CREATE FUNCTION [dbo].[UnpackStrings]
(
      @original nvarchar(4000), 
      @delimiter nchar(1),
      @zed nchar(1),
      @escape nchar(1)
)
RETURNS 
@unpacked TABLE 
(
      elementNumber INT IDENTITY(1,1), 
      element nvarchar(4000)
)
AS
BEGIN
      DECLARE @next int;
      DECLARE @c nchar(1);
      DECLARE @pos int;
      DECLARE @sb nvarchar(4000);

      -- Special characters must be distinct.
      IF ( (@delimiter = @escape) OR 
             (@zed = @escape) OR 
             (@delimiter = @zed) )
            RETURN;
      -- Null string return a null array
      IF (@original IS NULL)
            RETURN;
      -- A single escape character represents an array with a single 
      -- empty element to differentiate from an empty array.
      IF (@original = @escape)
      BEGIN
            INSERT @unpacked (element) VALUES ('');
            RETURN;
      END
      -- Otherwise read through the string and unpack.
      SET @pos = 1;
      SET @sb = '';
      SET @next = 0;
      -- Fill the table variable with the rows for your result set
      WHILE(  (@pos <= LEN(@original)) AND @next IS NOT NULL )
      BEGIN
            SET @next = UNICODE(SUBSTRING(@original, @pos, 1));
            IF (@next IS NULL)
            BEGIN
                  IF (LEN(@sb) > 0)
                        INSERT @unpacked (element) VALUES (@sb);
                        SET @sb = '';
                  CONTINUE;
            END
            ELSE
            BEGIN
                  SET @c = NCHAR(@next);
                  IF ( @c = @zed AND (LEN(@sb) = 0 OR LEN(@sb) IS NULL) )
                  BEGIN
                        INSERT @unpacked (element) VALUES (NULL);
                        -- need to peek at next character,
                        SET @next = UNICODE(SUBSTRING(@original, @pos+1, 1));
                        IF (@next IS NOT NULL)
                        BEGIN
                              SET @c = NCHAR(@next);
                              IF ( @c != @delimiter )
                              BEGIN
                                    -- Peek at next character and it not delimiter,
                                    -- bad format encountered.
                                    BREAK;
                              END
                        END                     
                        SET @sb = NULL;
                  END
                  ELSE
                  BEGIN
                        IF ( @c = @delimiter )
                        BEGIN
                              IF (LEN(@sb) > 0 )
                                    INSERT @unpacked (element) VALUES (@sb);
                              SET @sb = '';
                        END
                        ELSE
                        BEGIN
                              IF ( @c = @escape )
                              BEGIN
                                    SET @pos = @pos + 1;
                                    SET @next = UNICODE(SUBSTRING(@original, @pos, 1));
                                    IF (@next IS NULL )
                                    BEGIN
                                          CONTINUE;
                                    END
                                    ELSE 
                                    BEGIN 
                                          SET @sb =  @sb +  NCHAR(@next);
                                    END
                              END
                              ELSE
                              BEGIN
                                    SET @sb =  @sb + @c; 
                              END 
                        END
                  END
                  --
            END
            SET @pos = @pos + 1;
      END   
      --
      -- Likely not needed.  This is handled above.
      --
      -- A final zed character will made sb = null,
      -- but otherwise we have an additional element.
      IF (@sb IS NOT NULL )
            INSERT @unpacked (element) VALUES (@sb);

      RETURN 
END