是否有与文本流相同的SetCursorPosition?

时间:2015-05-27 01:57:02

标签: c# .net

当输出到控制台时,您可以设置光标的特定位置并写入(或者使用其他漂亮的技巧,例如打印退格将带您回来。)

是否可以通过文本流完成类似的事情?

场景:我需要构建一个包含n个文本的字符串,其中每个文本可能位于不同的行和起始位置(或左上角和左上角)。
两个字符串可能出现在同一行上。

我可以用它构建一个简单的Dictionary<int, StringBuilder>和fidget,但是我想知道是否有类似于文本流的控制台功能,你可以写到特定的地方(行)和专栏)。

修改 这仅适用于文本。没有控制权 结果可能是一个包含多个新行的字符串,并且文本出现在不同的位置。

示例(.将为空格):

..... txt3....... txt2
......................  
................ txt1.

这将是{3}列(无论如何)txt1txt2txt3以及行1具有不同列值的结果(txt3列&lt; txt2 colmun)

2 个答案:

答案 0 :(得分:1)

在等待更好的答案时,这是我的解决方案。似乎工作,经过轻微测试,可以简单地粘贴到linqpad并运行。

void Main()
{
    m_dict = new SortedDictionary<int, StringBuilder>();

    AddTextAt(1,40, "first");
    AddTextAt(2,40, "xx");
    AddTextAt(0,10, "second");
    AddTextAt(4,5, "third");
    AddTextAt(1,15, "four");

    GetStringFromDictionary().Dump();
}

// "global" variable
SortedDictionary<int, StringBuilder> m_dict;

/// <summary>
/// This will emulate writting to the console, where you can set the row/column and put your text there.
/// It's done by having Dictionary(int,StringBuilder) that will use to store our data, and eventually, 
/// when we need the string iterate over it and build our final representation.
/// </summary>
private void AddTextAt(int row, int column, string text)
{
    StringBuilder sb;

    // NB: The following will initialize the string builder !!
    // Dictionary doesn't have an entry for this row, add it and all the ones before it
    if (!m_dict.TryGetValue(row, out sb))
    {
            int start = m_dict.Keys.Any() ? m_dict.Keys.Last() +1 : 0;
        for (int i = start ; i <= row; i++)
        {
            m_dict.Add(i, null);
        }
    } 

    int leftPad = column + text.Length;
    // If dictionary doesn't have a value for this row, just create a StringBuilder with as many
    // columns as left padding, and then the text
    if (sb == null)
    {
        sb = new StringBuilder(text.PadLeft(leftPad));
        m_dict[row] = sb;
    }
    // If it does have a value:
    else
    {
        // If the new string is to be to the "right" of the current text, append with proper padding
        // (column - current string builder length) and the text
        int currrentSbLength = sb.ToString().Length;
        if (column >= currrentSbLength)
        {
            leftPad = column - currrentSbLength + text.Length;
            sb.Append(text.PadLeft(leftPad));
        }
        // otherwise, text goes on the "left", create a new string builder with padding and text, and 
        // append the older one at the end (with proper padding?)
        else
        {
            m_dict[row] = new StringBuilder(  text.PadLeft(leftPad)
                                            + sb.ToString().Substring(leftPad) );
        }
    }
}

/// <summary>
/// Concatenates all the strings from the private dictionary, to get a representation of the final string.
/// </summary>
private string GetStringFromDictionary()
{
    var sb = new StringBuilder();
    foreach (var k in m_dict.Keys)
    {
            if (m_dict[k]!=null)
            sb.AppendLine(m_dict[k].ToString());
            else
                sb.AppendLine();
    }
    return sb.ToString();
}

输出:

          second
               four                     first
                                        xx

     third

答案 1 :(得分:0)

没有。文本文件实际上没有水平/垂直位置的概念,因此您需要自己构建某种定位。

对于基本定位标签("\t")可能就足够了,对于任何更高级的标签,您需要用空格填充空白区域。

听起来你有某种表布局 - 首先在单元格中构建数据可能更容易(List<List<string>> - 由字符串列组成的行列表),而不是用{{1}格式化它或者为每个“单元格”手动添加必要数量的空格