我正在尝试读取一个二进制文件并将其存储在缓冲区中。问题是,在二进制文件中有多个以null结尾的字符,但它们不在末尾,而是在其他二进制文本之前,所以如果我将文本存储在"\0"之后,它只会将其删除到缓冲区中。
示例:
char * a = "this is a 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 %sn", 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;
}
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);
问题显然是缓冲区的写入,因为您一次读取一个字节。
如果你知道缓冲区中数据的长度,你可以强制cout继续:
char *bf = "Hello 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;
}
AN你可以这样使用它:
char *bf = "Hello world";
Mybuff my;
my.set(bf, 13); // physical copy of memory
cout << my << endl; // special output
我认为您的问题不在于读取数据,而在于如何打印数据。
char * a = "this is a test";
cout << a;
您给我们展示的这个例子打印了一个C字符串。由于C字符串是一个以"\0"结尾的字符序列,因此打印函数会在第一个空字符处停止。这是因为您需要通过使用特殊的终止字符(如此处的"\0"(或知道其长度来知道字符串的结束位置。
因此,要打印整个数据,您必须知道它的长度,并使用与读取它时类似的循环。
你在Windows上吗?如果是,则需要执行_setmode(_fileno(stdout), _O_BINARY);
包括<fcntl.h>
和<io.h>