在 C 中获取控制台缓冲区内容

发布于 2024-07-09 17:59:24 字数 154 浏览 5 评论 0原文

只是想知道是否有任何方法(在 C 中)获取控制台缓冲区的内容,最好是某种字符数组。 它将被写入一个文件,所以如果我错过了一些可以做到这一点的愚蠢的事情,那么请指出来。 它可以是 Windows 特定的。 我正在使用 MinGW(gcc 3.4.5)。

提前致谢。

Just wondering if there is any way (in C) to get the contents of the console buffer, preferably as some kind of char array. It is going to be written to a file, so if I am missing out on something stupid that will do exactly that, then point it out. It can be Windows-specific. I am using MinGW (gcc 3.4.5).

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

柠檬色的秋千 2024-07-16 17:59:24

我认为你需要看看 win32 控制台函数,例如 GetStdHandle()ReadConsoleOutput()< /a>、WriteConsoleOutput 等。

I think you need to take a look at win32 console functions for example GetStdHandle(), ReadConsoleOutput(), WriteConsoleOutput etc.

一百个冬季 2024-07-16 17:59:24

在 Win32 中,ReadConsoleOutput

从控制台屏幕缓冲区中的矩形字符单元格读取字符和颜色属性数据,然后该函数将数据写入目标缓冲区中指定位置的矩形块。

In Win32, ReadConsoleOutput:

Reads character and color attribute data from a rectangular block of character cells in a console screen buffer, and the function writes the data to a rectangular block at a specified location in the destination buffer.

つ低調成傷 2024-07-16 17:59:24

这是读取控制台缓冲区的方法。 GetNumCharsInConsoleBuffer 是获取控制台屏幕缓冲区中写入的总字符数,我使用 GetConsoleScreenBufferInfo 内。 之后,我创建一个动态分配的数组,其大小等于 GetNumCharsInConsoleBuffer 返回的先前值 + 1(用于零结尾)。 最后,ReadConsoleBuffer 将使用控制台屏幕缓冲区的内容填充刚刚创建的缓冲区。
之后,如果您想将缓冲区的内容写入文件,您可能需要进行一些格式化。 使用 ReadConsoleOutputCharacter,您获取控制台屏幕缓冲区的一个区域(矩形)。 您写入控制台屏幕缓冲区的行将用空格填充以适合缓冲区区域。 与win32 ReadConsoleOutput/WriteConsoleOutput 相同,您将获得屏幕的一个区域(矩形)。

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

DWORD GetNumCharsInConsoleBuffer()
{
    CONSOLE_SCREEN_BUFFER_INFO buffer_info = {0};
    if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &buffer_info) != FALSE)
        return (DWORD) ( (buffer_info.dwSize.X * ( buffer_info.dwCursorPosition.Y + 1)) - (buffer_info.dwSize.X - ( buffer_info.dwCursorPosition.X)) );
    else
        return 0;
}

DWORD ReadConsoleBuffer(char* buffer, DWORD bufsize)
{
    DWORD num_character_read = 0;
    COORD first_char_to_read = {0};
    if( ReadConsoleOutputCharacterA(GetStdHandle(STD_OUTPUT_HANDLE), buffer, bufsize, first_char_to_read, &num_character_read) != FALSE)
        buffer[bufsize-1] = '\0';
    else
        buffer[0] = '\0';

    return num_character_read;
}

int main(int argc, char** argv)
{
    fprintf(stdout, "Writting\nin\nthe\nbuffer\n");
    DWORD bufsize = GetNumCharsInConsoleBuffer();

    if(bufsize > 0)
    {
        bufsize++; // Add 1 for zero-ending char

        char* buffer = malloc(bufsize);
        memset(buffer, 0, bufsize);

        ReadConsoleBuffer(buffer, bufsize);  

        puts("\nBuffer contents:");
        puts(buffer);

        free(buffer);
    }

    system("pause"); 
    return 0;
}

输出:

Writting
in
the
buffer
Buffer contents:
Writting
in
the
buffer

Appuyez sur une touche pour continuer...

编辑:

我刚刚编写了一个函数,可用于将屏幕缓冲区的内容写入文件。 此函数从屏幕控制台缓冲区中删除填充的空格。
ReadConsoleBufferForFile 采用空字符指针作为第一个参数 (buffer),该参数将在执行期间分配。 所以不要忘记自己删除它。 ReadConsoleBufferForFile 将在第二个参数 (bufsize) 中写入缓冲区的大小。

#include <stdio.h>
#include <stdlib.h>
#include <crtdbg.h>
#include <Windows.h>

