简体   繁体   English

std :: getline和eol与eof

[英]std::getline and eol vs eof

I've got a program that is tailing a growing file. 我有一个程序正在跟踪不断增长的文件。

I'm trying to avoid grabbing a partial line from the file (eg reading before the line is completely written by the other process.) I know it's happening in my code, so I'm trying to catch it specifically. 我试图避免从文件中抓取部分行(例如,在其他进程完全写完该行之前先进行读取。)我知道它正在我的代码中发生,因此我试图专门捕获它。

Is there a sane way to do this? 有理智的方法吗?

Here's what I'm trying: 这是我正在尝试的:

if (getline (stream, logbuffer))
{
    if (stream.eof())
    {
        cout << "Partial line found!" << endl;
        return false;
    }
    return true;
}
return false;

However, I can't easily reproduce the problem so I'm not sure I'm detecting it with this code. 但是,我无法轻松重现该问题,因此不确定使用此代码检测到它。 std::getline strips off newlines, so I can't check the buffer for a trailing newline. std :: getline去除换行符,因此我无法检查缓冲区中是否包含尾随的换行符。 My log message (above) is NEVER tripping. 我的日志消息(以上)从未触发。

Is there some other way of trying to check what I want to detect? 还有其他尝试检查我要检测的内容的方法吗? Is there a way to know if the last line I read hit EOF without finding a EOL character? 有没有办法知道我读的最后一行是否在没有找到EOL字符的情况下达到了EOF?

Thanks. 谢谢。

This will never be true: 这将永远是不正确的:

if (getline (stream, logbuffer))
{
    if (stream.eof())
    {
       /// will never get here

If getline() worked, the stream cannot be in an eof state. 如果getline()有效,则流不能处于eof状态。 The eof() and related state tests only work on the results of a previous read operation such as getline() - they do not predict what the next read will do. eof()和相关的状态测试仅对诸如getline()之类的上一个读取操作的结果起作用-它们不预测下一个读取将做什么。

As far as I know, there is no way of doing what you want. 据我所知,没有办法做你想做的事。 However, if the other process writes a line at a time, the problems you say you are experiencing should be very rare (non -existent in my experience), depending to some extent on the OS you are are using. 但是,如果其他进程一次写一行,那么您所说的问题应该很少见(我的经验中不存在),在某种程度上取决于您所使用的OS。 I suspect the problem lies elsewhere, probably in your code. 我怀疑问题出在其他地方,可能在您的代码中。 Tailing a file is a very common thing to do, and one does not normally need to resort to special code to do it. 尾随一个文件是很常见的事情,通常不需要使用特殊代码来完成它。

However, should you find you do need to read partial lines, the basic algorithm is as follows: 但是,如果发现确实需要读取部分行,则基本算法如下:

forever do
   wait for file change
   read all possible input using read or readsome (not getline)
   chop input into lines and possible partial line
   process as required
end

An istream object such as std::cin has a get function that stops reading when it gets to a newline without extracting it from the stream. istream对象(例如std::cin具有get函数 ,该函数在到达换行符时会停止读取,而不会从流中提取它。 You could then peek() or get() it to see if indeed it is a newline. 然后,您可以peek()get()查看它是否确实是换行符。 The catch is that you have to know the maximum length of a line coming from the other application. 要注意的是,您必须知道来自其他应用程序的一行的最大长度。 Example (untested) code follows below: 示例(未试用)代码如下:

char buf[81];  // assumes an 80-char line length + null char
memset(buf, 0, 81);

if (cin.get(buf, 81))
{
    if (cin.peek() == EOF)  // You ran out of data before hitting end of line
    {
        cout << "Partial line found!\n";
    }
}

Even if the other program isn't done writing the file, in the file that's where the line ends, so there's no way to tell the difference other than waiting to see if the other program writes something new. 即使其他程序没有写完文件,也就是该行结束处的文件,所以除了等待其他程序是否写新东西外,别无其他方法。

edit: If you just want to tell if the line ends in a newline or not, you could write your own getline function that reads until it hits a newline but doesn't strip it. 编辑:如果只想知道行是否以换行符结尾,则可以编写自己的getline函数,该函数读取直到碰到换行符但不会剥离它。

I have to take issue with one statement you made here: 我必须对您在这里发表的一项声明表示怀疑:

However, I can't easily reproduce the problem so I'm not sure I'm detecting it with this code. 但是,我无法轻松重现该问题,因此不确定使用此代码检测到它。

It seems like from what you said it would be extremely easy to replicate your problem, if it is what you said. 从您所说的看来,如果确实如此,那么复制您的问题将非常容易。 You can easily create a text file in some text editor - just make sure that the last like ends in an EOF instead of going on to a new line. 您可以在某些文本编辑器中轻松创建文本文件-只需确保最后一个like以EOF结尾,而不是继续换行。 Then point your program at that file and see what results. 然后将程序指向该文件并查看结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM