Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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
C# 从控制台C上的位置读取#_C#_Console - Fatal编程技术网

C# 从控制台C上的位置读取#

C# 从控制台C上的位置读取#,c#,console,C#,Console,我需要从控制台中的特定位置读取文本,例如5,5 如果我需要写信到这个位置,它只会是: Console.SetCursorPosition(5, 5); Console.Write("My text"); 有没有什么方法可以让我以类似的方式阅读 我想澄清一下: 我不想停下来接受用户的输入,即使输入不是来自用户,也有可能是以前打印出来的。我真的想要一些: Console.GetCharAtLocation(5,5)或类似功能。此功能不存在。从理论上讲,您可以覆盖控制台上的输入和输出流,以保留您自己

我需要从控制台中的特定位置读取文本,例如5,5

如果我需要写信到这个位置,它只会是:

Console.SetCursorPosition(5, 5);
Console.Write("My text");
有没有什么方法可以让我以类似的方式阅读

我想澄清一下: 我不想停下来接受用户的输入,即使输入不是来自用户,也有可能是以前打印出来的。我真的想要一些:
Console.GetCharAtLocation(5,5)或类似功能。

此功能不存在。从理论上讲,您可以覆盖控制台上的输入和输出流,以保留您自己可以读取的控制台缓冲区副本,但这并不简单(并且可能不支持所有边缘情况,例如外部程序挂接到控制台并对其进行读写).

此功能不存在。从理论上讲,您可以覆盖控制台上的输入和输出流,以保留您自己可以读取的控制台缓冲区副本,但这并不简单(并且可能无法支持所有边缘情况,例如外部程序挂接到控制台并对其进行读写)。

关于:

class Program {
    static void Main( string[ ] args ) {
        CustomizedConsole.WriteLine( "Lorem Ipsum" ); //Lorem Ipsum
        Console.WriteLine( CustomizedConsole.ReadContent( 6, 5 ) ); //Ipsum
        Console.WriteLine( CustomizedConsole.GetCharAtLocation( 0, 0 ) ); //L
    }
}

static class CustomizedConsole {
    private static List<char> buffer = new List<char>();
    private static int lineCharCount = 0;

    public static void Write(string s){
        lineCharCount += s.Length;
        buffer.AddRange( s );
        Console.Write( s );
    }

    public static void WriteLine(string s ) {
        for ( int i = 0; i < Console.BufferWidth - lineCharCount - s.Length; i++ )
            s += " ";

        buffer.AddRange( s );
        Console.WriteLine( s );
        lineCharCount = 0;
    }

    public static string ReadContent( int index, int count ) {
        return new String(buffer.Skip( index ).Take( count ).ToArray());
    }

