阅读一篇巨大的文字

时间:2017-02-17 13:24:57

标签: c++ linux

我正在尝试读取一个文件,就像我在Linux中使用选项more一样。我只想尝试more几乎相同的实现。 我的问题是当我按顺序读取文件时:

aaaaaaaaaaaaaaaaaaaa

bbbbbbbbbbbbbbbbbbbbb
.....................
ccccccccccccccccccccc

例如:我在txt.file中有100个字符串,按照我向您展示的顺序排列。因此,每个字符串都不会超过控制台的水平大小,而是在ENTER之后。

该计划非常出色。我的意思是,如果我的txt.file信息没有完全显示,我只需按SPACE,然后从文件中查看我的另一个信息屏幕。

但是如果我用一个长字符串放一个大文本,它只是完全读取一个文件并显示文件的结尾。 我做错了什么?我可能不考虑控制台的水平尺寸?但我认为,在这种情况下Linux会为我考虑..你可以帮助我吗?

我的论点是:./more 0 1.txt

./more - make file,0 - 我正在使用此字符串,1.txt - 文件名。

我的代码:

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sys/ioctl.h>
#include <unistd.h>
#include <termios.h>


int getch();
void printRecord(int& numStr,struct winsize w, std::vector<std::string>& lines);

int main(int argc, char *argv[]) {
    struct winsize w;
    char ch;
    ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
    std::ifstream readRecord;
    std::vector<std::string> lines;

        std::string str;
        readRecord.open(argv[2]);
        int numStr= atoi(argv[1]);

        while (!readRecord.eof())
        {
            getline(readRecord, str);
            str.size();
            lines.push_back(str);
        }
            printRecord(numStr,w, lines);

         ch=getch();

           while(ch!='q'){
            if (ch==32)
            {
              numStr--;
                printRecord(numStr,w,lines);  
            }

            if (numStr>=lines.size()){
                break;}
           ch=getch();
            }

    return 0;
}

void printRecord(int& numStr,struct winsize w,std::vector<std::string>& lines)
{

    for (int i = numStr; i  <  numStr + w.winsize::ws_row-1; i++)
    {

        if (i>=lines.size())
            break;
        else
            std::cout << lines[i] << std::endl;

    }

    numStr += w.winsize::ws_row;
}

int getch()
{
    int ch;

    struct termios oldt, newt;
    tcgetattr( STDIN_FILENO, &oldt );
    newt = oldt;
    newt.c_lflag &= ~( ICANON | ECHO );
    tcsetattr( STDIN_FILENO, TCSANOW, &newt );
    ch = getchar();
    tcsetattr( STDIN_FILENO, TCSANOW, &oldt );

    return ch;
}

1 个答案:

答案 0 :(得分:3)

不,Linux在这种情况下不会“为我考虑”。如果您的代码按原样打印出文件的内容,则文件的内容将打印到标准输出。如果终端不足以显示文件的内容,则只有屏幕上的任何内容都将保留在最后。在打印文件的内容时,文件的初始部分将在显示滚动之前短暂显示。

终端不会自动为您的程序输出分页。那是真正的more工作。如果您想复制more的功能,您必须自己完成。

您的程序可以通过制作您应该阅读的TIOCGWINSZ ioctl,as explained in the tty_ioctl(4) manual page来获取终端显示的大小。在获得终端的大小之后,您的程序将决定文件的内容在屏幕上的适合程度,并正确地对其进行分页。

如果您必须处理多字节UTF-8编码内容,那么事情变得非常复杂,如果您的输出包含某些亚洲字符集,更不用说双宽字符。在国际化和本地化时代,计算印刷文本的实际尺寸是非常困难的。但是,对于普通的拉丁文本,这应该足够了。您还应该为SIGWINCH设置信号处理程序,如该手册页中所述,以检测对终端大小的更改,以便您可以相应地重新分隔文件的内容。

您还可以考虑使用更高级别的库,例如curses,在这种情况下可能会有用。