Низкоуровневый ввод / вывод C: при чтении из одного файла и записи в другой, я попадаю в бесконечный цикл - PullRequest
2 голосов
/ 19 марта 2012

Я работаю над назначением, которое позволяет использовать низкоуровневый ввод-вывод (read (), write (), lseek ()), а также perror ().

Я смогчтобы открыть файлы nessisary in и out с правильными разрешениями, но при выводе я получаю бесконечный цикл из содержимого in out.См. Фрагмент ниже ...

void *buf = malloc(1024);
while((n = read(in, buf, 1024)) > 0){
    if(lseek(in, n, SEEK_CUR) == -1){
        perror("in file not seekable");
        exit(-1);
    }
    while((m = write(out, buf, n)) > 0){
        if(lseek(out, m, SEEK_CUR) == -1){
            perror("out file not seekable");
            exit(-1);
        }
    }
    if(m == -1){ perror("error writing out"); exit(-1); }
}
if(n == -1){ perror("error reading in"); exit(-1); }

Я удалил некоторые ошибки из моего кода, и вы можете предположить, что переменные инициализированы и содержат операторы.

Ответы [ 2 ]

2 голосов
/ 19 марта 2012

Проблема заключается во внутреннем цикле:

while((m = write(out, buf, n)) > 0){

действительно должно быть

if((m = write(out, buf, n)) > 0){

Вы хотите, чтобы buf было написано только один раз, а не бесконечно много раз. Вы также должны обрабатывать короткие записи, то есть когда запись возвращается с m 0.

Кроме того, lseek() вызовы неверны, но они не ведут к циклу. read() и write() уже увеличивают текущее смещение файла. Вам не нужно продвигать его вручную, если только вы не хотите пропустить байты во входном или выходном файле (обратите внимание, что в случае выходного файла в UNIX пропуск байтов может привести к так называемым «дырам» в файлах, области которых ноль, но не занимают место на диске).

0 голосов
/ 19 марта 2012

Почему вы ищете входной файл после чтения?Поскольку вы в большинстве случаев будете читать 1024 байта (то есть n будет где-то между 0 и 1024), вы будете постоянно искать что-то за пределами того места, где вы оставили указатель входного файла, так что вы потеряете данные в передаче (включая, вероятно, за конец файла, когда вы приближаетесь к концу).

Это может быть одной из причин, по которой у вас есть бесконечный цикл, но далекоболее коварным является использование while для записи.Так как при успешном возвращении значения будут больше нуля, вы будете постоянно записывать первый кусок в файл снова и снова.По крайней мере, до тех пор, пока у вас не закончится место на диске или другие ресурсы.

Вам также не понадобится seek при записи.Вызовы read и write делают то, что должны и правильно передвигают указатель файла для следующего read или write - это не то, что вам нужно делать вручную.

Вы, вероятно, можете упростить все это до:

while ((n = read (in, buf, 1024)) > 0) {
    if ((m = write (out, buf, n)) != n) {
        perror ("error writing out");
        exit (-1);
    }
}

, что имеет следующие преимущества:

  • избавление от вызовов seek;
  • удаление бесконечного цикла;
  • проверка того, что вы написали все запрошенных байтов.
...