【问题标题】:Random symbols appearing while writing into a file in C using write()使用 write() 在 C 中写入文件时出现的随机符号
【发布时间】:2019-08-10 02:52:13
【问题描述】:

我正在制作一个程序,它获取一个文件并创建一个新文件,该文件以相反的顺序包含原始文件的内容。

我可以做到,但是每次我写入文件时,所有内容都是正确的,但是在输出文件的开头有随机符号不断变化

我试图从这个来源https://norvig.com/big.txt反转文本

预期输出

iP ot denrut niaga eh dnA

.stnerap rehto gnitatimi yb deriuqca ylno dah ilisaV ecnirP
hcihw tub ,doohybab morf nerdlihc rieht dettep evah ohw stnerap ot
larutan ssenrednet lautibah fo enot sselerac eht htiw reh gnisserdda
dna rethguad sih ot yltnatsni gninrut ,deksa eh "?ayleL ,lleW"

虽然我有时会得到这个输出,但大多数时候我会得到这样的输出

����iP ot denrut niaga eh dnA

.stnerap rehto gnitatimi yb deriuqca ylno dah ilisaV ecnirP
hcihw tub ,doohybab morf nerdlihc rieht dettep evah ohw stnerap ot
larutan ssenrednet lautibah fo enot sselerac eht htiw reh gnisserdda
dna rethguad sih ot yltnatsni gninrut ,deksa eh "?ayleL ,lleW"

我不知道为什么我会得到这些特殊字符,它们始终不一样,它们不断变化,有时它们根本不存在并给出正确的输出。

#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>

size_t getFilesize(const char* filename) {
    struct stat st;
    if(stat(filename, &st) != 0) {
        return 0;
    }
    return st.st_size;   
}
 void reverse(char s[])
 {
     int i, j;
     char c;

     for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
         c = s[i];
         s[i] = s[j];
         s[j] = c;
     }
} 
 void itoa(int n, char s[])
 {
     int i, sign;

     if ((sign = n) < 0)  /* record sign */
         n = -n;          /* make n positive */
     i = 0;
     do {       /* generate digits in reverse order */
         s[i++] = n % 10 + '0';   /* get next digit */
     } while ((n /= 10) > 0);     /* delete it */
     if (sign < 0)
         s[i++] = '-';
     s[i] = '\0';
     reverse(s);
}  


int main( int argc , char *argv[] ){

    int sz,fd,fd2;
    int seekStatus;
    int writeStatus;
    int fileSize;
    char c[100000];
    fd = open(argv[1],O_RDONLY);

    if (fd < 0) {
    perror("input file missing");
    exit(1);
  }
    mkdir("Output", 0700);
    fd2 = open("Output/A.txt", O_WRONLY | O_CREAT | O_TRUNC, 0700);


    fileSize= getFilesize(argv[1]);

    int progress = 0;
    char strprogress[100];
    int chunk;
    chunk = 100000;
    int i = -1; 

    if (fileSize<chunk ){
        seekStatus=lseek(fd, -1, SEEK_END);
        while (seekStatus >= 0 ){
            sz=read(fd,c,1);
            writeStatus=write(fd2, c , 1);
         progress= ((-1.0 * i / fileSize)) * 100 ;


            itoa(progress,strprogress);

            write(1,"\r",1);
            write(1,strprogress, strlen(strprogress));

            i=i-1;
            seekStatus=lseek(fd, i, SEEK_END);
        }
    }
    else{

        int k = 1; // iterator 
        seekStatus=lseek(fd, -1*k*chunk, SEEK_END); 
        while (seekStatus >=0){
            sz = read(fd , c ,chunk);
            reverse(c);
            writeStatus=write(fd2, c , chunk);
            progress= ((-1.0 * chunk  * k / fileSize)) * 100 ;
            write(1,"\r",1);
            write(1,strprogress, strlen(strprogress));
            k=k+1;
            seekStatus=lseek(fd, -1*k*chunk, SEEK_END);
        }
        int remaining;
        remaining = fileSize - (k*chunk);
        if ( remaining != 0 ){
            seekStatus=lseek(fd, fileSize-remaining, SEEK_END);
            sz = read(fd , c ,remaining);
            write(fd2, c , remaining);
            write(1,"\r",1);
            write(1,"100",strlen("100"));
        }

    }


}

基本上,我在我的程序中尝试做的是我一次读取文件 1000 个字节,然后在剩余字节数少于千时将其写入文件,我只是写一个一个字节。我还有一个写入屏幕的进度状态。

【问题讨论】:

    标签: c linux unix operating-system


    【解决方案1】:

    首先,这段代码非常错误。

            sz = read(fd , c ,chunk);
            reverse(c);
            writeStatus=write(fd2, c , chunk);
    

    read 读取任意数量的字节。我无法想象想要反转任意数量,所以这可能不是你想要的。对于这个用例,我们似乎需要readblockwriteblock。你的图书馆里没有它们。

    ssize_t readblock(int fd, void *outptr, size_t len)
    {
        void *ptr = outptr;
        int delta;
        while (len) {
            delta = read(fd, ptr, len);
            if (delta < 0) return -1;
            if (delta == 0) { return ptr - outptr; }
            ptr += delta;
            len -= delta;
        }
        return ptr - outptr;
    }
    
    ssize_t writeblock(int fd, const void *inptr, size_t len)
    {
        const void *ptr = inptr;
        int delta;
        while (len) {
            delta = write(fd, ptr, len);
            if (delta < 0) return -1;
            if (delta == 0) { errno = ENOSPC; return -1; }
            ptr += delta;
            len -= delta;
        }
        return ptr - inptr;
    }
    

    如果您不使用gcc,则无法编译。这种代码就是gcc 扩展的for。将ptr 的类型更改为char *

    但是您的代码仍然无法正常工作。我们还需要解决一件事。最后的块不会发生。我们需要传入大小。

    int oldseekstatus = 0;
    //...
    
    seekstatus = lseek(fd, 0, SEEK_END);
    oldseekstatus = seekstatus;
    seekStatus=lseek(fd, -1*k*chunk, SEEK_END); 
    while (seekStatus >=0) {
       sz = read(fd , c ,chunk);
       reverse(c, sz);
       writeStatus=write(fd2, c , chunk);
       //...
       k=k+1;
       oldseekstatus = seekstatus;
       seekStatus=lseek(fd, -1*k*chunk, SEEK_END);
    }
    if (oldseekstatus > 0 {
       lseek(fd, 0, SEEK_END);
       sz = read(fd , c ,chunk);
       reverse(c, sz);
       writeStatus=write(fd2, c , chunk);
    }
    

    让我们来处理反向

    void reverse(char s[], size_t sz)
      //...
      for (i = 0, j = sz-1; i<j; i++, j--) {
      //...
    

    【讨论】:

      猜你喜欢
      • 2012-06-16
      • 2016-04-23
      • 2011-10-23
      • 1970-01-01
      • 2014-02-17
      • 2017-07-26
      • 2014-06-01
      • 2021-03-11
      • 1970-01-01
      相关资源
      最近更新 更多