有没有办法在linux中创建虚拟文件描述符?

时间:2021-02-03 02:48:22

I have opened one file with following way:

我用以下方式打开了一个文件:

fp = fopen("some.txt","r");

Now in this file the 1st some bytes lets say 40 bytes are unnecessary junk of data so I want to remove them. But I cannot delete that data from that file, modify or create duplicates of that file without that unnecessary data.

现在在这个文件中,第一个字节可以说40个字节是不必要的数据垃圾,所以我想删除它们。但我无法从该文件中删除该数据,修改或创建该文件的副本而没有那些不必要的数据。

So I want to create another dummy FILE pointer which points to the file and when I pass this dummy pointer to any another function that does the following operation:

所以我想创建另一个指向文件的虚拟FILE指针,当我将这个虚拟指针传递给执行以下操作的任何其他函数时:

  fseek ( dummy file pointer , 0 , SEEK_SET );

then it should set the file pointer at 40th position in my some.txt.

然后它应该将文件指针设置在some.txt中的第40个位置。


But the function accepts a file descriptor so i need to pass a file descriptor which will treat the file as those first 40 bytes were never in the file.

但是该函数接受一个文件描述符,所以我需要传递一个文件描述符,它将文件视为文件中从未出现的前40个字节。


In short that dummy descriptor should treat the file as those 40 bytes were not in that file and all positioning operations should be with respect to that 40th byte counting as the is 1st byte.

简而言之,虚拟描述符应该将文件视为那个40字节不在该文件中,并且所有定位操作应该相对于第40个字节计数为第1个字节。

5 个解决方案

#1


2  

fseek ( dummy file pointer , 0 , SEEK_SET );

fseek(虚拟文件指针,0,SEEK_SET);

In short that dummy pointer should treat the file as there is no that 40 byte in that file and all position should be with respect to that 40th byte as counting as it is 1st byte.

简而言之,虚指针应该处理该文件,因为该文件中没有该40字节,并且所有位置都应该相对于该第40字节计数,因为它是第1字节计数。

You have conflicting requirements, you cannot do this with the C API.

您的要求存在冲突,您无法使用C API执行此操作。

SEEK_SET always refers to the absolute position in the file, which means if you want that command to work, you have to modify the file and remove the junk.

SEEK_SET始终引用文件中的绝对位置,这意味着如果您希望该命令起作用,则必须修改该文件并删除垃圾。

On linux you could write a FUSE driver that would present the file like it was starting from the 40th byte, but that's a lot of work. I'm only mentioned this because it's possible to solve the problem you've created, but it would be quite silly to actually do this.

在linux上,您可以编写一个FUSE驱动程序,它将文件显示为从第40个字节开始,但这是很多工作。我只是提到这个,因为它可以解决你创建的问题,但实际上这样做真的很傻。

The simplest thing of course would be just to abandon this emulating layer idea you're looking for, and write code that can handle that extra header junk.

最简单的事情当然是放弃你正在寻找的这个模拟层的想法,并编写可以处理额外的头垃圾的代码。

#2


4  

Easy.

#define CHAR_8_BIT    (0)
#define CHAR_16_BIT   (1)
#define BIT_WIDTH     (CHAR_8_BIT)

#define OFFSET        (40)

FILE* fp = fopen("some.txt","r");
FILE* dummy = NULL;

#if (BIT_WIDTH == CHAR_8_BIT)
dummy = fseek (fp, OFFSET*sizeof(char), SEEK_SET);
#else
dummy = fseek (fp, OFFSET*sizeof(wchar_t), SEEK_SET);
#endif

The SEEK_SET macro indicates beginning of file, and depending on whether you are using 8-bit characters (ASCI) or 16-bit characters (eg: UNICODE) you will step 40 CHARACTERS forward from the beginning of your file pointer, and assign that pointer/address to dummy.

SEEK_SET宏指示文件的开头,并且根据您使用的是8位字符(ASCI)还是16位字符(例如:UNICODE),您将从文件指针的开头向前步进40个CHARACTERS,并指定该指针/地址到虚拟。

Good luck!

These links will likely be helpful as well:

这些链接也可能会有所帮助:

char vs wchar_t

char vs wchar_t

http://www.cplusplus.com/reference/clibrary/cstdio/fseek/

If you want, you can just convert a file descriptor to a file pointer via the fdopen() call.

如果需要,可以通过fdopen()调用将文件描述符转换为文件指针。

http://linux.die.net/man/3/fdopen

#3


2  

If you want to remove the first 40 bytes of a file on the disk without creating another file, then you can copy the content from the 41th byte and onwards into a buffer, then write it back at offset -40. Then use ftruncate (a POSIX library in unistd.h) to truncate at (filesize - 40) offset.

如果要在不创建其他文件的情况下删除磁盘上文件的前40个字节,则可以将第41个字节中的内容复制到缓冲区中,然后将其写回偏移量-40。然后使用ftruncate(unistd.h中的POSIX库)截断(filesize - 40)偏移量。

#4


1  

I wrote a small code with what i understood from your question.

我用你的问题理解我写了一个小代码。

#include<stdio.h>

void readIt(FILE *afp)
{
    char mystr[100];
    while ( fgets (mystr , 100 , afp) != NULL )
       puts (mystr);
}
int main()
{
    FILE * dfp = NULL;
    FILE * fp = fopen("h4.sql","r");
    if(fp != NULL)
    {
        fseek(fp,10,SEEK_SET);
        dfp = fp;
        readIt(dfp);
        fclose(fp);
    }
}

The readIt() is reading the file from the 11 byte. Is this what you are expecting or something else?

readIt()从11字节读取文件。这是你期待的还是别的什么?

#5


1  