    public static char GetCharAtLocation( int x, int y ) {
        return buffer[ Console.BufferHeight * x + y ];
    }
}
类程序{
静态void Main(字符串[]参数){
CustomizedConsole.WriteLine(“Lorem Ipsum”);//Lorem Ipsum
Console.WriteLine(CustomizedConsole.ReadContent(6,5));//Ipsum
Console.WriteLine(CustomizedConsole.GetCharAtLocation(0,0));//L
}
}
静态类定制控制台{
私有静态列表缓冲区=新列表();
私有静态int-lineCharCount=0;
公共静态无效写入(字符串s){
lineCharCount+=s.长度;
缓冲区。添加范围;
控制台。写入;
}
公共静态无效写线(字符串s){
对于(int i=0;i
编辑:

正如其他人所说,这只是一个微不足道的案例,还有很多其他方面需要改进。但我写这篇文章只是作为一个起点。

关于:

class Program {
    static void Main( string[ ] args ) {
        CustomizedConsole.WriteLine( "Lorem Ipsum" ); //Lorem Ipsum
        Console.WriteLine( CustomizedConsole.ReadContent( 6, 5 ) ); //Ipsum
        Console.WriteLine( CustomizedConsole.GetCharAtLocation( 0, 0 ) ); //L
    }
}

static class CustomizedConsole {
    private static List<char> buffer = new List<char>();
    private static int lineCharCount = 0;

    public static void Write(string s){
        lineCharCount += s.Length;
        buffer.AddRange( s );
        Console.Write( s );
    }

    public static void WriteLine(string s ) {
        for ( int i = 0; i < Console.BufferWidth - lineCharCount - s.Length; i++ )
            s += " ";

        buffer.AddRange( s );
        Console.WriteLine( s );
        lineCharCount = 0;
    }

    public static string ReadContent( int index, int count ) {
        return new String(buffer.Skip( index ).Take( count ).ToArray());
    }

    public static char GetCharAtLocation( int x, int y ) {
        return buffer[ Console.BufferHeight * x + y ];
    }
}
类程序{
静态void Main(字符串[]参数){
CustomizedConsole.WriteLine(“Lorem Ipsum”);//Lorem Ipsum
Console.WriteLine(CustomizedConsole.ReadContent(6,5));//Ipsum
Console.WriteLine(CustomizedConsole.GetCharAtLocation(0,0));//L
}
}
静态类定制控制台{
私有静态列表缓冲区=新列表();
私有静态int-lineCharCount=0;
公共静态无效写入(字符串s){
lineCharCount+=s.长度;
缓冲区。添加范围;
控制台。写入;
}
公共静态无效写线(字符串s){
对于(int i=0;i
编辑:


正如其他人所说,这只是一个微不足道的案例,还有很多其他方面需要改进。但我写这篇文章只是作为一个起点。

正如@Servy所说,没有任何内置功能(我知道或可以找到)可以做你想要的。然而,有一个解决办法(这是一个有点黑客,但它的工作)

您可以在内存或磁盘上创建自己的缓冲区。无论何时输出到控制台,也要输出到缓冲区。然后,您可以使用缓冲区以控制台无法使用的方式进行读取

缓冲区有两种方式:在磁盘上或在内存中。您可以使用
Console.BufferWidth
Console.BufferHeight
属性来查找缓冲区大小。我发现在内存中使用字符串数组更简单(每个字符串都是一行输出,如果我没记错的话,数组中有许多字符串等于
缓冲区高度
)。一位同事最后在磁盘上做了同样的事情

您需要创建一个方法来替换
Console.Write
Console.WriteLine
,以便可以同时写入两个缓冲区。比如:

public void MyWrite( string output ) {
    Console.Write( output );
    Array.Write( output );  // obvious pseudo-code
}

我发现围绕数组包装一个类并实现支持它的方法很有帮助。。。然后,您可以实现您的
GetCharAtLocation(inti,intj)
方法,以及您需要的任何其他功能。

正如@Servy所述,没有任何内置功能(我知道或可以找到)可以实现您想要的功能。然而,有一个解决办法(这是一个有点黑客,但它的工作)

您可以在内存或磁盘上创建自己的缓冲区。无论何时输出到控制台,也要输出到缓冲区。然后,您可以使用缓冲区以控制台无法使用的方式进行读取

缓冲区有两种方式:在磁盘上或在内存中。您可以使用
Console.BufferWidth
Console.BufferHeight
属性来查找缓冲区大小。我发现在内存中使用字符串数组更简单(每个字符串都是一行输出,如果我没记错的话,数组中有许多字符串等于
缓冲区高度
)。一位同事最后在磁盘上做了同样的事情

您需要创建一个方法来替换
Console.Write
Console.WriteL
public class ConsoleReader
{
    public static IEnumerable<string> ReadFromBuffer(short x, short y, short width, short height)
    {
        IntPtr buffer = Marshal.AllocHGlobal(width * height * Marshal.SizeOf(typeof(CHAR_INFO)));
        if (buffer == null)
            throw new OutOfMemoryException();

        try
        {
            COORD coord = new COORD();
            SMALL_RECT rc = new SMALL_RECT();
            rc.Left = x;
            rc.Top = y;
            rc.Right = (short)(x + width - 1);
            rc.Bottom = (short)(y + height - 1);

            COORD size = new COORD();
            size.X = width;
            size.Y = height;

            const int STD_OUTPUT_HANDLE = -11;
            if (!ReadConsoleOutput(GetStdHandle(STD_OUTPUT_HANDLE), buffer, size, coord, ref rc))
            {
                // 'Not enough storage is available to process this command' may be raised for buffer size > 64K (see ReadConsoleOutput doc.)
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            IntPtr ptr = buffer;
            for (int h = 0; h < height; h++)
            {
                StringBuilder sb = new StringBuilder();
                for (int w = 0; w < width; w++)
                {
                    CHAR_INFO ci = (CHAR_INFO)Marshal.PtrToStructure(ptr, typeof(CHAR_INFO));
                    char[] chars = Console.OutputEncoding.GetChars(ci.charData);
                    sb.Append(chars[0]);
                    ptr += Marshal.SizeOf(typeof(CHAR_INFO));
                }
                yield return sb.ToString();
            }
        }
        finally
        {
            Marshal.FreeHGlobal(buffer);
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct CHAR_INFO
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
        public byte[] charData;
        public short attributes;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct COORD
    {
        public short X;
        public short Y;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct SMALL_RECT
    {
        public short Left;
        public short Top;
        public short Right;
        public short Bottom;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct CONSOLE_SCREEN_BUFFER_INFO
    {
        public COORD dwSize;
        public COORD dwCursorPosition;
        public short wAttributes;
        public SMALL_RECT srWindow;
        public COORD dwMaximumWindowSize;
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool ReadConsoleOutput(IntPtr hConsoleOutput, IntPtr lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, ref SMALL_RECT lpReadRegion);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr GetStdHandle(int nStdHandle);
}
static void Populate_Console()
{
    Console.Clear();
    Console.Write(@"
 ┌───────┐
1│C D E F│
2│G H I J│
3│K L M N│
4│O P Q R│
 └───────┘
  2 4 6 8          ".Trim());
}
[DllImport("kernel32", SetLastError = true)]
static extern IntPtr GetStdHandle(int num);
    [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
    [return: MarshalAs(UnmanagedType.Bool)] //   ̲┌──────────────────^
    static extern bool ReadConsoleOutputCharacterA(
        IntPtr hStdout,   // result of 'GetStdHandle(-11)'
        out byte ch,      // A̲N̲S̲I̲ character result
        uint c_in,        // (set to '1')
        uint coord_XY,    // screen location to read, X:loword, Y:hiword
        out uint c_out);  // (unwanted, discard)

    [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
    [return: MarshalAs(UnmanagedType.Bool)] //   ̲┌───────────────────^
    static extern bool ReadConsoleOutputCharacterW(
        IntPtr hStdout,   // result of 'GetStdHandle(-11)'
        out Char ch,      // U̲n̲i̲c̲o̲d̲e̲ character result
        uint c_in,        // (set to '1')
        uint coord_XY,    // screen location to read, X:loword, Y:hiword
        out uint c_out);  // (unwanted, discard)
static void Windows_Console_Readback()
{
    var stdout = GetStdHandle(-11);

    for (uint coord, y = 1; y <= 4; y++)
    {
        coord = (5 - y) * 2;        // loword  <-- X coord to read
        coord |= y << 16;           // hiword  <-- Y coord to read

        if (!ReadConsoleOutputCharacterA(
                stdout,
                out byte chAnsi,    // result: single ANSI char
                1,                  // # of chars to read
                coord,              // (X,Y) screen location to read (see above)
                out _))             // result: actual # of chars (unwanted)
            throw new Win32Exception();

        Console.Write(" " + (Char)chAnsi + " ");
    }
}