簡體   English   中英

C++:將讀取的二進制文件存儲到緩沖區中

[英]C++: Store read binary file into buffer

我正在嘗試讀取一個二進制文件並將其存儲在緩沖區中。 問題是,在二進制文件中有多個以空字符結尾的字符,但它們不在末尾,而是在其他二進制文本之前,所以如果我將文本存儲在 '\\0' 之后,它只會在緩沖。

例子:

char * a = "this is a\0 test";
cout << 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;
}

這就是我使用它的方式:

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

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

我只想提一下,有一種從二進制文件讀取到緩沖區的標准方法。

使用<cstdio>

char buffer[BUFFERSIZE];

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

使用<fstream>

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

當然,您之后如何處理緩沖區完全取決於您。

編輯:使用<cstdio>完整示例

#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;
}

問題絕對是緩沖區的寫入,因為您一次讀取一個字節。

如果您知道緩沖區中數據的長度,則可以強制 cout 繼續:

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

這應該給出以下輸出:

Hello
Hello  world

然而,這是一種變通方法,因為 cout 預計會輸出可打印的數據。 請注意,諸如 '\\0' 之類的不可打印字符的輸出取決於系統。

替代解決方案:

但是如果你操作二進制數據,你應該定義特殊的數據結構和打印。 這里有一些提示,以及一般原則的快速草稿:

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)); }
} ; 

然后你可以重載輸出運算符函數:

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;
}

而且你可以這樣使用它:

char *bf = "Hello\0 world"; 
Mybuff my; 
my.set(bf, 13);   // physical copy of memory
cout << my << endl;   // special output 
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;
    vec.reserve(file_size);
    vec.insert(vec.begin(),
               std::istream_iterator<unsigned char>(file),
               std::istream_iterator<unsigned char>());
    return (vec);
}

進而

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

我相信您的問題不在於讀取數據,而在於您嘗試打​​印數據的方式。

char * a = "this is a\0 test";
cout << a;

您向我們展示的這個示例打印了一個 C 字符串。 由於 C 字符串是一個以 '\\0' 結尾的字符序列,所以打印函數在第一個空字符處停止。 這是因為您需要通過使用特殊的終止字符(如此處的 '\\0')或知道其長度來知道字符串的結束位置。

因此,要打印整個數據,您必須知道它的長度並使用類似於您用於讀取它的循環。

你在 Windows 上嗎? 如果是這樣,您需要執行_setmode(_fileno(stdout), _O_BINARY);

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM