read()调用后printf打印垃圾。偏移始终打印为0

时间:2021-01-06 20:19:43
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdint.h>

int main()
{
    int file;
    off_t offset;

    if((file=open("testfile.txt",O_RDONLY)) < -1)
            return 1;

    char buffer[19];

    if(read(file,buffer,19) != 19)  return 1;
    fprintf(stdout,"%s\n",buffer);


    if(offset = lseek(file,-19,SEEK_END) < 0) return 1;
    fprintf(stdout,"%jd\n",(intmax_t)offset);

    if(read(file,buffer,19) != 19)  return 1;
    fprintf(stdout,"%s\n",buffer);

    return 0;
}

The Output is as follows:

输出如下:

This is a test file��

这是一个测试文件

0

his is a test file

他是一个测试文件

��

testfile.txt :

This is a test file Testing how SEEK_END works This is a test file

这是一个测试文件测试SEEK_END的工作原理这是一个测试文件

I have tried different formatting for offset, such as %ld,%d, but the output is still the same. Can't figure out why garbage appears at the end of first line and last line. Please help.

我尝试了不同的偏移格式,例如%ld,%d,但输出仍然相同。无法弄清楚为什么垃圾出现在第一行和最后一行的末尾。请帮忙。

3 个解决方案

#1


3  

You need to leave room for an end of line character, '\0';

你需要为行尾字符留出空间,'\ 0';

So make char buffer[19]; char buffer[20]; then also add buffer[19] = '\0'; - remember it's zero based counting. Then it shouldn't have the garbage data.

所以make char buffer [19]; char buffer [20];然后还添加缓冲区[19] ='\ 0'; - 记住它是基于零的计数。然后它不应该有垃圾数据。

The reason is because printf doesn't know where the end is of the character array. So it keeps printing until it finds a '\0' in garbage memory.

原因是因为printf不知道字符数组的结尾。所以它一直打印,直到它在垃圾记忆中找到'\ 0'。

#2


2  

read does not know anthing about strings, it reads bytes from a file. so if you read in 19 bytes into "buffer" and there is no terminating \0 then it is not a valid string.

read不知道关于字符串的anthing,它从文件中读取字节。因此,如果您将19个字节读入“缓冲区”并且没有终止\ 0那么它就不是有效的字符串。

So either you need to ensure that your buffer is 0 terminated or print out only the first 19 bytes e.g. printf( "%.*s", sizeof(buffer), buffer ); or extend the buffer for the \0 e.g. char buffer[20] = {0};

因此,您需要确保缓冲区为0终止或仅打印出前19个字节,例如printf(“%。* s”,sizeof(缓冲区),缓冲区);或扩展\ 0的缓冲区,例如char buffer [20] = {0};

You should also open the file like this in order to make sure lseek works (file must be opened in binary mode)

您还应该打开这样的文件,以确保lseek工作(文件必须以二进制模式打开)

if((file=open("testfile.txt",O_RDONLY|O_BINARY)) == -1) // returns -1 by failure
{
  perror("testfile.txt"); // to get an error message why it failed.
  return 1;
}

it is always good to give an error message when something fails instead of just terminating the program.

当出现故障而不是仅仅终止程序时,给出错误消息总是好的。

#3


0  

Other answers have already offered solutions for the problem with printing buffer. This answer addresses the other question in your post.

其他答案已经为打印缓冲区的问题提供了解决方案。这个答案解决了你帖子中的另一个问题。

Due to operator precedence, the line

由于运算符优先,该行

if(offset = lseek(file,-19,SEEK_END) < 0) return 1;

is equivalent to:

相当于:

if(offset = (lseek(file,-19,SEEK_END) < 0)) return 1;

I am sure you meant to use:

我相信你打算使用:

if( (offset = lseek(file,-19,SEEK_END)) < 0) return 1;

#1


3  

You need to leave room for an end of line character, '\0';

你需要为行尾字符留出空间,'\ 0';

So make char buffer[19]; char buffer[20]; then also add buffer[19] = '\0'; - remember it's zero based counting. Then it shouldn't have the garbage data.

所以make char buffer [19]; char buffer [20];然后还添加缓冲区[19] ='\ 0'; - 记住它是基于零的计数。然后它不应该有垃圾数据。

The reason is because printf doesn't know where the end is of the character array. So it keeps printing until it finds a '\0' in garbage memory.

原因是因为printf不知道字符数组的结尾。所以它一直打印,直到它在垃圾记忆中找到'\ 0'。

#2


2  

read does not know anthing about strings, it reads bytes from a file. so if you read in 19 bytes into "buffer" and there is no terminating \0 then it is not a valid string.

read不知道关于字符串的anthing,它从文件中读取字节。因此,如果您将19个字节读入“缓冲区”并且没有终止\ 0那么它就不是有效的字符串。

So either you need to ensure that your buffer is 0 terminated or print out only the first 19 bytes e.g. printf( "%.*s", sizeof(buffer), buffer ); or extend the buffer for the \0 e.g. char buffer[20] = {0};

因此,您需要确保缓冲区为0终止或仅打印出前19个字节,例如printf(“%。* s”,sizeof(缓冲区),缓冲区);或扩展\ 0的缓冲区,例如char buffer [20] = {0};

You should also open the file like this in order to make sure lseek works (file must be opened in binary mode)

您还应该打开这样的文件,以确保lseek工作(文件必须以二进制模式打开)

if((file=open("testfile.txt",O_RDONLY|O_BINARY)) == -1) // returns -1 by failure
{
  perror("testfile.txt"); // to get an error message why it failed.
  return 1;
}

it is always good to give an error message when something fails instead of just terminating the program.

当出现故障而不是仅仅终止程序时,给出错误消息总是好的。

#3


0  

Other answers have already offered solutions for the problem with printing buffer. This answer addresses the other question in your post.

其他答案已经为打印缓冲区的问题提供了解决方案。这个答案解决了你帖子中的另一个问题。

Due to operator precedence, the line

由于运算符优先,该行

if(offset = lseek(file,-19,SEEK_END) < 0) return 1;

is equivalent to:

相当于:

if(offset = (lseek(file,-19,SEEK_END) < 0)) return 1;

I am sure you meant to use:

我相信你打算使用:

if( (offset = lseek(file,-19,SEEK_END)) < 0) return 1;