const char* ReadConsoleBufferForFile(char** buffer, size_t* bufsize)
{
    CONSOLE_SCREEN_BUFFER_INFO buffer_info = {0};
    if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &buffer_info) != FALSE )
    {
        size_t data_size = (size_t) ( (buffer_info.dwSize.X * ( buffer_info.dwCursorPosition.Y + 1)) - 
                                      (buffer_info.dwSize.X - ( buffer_info.dwCursorPosition.X + 1)) );

        if(data_size > 1)
        {
            char* data = malloc(data_size); //= new char[data_size];
            _ASSERTE(data != 0);

            DWORD num_char_read;
            COORD first_char_read = {0};
            if( ReadConsoleOutputCharacterA(GetStdHandle(STD_OUTPUT_HANDLE), data, data_size, first_char_read, &num_char_read) != FALSE )
            {
                data[data_size-1] = '\0';

                const char* const pbeg = &data[0];
                const char* const pend = &data[data_size-1];
                char* pcur, *pmem;

                const int line_size = buffer_info.dwSize.X;
                int line_count = buffer_info.dwCursorPosition.Y;

                if(buffer_info.dwCursorPosition.X > 0) // No new line char at the end of the last line, so no padded spaces. 
                {                    
                    if((line_count + 1) > 1)
                    {
                        pmem = &data[data_size - buffer_info.dwCursorPosition.X - 1];
                        pcur = (pmem - 1);
                    }
                    else // 1 line and no new line char(no padded spaces). Will no enters the loop.
                        pcur = &data[0];
                }
                else 
                {
                    pcur = &data[data_size-2];
                    pmem = 0;
                }
                
                if(pcur != pbeg)
                {
                    while(1)
                    {
                        line_count--;

                        while(*pcur == ' ') { pcur--; }
                        *(pcur + 1) = '\n'; // Padded spaces replaced by new line char.

                        if(!pmem) // first round. Add zero-ending char.
                            *(pcur + 2) = '\0'; 
                        else
                            memmove(pcur + 2, pmem, (pend - pmem) + 1);

                        if(line_count == 0)
                            break;

                        pmem = &data[line_count * line_size];
                        pcur = (pmem - 1);
                    }
                }

                *bufsize = strlen(data) + 1;
                 
                *buffer = malloc(*bufsize); //= new char[*bufsize];
                _ASSERTE(*buffer != 0);

                memcpy(*buffer, data, *bufsize);
                free(data); //delete[] data;
               
                pcur= *buffer;
                return pcur;
            }

            if(data)
                free(data); // delete[] data;
        }
    }
     
    *buffer = 0;
    return 0;
}


int main(int argc, char** argv)
{
    printf("Writting\nin\nthe\nbuffer");

    char* buffer;
    size_t size;  
    ReadConsoleBufferForFile(&buffer, &size);

    if(buffer)
    {
        freopen("out.txt", "w", stdout); 
        fprintf(stdout, buffer);
        free(buffer);
        fclose(stdout);
    }  
     
    return 0;
}

“out.txt”中的输出:

Writting
in
the
buffer

Here's a way to read the console buffer. GetNumCharsInConsoleBuffer is to get the total characters written in the console screen buffer, I use GetConsoleScreenBufferInfo inside. After, I create a dynamically allocated array of size equal to the previously value returned by GetNumCharsInConsoleBuffer + 1 (for zero-ending). And finally, ReadConsoleBuffer will fill the buffer just created with the contents of the console screen buffer.
After, if you want to write the contents of your buffer to a file, you'll probably need to do some formatting. With ReadConsoleOutputCharacter you get a region(rectangle) of the console screen buffer. The lines you wrote to the console screen buffer will be padded with spaces to fit the region of the buffer. it'll be the same with the win32 ReadConsoleOutput/WriteConsoleOutput, you'll get a region(rectangle) of your screen.

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

DWORD GetNumCharsInConsoleBuffer()
{
    CONSOLE_SCREEN_BUFFER_INFO buffer_info = {0};
    if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &buffer_info) != FALSE)
        return (DWORD) ( (buffer_info.dwSize.X * ( buffer_info.dwCursorPosition.Y + 1)) - (buffer_info.dwSize.X - ( buffer_info.dwCursorPosition.X)) );
    else
        return 0;
}

DWORD ReadConsoleBuffer(char* buffer, DWORD bufsize)
{
    DWORD num_character_read = 0;
    COORD first_char_to_read = {0};
    if( ReadConsoleOutputCharacterA(GetStdHandle(STD_OUTPUT_HANDLE), buffer, bufsize, first_char_to_read, &num_character_read) != FALSE)
        buffer[bufsize-1] = '\0';
    else
        buffer[0] = '\0';

    return num_character_read;
}

