Эффективная замена заголовков для больших (10M строк )файлов?

Причина в том, что вы используете scanf, который читает из потока стандартного ввода. Он использует буферы, поэтому он попытается прочитать данные из одного буфера и только затем проверит, сколько этих данных ему действительно нужно. Поскольку ваша команда lsдоступна немедленно, она также будет прочитана в буфер, ожидая другого вызова scanf (или любой другой буферизованной функции stdio, работающей на стандартном вводе ). Поэтому, когда shзатем пытается прочитать со стандартного ввода, ничего не остается, поскольку он не видит буфер, который является внутренним для вашей программы на C.

Есть как минимум два способа решить эту проблему.

  1. Убедитесь, что команда «ls» не выводится на стандартный ввод до того, как scanf завершит чтение. Это немного сложно, так как вам нужно будет подождать, пока ваша программа выведет доказательства прохождения этой точки (не тривиально ), или затем использовать некоторую фиксированную задержку и надеяться, что система никогда не остановится в этой точке и сделает задержка слишком короткая (т.е. это хрупкое решение ).Последний будет выглядеть примерно так :(echo 3 ; sleep 1 ; echo ls) | myprogram, т. е. три команды выполняются по порядку, и все они обеспечивают ввод для myprogram.

  2. Вы используете функции для чтения из стандартного ввода -без буферов -только минимальное количество необходимых символов. Например, функция readне использует буферы. Вы можете написать вспомогательную функцию, например

#include 
#include 
#include 
#include 

int unbuffered_scanf(const char *fmt,...) {
  char buffer[100]; // maximum line length
  int i;
  int ret;
  for(i=0; i 0)
        system("/bin/sh");
    else
        printf("Goodbye!\n");
}

Для получения дополнительной информации о небуферизованных функциях прочтите информационные страницы, например, здесь:https://www.gnu.org/software/libc/manual/html_node/I_002fO-Primitives.html#I_002fO-Primitives

РЕДАКТИРОВАТЬ:По-видимому, есть способ отключить буферизацию, выполняемую scanfи другими, используя, например,. функция setbuf-она, вероятно, работает внутренне точно так же, как мой пример выше:

#include 
#include 

int main()
{
    int iRetval = 0;
    unsigned int uiNum;

    setbuf(stdin, NULL);
    printf("Enter number: ");
    fflush(stdout);
    iRetval = scanf("%u", &uiNum);
    printf("\nThe number is %u, Retval: %i\n", uiNum, iRetval);
    fflush(stdout);
    if( iRetval > 0)
        system("/bin/sh");
    else
        printf("Goodbye!\n");
}

1
18.06.2021, 00:42
2 ответа
  1. Вывод нового заголовка в новый файл, например. printf "This is my first line\n > bigfile.new.
  2. Используйте tailиз bigfileдля предоставления остальных, используя перенаправление добавления:>>.

Одно замечание:tail +2заключается в том, что "GNUism" -будет работать в большинстве дистрибутивов Linux, но не совместим с POSIX и, вероятно, не будет работать в других Unices.

1
28.07.2021, 11:24

Предполагая bashи Linux, это, вероятно, быстрее, чем код в вашем вопросе:

(echo "New headers";tail +2 bigfile.txt) > newbigfile.txt && mv newbigfile.txt bigfile.txt
1
28.07.2021, 11:24

Теги

Похожие вопросы