I haven't actually tried this, but I think you should be able to use mmap (with the MAP_SHARED option) to get your file mapped into your address space, and then fmemopen to get a FILE* that refers to all but the first 40 bytes of that buffer.

我实际上没有尝试过这个,但我认为你应该能够使用mmap(使用MAP_SHARED选项)将你的文件映射到你的地址空间,然后fmemopen得到一个引用除了前40个之外的所有文件的FILE *该缓冲区的字节数。

This gives you a FILE* (as you describe in the body of your question), but I believe not a file descriptor (as in the title and elsewhere in the question). The two are not the same, and AFAIK the FILE* created with fmemopen does not have an associated file descriptor.

这给你一个文件*(正如你在问题正文中描述的那样),但我认为不是文件描述符(如标题和问题的其他部分)。两者不一样,用fmemopen创建的AFAIK FILE *没有关联的文件描述符。

#1


2  

fseek ( dummy file pointer , 0 , SEEK_SET );

fseek(虚拟文件指针,0,SEEK_SET);

In short that dummy pointer should treat the file as there is no that 40 byte in that file and all position should be with respect to that 40th byte as counting as it is 1st byte.

简而言之,虚指针应该处理该文件,因为该文件中没有该40字节,并且所有位置都应该相对于该第40字节计数,因为它是第1字节计数。

You have conflicting requirements, you cannot do this with the C API.

您的要求存在冲突,您无法使用C API执行此操作。

SEEK_SET always refers to the absolute position in the file, which means if you want that command to work, you have to modify the file and remove the junk.

SEEK_SET始终引用文件中的绝对位置,这意味着如果您希望该命令起作用,则必须修改该文件并删除垃圾。

On linux you could write a FUSE driver that would present the file like it was starting from the 40th byte, but that's a lot of work. I'm only mentioned this because it's possible to solve the problem you've created, but it would be quite silly to actually do this.

在linux上,您可以编写一个FUSE驱动程序,它将文件显示为从第40个字节开始,但这是很多工作。我只是提到这个,因为它可以解决你创建的问题,但实际上这样做真的很傻。

The simplest thing of course would be just to abandon this emulating layer idea you're looking for, and write code that can handle that extra header junk.

最简单的事情当然是放弃你正在寻找的这个模拟层的想法,并编写可以处理额外的头垃圾的代码。

#2


4  

Easy.

#define CHAR_8_BIT    (0)
#define CHAR_16_BIT   (1)
#define BIT_WIDTH     (CHAR_8_BIT)

#define OFFSET        (40)

FILE* fp = fopen("some.txt","r");
FILE* dummy = NULL;

#if (BIT_WIDTH == CHAR_8_BIT)
dummy = fseek (fp, OFFSET*sizeof(char), SEEK_SET);
#else
dummy = fseek (fp, OFFSET*sizeof(wchar_t), SEEK_SET);
#endif

The SEEK_SET macro indicates beginning of file, and depending on whether you are using 8-bit characters (ASCI) or 16-bit characters (eg: UNICODE) you will step 40 CHARACTERS forward from the beginning of your file pointer, and assign that pointer/address to dummy.

SEEK_SET宏指示文件的开头,并且根据您使用的是8位字符(ASCI)还是16位字符(例如:UNICODE),您将从文件指针的开头向前步进40个CHARACTERS,并指定该指针/地址到虚拟。

Good luck!

These links will likely be helpful as well:

这些链接也可能会有所帮助:

char vs wchar_t

char vs wchar_t

http://www.cplusplus.com/reference/clibrary/cstdio/fseek/

If you want, you can just convert a file descriptor to a file pointer via the fdopen() call.

如果需要,可以通过fdopen()调用将文件描述符转换为文件指针。

http://linux.die.net/man/3/fdopen

#3


2  

If you want to remove the first 40 bytes of a file on the disk without creating another file, then you can copy the content from the 41th byte and onwards into a buffer, then write it back at offset -40. Then use ftruncate (a POSIX library in unistd.h) to truncate at (filesize - 40) offset.

如果要在不创建其他文件的情况下删除磁盘上文件的前40个字节,则可以将第41个字节中的内容复制到缓冲区中,然后将其写回偏移量-40。然后使用ftruncate(unistd.h中的POSIX库)截断(filesize - 40)偏移量。

#4


1  

I wrote a small code with what i understood from your question.

我用你的问题理解我写了一个小代码。

#include<stdio.h>

void readIt(FILE *afp)
{
    char mystr[100];
    while ( fgets (mystr , 100 , afp) != NULL )
       puts (mystr);
}
int main()
{
    FILE * dfp = NULL;
    FILE * fp = fopen("h4.sql","r");
    if(fp != NULL)
    {
        fseek(fp,10,SEEK_SET);
        dfp = fp;
        readIt(dfp);
        fclose(fp);
    }
}

The readIt() is reading the file from the 11 byte. Is this what you are expecting or something else?

readIt()从11字节读取文件。这是你期待的还是别的什么?

#5


1  

I haven't actually tried this, but I think you should be able to use mmap (with the MAP_SHARED option) to get your file mapped into your address space, and then fmemopen to get a FILE* that refers to all but the first 40 bytes of that buffer.

我实际上没有尝试过这个,但我认为你应该能够使用mmap(使用MAP_SHARED选项)将你的文件映射到你的地址空间,然后fmemopen得到一个引用除了前40个之外的所有文件的FILE *该缓冲区的字节数。

This gives you a FILE* (as you describe in the body of your question), but I believe not a file descriptor (as in the title and elsewhere in the question). The two are not the same, and AFAIK the FILE* created with fmemopen does not have an associated file descriptor.

这给你一个文件*(正如你在问题正文中描述的那样),但我认为不是文件描述符(如标题和问题的其他部分)。两者不一样,用fmemopen创建的AFAIK FILE *没有关联的文件描述符。