Каков эффективный способ реализации хвоста в * NIX? Я подошел (написал) с двумя простыми решениями, используя как круглый буфер для загрузки строк в круговую структуру (массив | дважды связанный круговой список - для удовольствия). Я видел часть старой реализации в busybox, и из того, что я понял, они использовали fseek для поиска EOF, а затем читали материал «назад». Есть ли что-нибудь более чистое и быстрое там? Меня спросили об этом на собеседовании, и искатель не выглядел удовлетворенным. Заранее спасибо.Как бы эффективно реализовать хвост?
ответ
Я не думаю, что существуют решения, отличные от «держать последние N строк при чтении вперед данных» или «начинать с конца и идти назад, пока вы не прочтете N-ю строку».
Дело в том, что вы использовали бы тот или иной на основе контекста.
«Переход в конец и назад» лучше, когда хвост обращается к файлу произвольного доступа или когда данные достаточно малы, чтобы их можно было поместить в память. В этом случае время выполнения минимизируется, так как вы сканируете данные, которые должны быть выведены (так, что это «оптимально»)
Ваше решение (сохранить последние последние строки) лучше, когда хвост питается конвейером или когда данные огромны. В этом случае другое решение тратит слишком много памяти, поэтому это непрактично, и в случае, если источник медленнее, чем хвост (что является вероятным), сканирование всего файла не имеет большого значения.
Прочитать назад с конца файла до N
считываются строки или начинается начало файла.
Затем распечатайте то, что было просто прочитано.
Я не думаю, что здесь нужны какие-либо причудливые данные.
Here is the source code of tail Если вам интересно.
/*This example implements the option n of tail command.*/
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
#define BUFF_SIZE 4096
FILE *openFile(const char *filePath)
{
FILE *file;
file= fopen(filePath, "r");
if(file == NULL)
{
fprintf(stderr,"Error opening file: %s\n",filePath);
exit(errno);
}
return(file);
}
void printLine(FILE *file, off_t startline)
{
int fd;
fd= fileno(file);
int nread;
char buffer[BUFF_SIZE];
lseek(fd,(startline + 1),SEEK_SET);
while((nread= read(fd,buffer,BUFF_SIZE)) > 0)
{
write(STDOUT_FILENO, buffer, nread);
}
}
void walkFile(FILE *file, long nlines)
{
off_t fposition;
fseek(file,0,SEEK_END);
fposition= ftell(file);
off_t index= fposition;
off_t end= fposition;
long countlines= 0;
char cbyte;
for(index; index >= 0; index --)
{
cbyte= fgetc(file);
if (cbyte == '\n' && (end - index) > 1)
{
countlines ++;
if(countlines == nlines)
{
break;
}
}
fposition--;
fseek(file,fposition,SEEK_SET);
}
printLine(file, fposition);
fclose(file);
}
int main(int argc, char *argv[])
{
FILE *file;
file= openFile(argv[2]);
walkFile(file, atol(argv[1]));
return 0;
}
/*Note: take in mind that i not wrote code to parse input options and arguments, neither code to check if the lines number argument is really a number.*/
Первое использование fseek
найти конец файла-то вычитает 512 и fseek
к этому смещению, а затем читать вперед оттуда до конца. Подсчитайте количество разрывов строк, потому что, если их слишком мало, вам придется сделать то же самое с вычитаемым смещением 1024 ..., но в 99% случаев 512 будет достаточно.
Это (1) избегает чтение всего файла вперед и (2) причина, почему это, вероятно, более эффективно, чем чтение в обратном направлении от конца, что чтение вперед обычно быстрее.
и удваивать смещение каждый раз, когда он терпит неудачу. –
- 1. Реализовать хвост с AWK
- 2. Как эффективно реализовать объединение соединений?
- 3. Как эффективно реализовать макет gridview
- 4. Как эффективно реализовать функциональность базы данных?
- 5. Как эффективно реализовать коллизию для 2D-игры?
- 6. Как эффективно реализовать замыкания в LLVM IR?
- 7. Как эффективно реализовать функцию итерации в R
- 8. Как эффективно реализовать шаблон стратегии с весной?
- 9. Сохранение дерева в файл. Как эффективно реализовать?
- 10. Как я могу это реализовать более эффективно
- 11. Как эффективно реализовать бинарные диаграммы решений (BDD)?
- 12. Как эффективно реализовать ViewPager с различными фрагментами?
- 13. Как реализовать веб-приложения более эффективно?
- 14. Как эффективно реализовать несколько тем в приложении?
- 15. Как эффективно реализовать Maxpooling в MATLAB?
- 16. Обратный журнал, как хвост
- 17. Как бы я повторно реализовать dynamic_cast?
- 18. Как бы реализовать функцию «построить» в clojure?
- 19. Как вы могли бы реализовать вне-правила?
- 20. Как бы реализовать этот протокол быстро?
- 21. длинное приложение (хвост как)
- 22. Как «отрезать хвост» серии
- 23. Как написать хвост -f как программа C
- 24. Как эффективно реализовать дескриптор в потокобезопасной C-библиотеке
- 25. Как заставить GInfoWindow сократить хвост?
- 26. Хвост базы данных MariaDB изменяется, как хвост MongoDB oplog
- 27. Как бы вы могли написать этот запрос linq эффективно?
- 28. Как бы вы эффективно реализовали эти запросы в MongoDB?
- 29. хотел бы знать, как эффективно выполнять регрессионное тестирование?
- 30. Как эффективно реализовать неизменный граф гетерогенных неизменяемых объектов в C++?
Мне нравится этот вопрос, потому что это очень важный урок при изучении программирования (и в целом в системах). Некоторые операции просто неотъемлемо * невозможно сделать эффективно *, по крайней мере, не дано стандартное представление данных, с которыми вы работаете (в данном случае, линейный файл байтового потока, начинающийся с самого начала). Научиться распознавать это просто из формата данных и избегать сопряжения данных и операций, которые не могут эффективно работать вместе, является ключевой частью обучения эффективному программному обеспечению. –