C低级标准输入接受文件名然后将文件内容打印到标准输出

时间:2013-10-31 18:46:08

标签: c stdin low-level low-level-io low-level-code

我想通过stdin从用户那里获取文件名,用open()打开文件并将其分配给文件描述符,然后将该文件的内容打印到stdout。这是我的代码,但它无法正常工作。

问题:

  1. printf(“输入文件名”);声明永远不会出现
  2. 它永远不会打开文件;相反,无论用户输入打印到屏幕上,然后打印“没有这样的文件或目录”错误消息并退出程序
  3. 程序存在后,我看到在终端
  4. 中的提示之前打印的“输入文件名”

    CODE:

        {
            printf("Enter the filename: ");
            read(STDIN_FILENO, userInput, sizeof(userInput));
            if((input_file1 = open(userInput, O_RDONLY)) < 0)
            {
                perror(userInput);
                exit(1);
            }
    
            while((n = read(input_file1, buffer, sizeof(buffer))) > 0)
            {
                if((write(STDOUT_FILENO, buffer, n)) < 0)
                {
                    perror("failed to write to standard-out");
                    close(input_file1);
                    exit(1);
                }
            }
        }
    

    控制台:

    machine{user1}168: ls // to show that the file exists
    a.out  backup  file1 
    machine{user1}170: ./a.out
    file1 // this is user input
    file1 // this is printed for no reason
    : No such file or directory // ????
    Enter the filename: machine{user1}171: // now the prompt is printed...? 
    

2 个答案:

答案 0 :(得分:2)

<stdio.h>输入/输出例程为buffered(请参阅stdio(3)&amp; setbuf(3)。您需要调用fflush(3)(在最近的libc上,它是隐式的如果您使用stdoutfgets阅读,则需要scanf。并且您确实应该避免在同一输出或输入上混合文件描述符和FILE句柄(请参阅{{3但总是调用fflush ....)。 所以替换

         printf("Enter the filename: ");
         read(STDIN_FILENO, userInput, sizeof(userInput));

         printf("Enter the filename: \n");
         fflush(NULL);
         if (!fgets(userInput,sizeof(userInput),stdin))
           { perror("fgets"); exit(EXIT_FAILURE); };

实际上,如果您保留非常重要的终止fflush(换行符),则可以避免使用\n。如果您不想要任何换行符,最好拨打fflush(但有些libc正在为您调用)。

过多地或过于频繁地调用fflush的危害要小得多(因为在所有已经刷新的流上它都是无操作的)比调用它太少或不够。

但是你应该学习fileno(3)(以避免固定长度的线条)。在Linux和GNU系统上getline(3)值得使用:它使您能够提供性感提示,并且您的用户可以编辑键入的行。

答案 1 :(得分:2)

您的提示永远不会出现,因为您使用read()而不是其中一个标准I / O函数(scanf()fgets()等)来获取输入。在调用fflush(stdout)之前,请更改输入功能或使用fflush(0)read()

您的阅读内容包括换行符,因此open会尝试使用名称末尾的换行符打开该文件。该文件不存在,因此打开失败。

{
    printf("Enter the filename: ");
    if (fgets(userInput, sizeof(userInput), stdin) == 0)
    {
        fprintf(stderr, "Oops!\n");
        exit(1);
    }
    userInput[strlen(userInput)-1] = '\0';
    if ((input_file1 = open(userInput, O_RDONLY)) < 0)
    {
        perror(userInput);
        exit(1);
    }

    while ((n = read(input_file1, buffer, sizeof(buffer))) > 0)
    {
        if (printf("%.*s", n, buffer)) != n)
        {
            perror("failed to write to standard-out");
            close(input_file1);
            exit(1);
        }
    }
    close(input_file1);
}