使用read()函数从文件中读取内容

14

我需要编写一个程序,逐行读取数字。是否可以只读取文件中的一行,然后从缓冲区中读取一个 int ,并一直持续读取到文件末尾?但是,很难找到使用 read 和 write 的好的示例。我的示例有点可行,但我希望能够一直读取直到检测到 '\n' 字符,然后将缓冲区转换为 int。

#include <fcntl.h> 
#include <stdio.h> 
#include <string.h>
#include <unistd.h> 
#include <iostream>

int fd[2];

void readFile(int fd) {
    unsigned char buffer[10];
    int bytes_read;
    int k=0;
    do {
        bytes_read = read(fd, buffer, 10); 
        k++;
            for(int i=0; i<10; i++) {
            printf("%c", buffer[i]);
        }
    }
    while (bytes_read != 0); 
}

int tab[50];

int main(int argc, char *argv[]) {
    if(argv[1] == NULL || argv[2] == NULL)   {
            printf("Function requires two arguments!\nGood bye...\n");
            return -1;
    }
    else {
        if (access(argv[1], F_OK) == 0) {
            fd[0] = open(argv[1], O_RDONLY);
        }
        else { 
            fd[0] = open(argv[1], O_WRONLY|O_CREAT|O_SYNC, 0700);
            const int size = 50;
                for(int i=0; i<size; i++) {
                    char buf[10];   
                    sprintf(buf, "%d\n", i+1);
                    write(fd[0], buf, strlen(buf));
                }
                close(fd[0]);
            fd[0] = open(argv[1], O_RDONLY);
            if (access(argv[2], F_OK) == 0) 
                fd[1] = open(argv[2], O_WRONLY);
            else 
                fd[1] = open(argv[2], O_WRONLY|O_CREAT, 0700);
        }
    }

    if (access(argv[2], F_OK) == 0) 
        fd[1] = open(argv[2], O_WRONLY); 
    else 
        fd[1] = open(argv[2], O_WRONLY|O_CREAT, 0700);


    readFile(fd[0]);
    close(fd[0]);
    close(fd[1]);
}

修改后的代码:

void readFile(int fd) {
    char buffer[10];
    int bytes_read;
    int k = 0;
    do {
        char t = 0;
        bytes_read = read(fd, &t, 1); 
        buffer[k++] = t;    
        printf("%c", t);
        if(t == '\n' && t == '\0') {
            printf("%d", atoi(buffer));
            for(int i=0; i<10; i++) 
                buffer[i]='\0';
            k = 0;
        }
    }
    while (bytes_read != 0); 
}

2
问题是什么? - shodanex
哦,抱歉。如何只读取一行。 - Wit
如果read出现错误并返回-1,则您的while循环将永远不会终止。始终预期错误。 - William Pursell
不要使用do { ... read() ...,考虑使用while ((bytes_read = read(fd, &t, 1)) > 0) { - chux - Reinstate Monica
3个回答

25

逐字节读取并检查每个字节是否等于'\n',如果不是,则将其存储到buffer中。
如果是'\n',则将'\0'添加到缓冲区,然后使用atoi()函数。

可以像这样读取单个字节:

char c;
read(fd,&c,1);

请参见read()


好的,它正在工作,但是出现了一个错误:“*** stack smashing detected ***: ./pro terminated core dumped.”。我的函数在第一篇帖子中的“edit”标签下。 - Wit
使用gdb进行回溯并找出导致段错误的代码行。 - Gangadhar
这段代码会在我的机器上导致分段错误。我认为你需要使用char c[1];,因为read函数期望的是char*而不是char - gbtimmon
@gbtimmon:根据 POSIX 定义,read() 没有标准版本需要 char ** - Jonathan Leffler
5
快速问题:这样做是否比在单个read调用中读取到缓冲区(char数组),然后迭代缓冲区中的字符要低效?我想一个字符一个字符地调用read会比读取到缓冲区更加昂贵... - birgersp
@Gangadhar 缓冲区应该有多大?可能一行很长,对吧? - TMOTTM

0

我正在使用read从文件中读取一些数据。在这里,我正在读取2D字符指针中的数据,但对于1D也是相同的方法。只需逐个字符地读取,不必担心异常,因为while循环中的条件正在处理异常:D

  while ( (n = read(fd, buffer,1)) > 0 )
{   

if(buffer[0] == '\n')
{
  r++;
  char**tempData=(char**)malloc(sizeof(char*)*r);

  for(int a=0;a<r;a++)
  {
    tempData[a]=(char*)malloc(sizeof(char)*BUF_SIZE);
    memset(tempData[a],0,BUF_SIZE);
  }

  for(int a=0;a<r-1;a++)
  {
    strcpy(tempData[a],data[a]);
  }

   data=tempData;

   c=0;
}

else
{
  data[r-1][c]=buffer[0];
  c++;
  buffer[1]='\0';
}

   }

-1

fgets对您有用。这里有非常好的文档:-
http://www.cplusplus.com/reference/cstdio/fgets/

如果您不想使用fgets,以下方法适合您:

int readline(FILE *f, char *buffer, size_t len)
{
   char c; 
   int i;

   memset(buffer, 0, len);

   for (i = 0; i < len; i++)
   {   
      int c = fgetc(f); 

      if (!feof(f)) 
      {   
         if (c == '\r')
            buffer[i] = 0;
         else if (c == '\n')
         {   
            buffer[i] = 0;

            return i+1;
         }   
         else
            buffer[i] = c; 
      }   
      else
      {   
         //fprintf(stderr, "read_line(): recv returned %d\n", c);
         return -1; 
      }   
   }   

   return -1; 
}

1
事实是我不能这样做,因为我必须使用read(),因为这是我的作业要求。 - Wit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接