0

I have to implement a buffered writer with C++ on linux. Now I've got a problem: I can write characters to a file, but in addition, the file is filled with invalid characters (in gedit the file is filled with \00 after the real characters).

Here's a part of the code:

BufferedWriter::BufferedWriter(const char* path) {
    pagesize = getpagesize();
    if ((fd = open(path, O_WRONLY | O_DIRECT | O_CREAT | O_TRUNC, S_IRWXU))
        == -1) {
        perror("BufferedWriter: Error while opening file");
        throw -1;
    }
    if (posix_memalign((void**) &buffer, pagesize, pagesize) != 0) {
        perror("BufferedWriter: Error while allocating memory");
        throw -3;
    }
    for (int i = 0; i < pagesize; i++) {
        buffer[i] = 0;
    }
    charCnt = 0;
}

...

void BufferedWriter::writeChar(char c) {
    buffer[charCnt] = c;
    charCnt++;
    if (charCnt == pagesize) {
        if (write(fd, buffer, pagesize) == -1) {
            perror("BufferedWriter: Error while writing to file");
            throw -5;
        }
        for (int i = 0; i < pagesize; i++) {
            buffer[i] = 0;
        }
        charCnt = 0;
     }
}

When I initialize my buffer e.g. with whitespaces, it all works fine, but is there another way to prevent the "invalid characters"?

Thanks for helping me

hjoeren
  • 549
  • 1
  • 5
  • 12
  • 1
    Where is the code that writes less than a page? And why do you keep zeroing the buffer? Since you know how many bytes of data are in it, why not just not access the values that aren't valid? – David Schwartz Nov 25 '13 at 23:55
  • As an aside, chances are you are not helping yourself with O_DIRECT. You are going to need more than this to outperform what the kernel does for free and not all file systems support O_DIRECT so you have to check that you aren't writing to VFAT, etc. – Duck Nov 26 '13 at 00:08
  • When I try to write less than a page, e.g. "write (fd, buffer, charCnt)" the write-function results with an error (invalid argument). The O_DIRECT-Flag I have to use (as part of an excercise) – hjoeren Nov 26 '13 at 00:20
  • The last page of your file will be padded out with NULs because you're always writing pagesize increments. You probably need to `ftruncate()` to the actual size at the end. – Joe Z Nov 26 '13 at 00:37
  • Thanks all for helping. @JoeZ 's comment with `ftruncate()` is a way for me, to handle my problem. – hjoeren Nov 26 '13 at 09:26
  • @JörenHaag : I'll write it up as an answer then... – Joe Z Nov 26 '13 at 12:44

1 Answers1

0

Because you're using O_DIRECT, you're apparently forced to write in pagesize increments. However, that implies your file will always be padded out to a multiple of pagesize. In your current code, it will be padded with zeros, because you zero the page each time before filling it.

One way to address this is to track the actual amount of data that should be in the file, and ftruncate() the file to the desired size before closing it.

Joe Z
  • 17,413
  • 3
  • 28
  • 39