Работа с open
, read
и write
, на самом деле не сильно отличается от работая с fopen
, fread
и fwrite
(или fgets
и fprintf
) за исключением любых конверсий, подсчета байтов и настроек созданных битов доступа к файлу, находящихся на вас. Когда write
записывает в файл значение 1020
, он записывает номер bytes
, который вы укажете ему, чтобы написать, и номер будет существовать в файле с тем же контентом, как ваше оборудование.
Например, если у вас есть unsigned v = 1020;
(0x3fc
в шестнадцатеричном), а затем write (fd, &v, sizeof v);
, когда вы смотрите на ваш файл с hexdump
или od
(или тому подобное), он будет содержать fc 03 00 00
(предполагая, что ваше оборудование прямой порядок байтов). Это ваши 4-bytes
значения unsigned
1020
. Вы не можете открыть файл в текстовом редакторе и ожидать увидеть символы ASCII, потому что это не то, что было записано в файл.
Чтобы найти количество строк в файле с помощью open
и read
, вы в основном хотят open
файл, прочитать файл в буфер некоторое разумное количество байт в то время, и сосчитать '\n'
символов в файле.
(примечание: вы также хотите, чтобы проверить, если последний символ чтения из файла есть нечто иное, чем '\n'
Если вы хотите добавить +1
к вашей линии отсчета для учета не-. POSIX конец финальной строки.)
Единственное другое предостережение - обратить внимание на mode
(разрешения) для любого нового созданного вами файла open
для записи. В противном случае вы окажетесь без доступа к вновь созданному файлу. Вот почему open предоставляет mode_t mode
в качестве третьего аргумента в случае, если предусмотрен флаг O_CREAT
.
Если вы хотите остаться верными только с помощью open, read, write
для вашей программы ввода/вывода, тогда вам придется предоставить вывод сообщения об ошибке на терминал STDERR_FILENO
в случае возникновения ошибки. Вам может понадобиться короткая вспомогательная функция, которая будет писать сообщения строки.
Соединяя кусочки вместе, вы можете сделать что-то вроде следующего, оставаясь верным своему делу.В следующем коде имена infile
и outfile
указаны в качестве первых двух аргументов программы: infile
65K bytes
за один раз, подсчитывает '\n'
s в файле, а затем записывает результат в outfile
, в котором учтен любой конец строки, не относящейся к POSIX для файла , writeliteral
предоставляется в качестве помощника для сообщений об ошибках:
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
enum { BUFFERSZ = 1 << 16 }; /* 65K buffer size */
void writeliteral (int fildes, const char *s);
int main (int argc, char **argv) {
if (argc < 3) {
writeliteral (STDERR_FILENO, "error: insufficient input.\n");
writeliteral (STDERR_FILENO, "usage: progname infile outfile\n");
return 1;
}
char buf[BUFFERSZ] = "";
unsigned i = 0, nlines = 0;
ssize_t n = 0;
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int fd = open (argv[1], O_RDONLY);
if (fd == -1) { /* validate file open for reading */
writeliteral (STDERR_FILENO, "error: infile open failed.\n");
return 1;
}
while ((n = read (fd, buf, sizeof buf)) > 0) /* read 65k chars */
for (i = 0; i < n; i++) /* count newlines in buf */
if (buf[i] == '\n')
nlines++;
if (buf[i - 1] != '\n') /* account for non-POSIX line end */
nlines++;
close (fd); /* close file */
/* open outfile for writing, create if it doesn't exist */
if ((fd = open (argv[2], O_WRONLY | O_CREAT, mode)) == -1) {
writeliteral (STDERR_FILENO, "error: outfile open failed.\n");
return 1;
}
write (fd, &nlines, sizeof nlines); /* write nlines to outfile */
close (fd); /* close file */
return 0;
}
/** write a string literal to 'fildes' */
void writeliteral (int fildes, const char *s)
{
size_t count = 0;
const char *p = s;
for (; *p; p++) {}
count = p - s;
write (fildes, s, count);
}
Пример входного файла
$ nl -ba ../dat/captnjack.txt
1 This is a tale
2 Of Captain Jack Sparrow
3 A Pirate So Brave
4 On the Seven Seas.
Пример использования/вывода
$ ./bin/readwrite_lineno ../dat/captnjack.txt ../dat/jacklines.dat
$ hexdump -n 16 -C ../dat/jacklines.dat
00000000 04 00 00 00 |....|
00000004
Посмотрите его и дайте мне знать, если у вас есть вопросы. Это показывает, почему вы можете оценить семейство спецификаторов формата еще больше, когда закончите.
Unix системный вызов? что? – redFIVE
Система @redFIVE Unix Вызывает, например. open, read, close, lseek и т. д. – bmalhi
Почему бы не прочитать * символ по символу * используя 'getch()' и увеличить 'lineCount', когда вы сталкиваетесь с' \ n' :) – Cherubim