int main(int argc, char** argv)
{
    fprintf(stdout, "Writting\nin\nthe\nbuffer\n");
    DWORD bufsize = GetNumCharsInConsoleBuffer();

    if(bufsize > 0)
    {
        bufsize++; // Add 1 for zero-ending char

        char* buffer = malloc(bufsize);
        memset(buffer, 0, bufsize);

        ReadConsoleBuffer(buffer, bufsize);  

        puts("\nBuffer contents:");
        puts(buffer);

        free(buffer);
    }

    system("pause"); 
    return 0;
}

Output:

Writting
in
the
buffer
Buffer contents:
Writting
in
the
buffer

Appuyez sur une touche pour continuer...

EDIT:

I just wrote a function that can be used to write the contents of the screen buffer to file. This function removes the padded spaces from the screen console buffer.
ReadConsoleBufferForFile takes a null char pointer as first argument (buffer) that will be allocated during its execution. So don't forget to delete it by yourself. ReadConsoleBufferForFile will write the size of the buffer in the second argument (bufsize).

#include <stdio.h>
#include <stdlib.h>
#include <crtdbg.h>
#include <Windows.h>

const char* ReadConsoleBufferForFile(char** buffer, size_t* bufsize)
{
    CONSOLE_SCREEN_BUFFER_INFO buffer_info = {0};
    if( GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &buffer_info) != FALSE )
    {
        size_t data_size = (size_t) ( (buffer_info.dwSize.X * ( buffer_info.dwCursorPosition.Y + 1)) - 
                                      (buffer_info.dwSize.X - ( buffer_info.dwCursorPosition.X + 1)) );

        if(data_size > 1)
        {
            char* data = malloc(data_size); //= new char[data_size];
            _ASSERTE(data != 0);

            DWORD num_char_read;
            COORD first_char_read = {0};
            if( ReadConsoleOutputCharacterA(GetStdHandle(STD_OUTPUT_HANDLE), data, data_size, first_char_read, &num_char_read) != FALSE )
            {
                data[data_size-1] = '\0';

                const char* const pbeg = &data[0];
                const char* const pend = &data[data_size-1];
                char* pcur, *pmem;

                const int line_size = buffer_info.dwSize.X;
                int line_count = buffer_info.dwCursorPosition.Y;

                if(buffer_info.dwCursorPosition.X > 0) // No new line char at the end of the last line, so no padded spaces. 
                {                    
                    if((line_count + 1) > 1)
                    {
                        pmem = &data[data_size - buffer_info.dwCursorPosition.X - 1];
                        pcur = (pmem - 1);
                    }
                    else // 1 line and no new line char(no padded spaces). Will no enters the loop.
                        pcur = &data[0];
                }
                else 
                {
                    pcur = &data[data_size-2];
                    pmem = 0;
                }
                
                if(pcur != pbeg)
                {
                    while(1)
                    {
                        line_count--;

                        while(*pcur == ' ') { pcur--; }
                        *(pcur + 1) = '\n'; // Padded spaces replaced by new line char.

                        if(!pmem) // first round. Add zero-ending char.
                            *(pcur + 2) = '\0'; 
                        else
                            memmove(pcur + 2, pmem, (pend - pmem) + 1);

                        if(line_count == 0)
                            break;

                        pmem = &data[line_count * line_size];
                        pcur = (pmem - 1);
                    }
                }

                *bufsize = strlen(data) + 1;
                 
                *buffer = malloc(*bufsize); //= new char[*bufsize];
                _ASSERTE(*buffer != 0);

                memcpy(*buffer, data, *bufsize);
                free(data); //delete[] data;
               
                pcur= *buffer;
                return pcur;
            }

            if(data)
                free(data); // delete[] data;
        }
    }
     
    *buffer = 0;
    return 0;
}


int main(int argc, char** argv)
{
    printf("Writting\nin\nthe\nbuffer");

    char* buffer;
    size_t size;  
    ReadConsoleBufferForFile(&buffer, &size);

    if(buffer)
    {
        freopen("out.txt", "w", stdout); 
        fprintf(stdout, buffer);
        free(buffer);
        fclose(stdout);
    }  
     
    return 0;
}

Output in 'out.txt':

Writting
in
the
buffer
温柔女人霸气范 2024-07-16 17:59:24

下载 mingw-readline

并查看 GNU Readline

rl_line_buffer

Download mingw-readline

And look GNU Readline

rl_line_buffer
北方的韩爷 2024-07-16 17:59:24

如果它是命令窗口中的屏幕,那么可能没有,或者没有简单的方法。 您可以破解 Windows 事件来全选、复制和读取剪贴板。

If it's the screen in a command window, then potentially no, or no easy way. You could hack at Windows events to select-all, copy, and read the clipboard.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文