C++:将读取的二进制文件存储到缓冲区中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24716250/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:48:21  来源:igfitidea点击:

C++: Store read binary file into buffer

c++bufferfgetsnull-terminated

提问by schacker22

I'm trying to read a binary file and store it in a buffer. The problem is, that in the binary file are multiple null-terminated characters, but they are not at the end, instead they are before other binary text, so if I store the text after the '\0' it just deletes it in the buffer.

我正在尝试读取一个二进制文件并将其存储在缓冲区中。问题是,在二进制文件中有多个以空字符结尾的字符,但它们不在末尾,而是在其他二进制文本之前,所以如果我将文本存储在 '\0' 之后,它只会在缓冲。

Example:

例子:

char * a = "this is a
bool CStream::Read  (int * _OutChar)
{
    if (!bInitialized)
        return false;

    int iReturn = 0;

     *_OutChar = fgetc (pFile);

    if (*_OutChar == EOF)
        return false;

    return true;
}
test"; cout << a;

This will just output: this is a

这只会输出: this is a

here's my real code:

这是我的真实代码:

this function reads one character

此函数读取一个字符

    char * SendData = new char[4096 + 1];

    for (i = 0; i < 4096; i++)
    {
        if (Stream.Read (&iChar))
            SendData[i] = iChar;
        else
            break;
    }

And this is how I use it:

这就是我使用它的方式:

char buffer[BUFFERSIZE];

FILE * filp = fopen("filename.bin", "rb"); 
int bytes_read = fread(buffer, sizeof(char), BUFFERSIZE, filp);

回答by Stian Svedenborg

I just want to mention that there is a standard way to read from a binary file into a buffer.

我只想提一下,有一种从二进制文件读取到缓冲区的标准方法。

Using <cstdio>:

使用<cstdio>

std::ifstream fin("filename.bin", ios::in | ios::binary );
fin.read(buffer, BUFFERSIZE);

Using <fstream>:

使用<fstream>

#include <cstdio>

const int BUFFERSIZE = 4096;    

int main() {
    const char * fname = "filename.bin";
    FILE* filp = fopen(fname, "rb" );
    if (!filp) { printf("Error: could not open file %s\n", fname); return -1; }

    char * buffer = new char[BUFFERSIZE];
    while ( (int bytes = fread(buffer, sizeof(char), BUFFERSIZE, filp)) > 0 ) {
        // Do something with the bytes, first elements of buffer.
        // For example, reversing the data and forget about it afterwards!
        for (char *beg = buffer, *end=buffer + bytes; beg < end; beg++, end-- ) {
           swap(*beg, *end);
        }
    }

    // Done and close.
    fclose(filp);

    return 0;
}

What you do with the buffer afterwards is all up to you of course.

当然,您之后如何处理缓冲区完全取决于您。

Edit: Full example using <cstdio>

编辑:完整示例使用 <cstdio>

char *bf = "Hello
Hello
Hello  world
world"; cout << bf << endl; cout << string(bf, 12) << endl;

回答by Christophe

The problem is definitievely the writing of your buffer, because you read a byte at a time.

问题绝对是缓冲区的写入,因为您一次读取一个字节。

If you know the length of the data in your buffer, you could force cout to go on:

如果您知道缓冲区中数据的长度,则可以强制 cout 继续:

struct Mybuff {   // special strtucture to manage buffers of binary data
    static const int maxsz = 512; 
    int size;
    char buffer[maxsz]; 
    void set(char *src, int sz)  // binary copy of data of a given length
    { size = sz; memcpy(buffer, src, max(sz, maxsz)); }
} ; 

This should give the following output:

这应该给出以下输出:

ostream& operator<< (ostream& os, Mybuff &b)
{
    for (int i = 0; i < b.size; i++) 
        os.put(isprint(b.buffer[i]) ? b.buffer[i]:'*');  // non printables replaced with *
    return os;
}

However this is a workaround, as cout is foreseent to output printable data. Be aware that the output of non printable chars such as '\0' is system dependent.

然而,这是一种变通方法,因为 cout 预计会输出可打印的数据。请注意,诸如 '\0' 之类的不可打印字符的输出取决于系统。

Alternative solutions:

替代解决方案:

But if you manipulate binary data, you should define ad-hoc data structures and printing. Here some hints, with a quick draft for the general principles:

但是如果你操作二进制数据,你应该定义特殊的数据结构和打印。这里有一些提示,以及一般原则的快速草稿:

char *bf = "Hello
char * a = "this is a
static std::vector<unsigned char> read_binary_file (const std::string filename)
{
    // binary mode is only for switching off newline translation
    std::ifstream file(filename, std::ios::binary);
    file.unsetf(std::ios::skipws);

    std::streampos file_size;
    file.seekg(0, std::ios::end);
    file_size = file.tellg();
    file.seekg(0, std::ios::beg);

    std::vector<unsigned char> vec(file_size);
    vec.insert(vec.begin(),
               std::istream_iterator<unsigned char>(file),
               std::istream_iterator<unsigned char>());
    return (vec);
}
test"; cout << a;
world"; Mybuff my; my.set(bf, 13); // physical copy of memory cout << my << endl; // special output

Then you could overload the output operator function:

然后你可以重载输出运算符函数:

auto vec = read_binary_file(filename);
auto src = (char*) new char[vec.size()];
std::copy(vec.begin(), vec.end(), src);

ANd you could use it like this:

而且你可以这样使用它:

##代码##

回答by Jan Smr?ina

I believe your problem is not in reading the data, but rather in how you try to print it.

我相信您的问题不在于读取数据,而在于您尝试打​​印数据的方式。

##代码##

This example you show us prints a C-string. Since C-string is a sequence of chars ended by '\0', the printing function stops at the first null char. This is because you need to know where the string ends either by using special terminating character (like '\0' here) or knowing its length.

您向我们展示的这个示例打印了一个 C 字符串。由于 C 字符串是一个以 '\0' 结尾的字符序列,所以打印函数在第一个空字符处停止。这是因为您需要通过使用特殊的终止字符(如此处的 '\0')或知道其长度来知道字符串的结束位置。

So, to print whole data, you must know the length of it and use a loop similar to the one you use for reading it.

因此,要打印整个数据,您必须知道它的长度并使用类似于您用于读取它的循环。

回答by Neil McGill

##代码##

and then

进而

##代码##

回答by Lasse Reinhold

Are you on Windows? If so you need to execute _setmode(_fileno(stdout), _O_BINARY);

你在 Windows 上吗?如果是这样,您需要执行_setmode(_fileno(stdout), _O_BINARY);

Include <fcntl.h>and <io.h>

包括<fcntl.h><io.h>