I have a Linux file descriptor (from socket), and I want to read one line. How to do it in C++?
+1
A:
Pseudocode:
char newline = '\n';
file fd;
initialize(fd);
string line;
char c;
while( newline != (c = readchar(fd)) ) {
line.append(c);
}
Something like that.
echo
2009-10-17 22:23:39
This is usually good enough, but sometimes i get reaallly long lines, and reading one char at a time is too slow.
Łukasz Lew
2009-10-17 22:25:17
+2
A:
I you are reading from a TCP socket you can't assume when the end of line will be reached. Therfore you'll need something like that:
std::string line;
char buf[1024];
int n = 0;
while(n = read(fd, buf, 1024))
{
const int pos = std::find(buf, buf + n, '\n')
if(pos != std::string::npos)
{
if (pos < 1024-1 && buf[pos + 1] == '\n')
break;
}
line += buf;
}
line += buf;
Assuming you are using "\n\n" as a delimiter. (I didn't test that code snippet ;-) )
On a UDP socket, that is another story. The emiter may send a paquet containing a whole line. The receiver is garanted to receive the paquet as a single unit .. If it receives it , as UDP is not as reliable as TCP of course.
yves Baumes
2009-10-17 22:25:56
It's about TCP, yes. The problem is that the socket is interactive.I have to sent one line, then I get few lines. I can recognize the end with double newline "\n\n".
Łukasz Lew
2009-10-17 22:28:36
... so I can't read ahead 1024 characters because there might be not so many. man 2 read shows that POSIX read have 3 arguments, so I don't know what read are you referring to.
Łukasz Lew
2009-10-17 22:32:14
as I told you I didn't test it. I only write 'at the fly' . The code is easy to understand and adapt. By the way I've updated it to take in account your line delimiters: "\n\n"
yves Baumes
2009-10-17 22:33:56
Łukasz: What do you mean "read ahead"? `read()` returns as soon as any data is available. Just call `read()` with a large buffer; it will not wait for the whole buffer to fill.
Artelius
2009-10-17 22:37:26
reading 1024 characters at a time is not a problem. As long as the place holder is wide enough and that you don't look over what is transmitted by read() call. That is the meaning of the read() return value: the n variable in my exemple.
yves Baumes
2009-10-17 22:39:23
No, a non-blocking read is one that returns even if *no* data is available. However, even in blocking mode, read() will return as soon as data arrives. From the man page: "On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now"
Artelius
2009-10-17 22:40:20
@Artelius : thnaks to you for great explanation! With a better english than mine . :-)
yves Baumes
2009-10-17 22:41:58
A:
Anders Hedström
2009-10-18 07:10:32
A:
Here is a tested, quite efficient code:
bool ReadLine (int fd, string* line) {
// We read-ahead, so we store in static buffer
// what we already read, but not yet returned by ReadLine.
static string buffer;
// Do the real reading from fd until buffer has '\n'.
string::iterator pos;
while ((pos = find (buffer.begin(), buffer.end(), '\n')) == buffer.end ()) {
char buf [1025];
int n = read (fd, buf, 1024);
if (n == -1) { // handle errors
*line = buffer;
buffer = "";
return false;
}
buf [n] = 0;
buffer += buf;
}
// Split the buffer around '\n' found and return first part.
*line = string (buffer.begin(), pos);
buffer = string (pos + 1, buffer.end());
return true;
}
It's also useful to setup signal SIGPIPE ignoring in reading and writing (and handle errors as shown above):
signal (SIGPIPE, SIG_IGN);
Łukasz Lew
2009-10-18 11:15:16