我正在尝试将图像读取到char数组中。这是我的尝试:
ifstream file ("htdocs/image.png", ios::in | ios::binary | ios::ate);
ifstream::pos_type fileSize;
char* fileContents;
if(file.is_open())
{
fileSize = file.tellg();
fileContents = new char[fileSize];
file.seekg(0, ios::beg);
if(!file.read(fileContents, fileSize))
{
cout << "fail to read" << endl;
}
file.close();
cout << "size: " << fileSize << endl;
cout << "sizeof: " << sizeof(fileContents) << endl;
cout << "length: " << strlen(fileContents) << endl;
cout << "random: " << fileContents[55] << endl;
cout << fileContents << endl;
}
这就是输出:
size: 1944
sizeof: 8
length: 8
random: ?
?PNG
有人能向我解释一下吗?位置8处是否有文件末尾字符?此示例取自cplusplus.com
运行Mac OS X并使用XCode进行编译。
-
返回文件的大小。
image.png
的大小是1944 bytes
。cout << "size: " << fileSize << endl;
-
返回
sizeof(char*)
,即环境中的8
请注意,在任何环境中,任何指针的大小都是相同的cout << "sizeof: " << sizeof(fileContents) << endl;
-
您正在读取的文件是一个二进制文件,因此它可能包含
0
作为有效数据。当您使用strlen
时,它会返回遇到0
之前的长度,如果您的文件是8
。cout << "length: " << strlen(fileContents) << endl;
-
返回文件开头的
56th location
(记住数组索引从0开始)处的字符。cout << "random: " << fileContents[55] << endl;
建议:
请记住使用:
解除分配fileContents
的动态内存分配
delete[] fileContents;
如果不这样做,您最终将创建内存泄漏。
fileSize-文件中的字节数。
sizeof(fileContents)-返回char*指针的大小。
strlen(fileContents)-统计字符数,直到找到值为"0"的字符为止。这显然是在8个字符之后——因为您正在读取二进制数据,所以这不是一个意外的结果。
cout<lt;fileContents-像strlen一样,cout写出字符,直到找到值为"0"的字符。从输出中看,有些字符似乎无法打印。
您的示例还有一些其他问题——例如,它没有释放所使用的内存。这里有一个稍微健壮一点的版本:
vector< char > fileContents;
{
ifstream file("htdocs/image.png", ios::in | ios::binary | ios::ate);
if(!file.is_open())
throw runtime_error("couldn't open htdocs/image.png");
fileContents.resize(file.tellg());
file.seekg(0, ios::beg);
if(!file.read(&fileContents[ 0 ], fileContents.size()))
throw runtime_error("failed to read from htdocs/image.png");
}
cout << "size: " << fileContents.size() << endl;
cout << "data:" << endl;
for( unsigned i = 0; i != fileContents.size(); ++i )
{
if( i % 65 == 0 )
cout << L"n';
cout << fileContents[ i ];
}
我对另一个问题的回答应该正是你想要的(尤其是关于将其读入vector<char>
的第二部分,你应该更喜欢它而不是数组
至于你的输出:
sizeof(fileContents)
返回char *
的大小,在您的系统中为8(我猜是64位)strlen
在第一个' '
处停止,就像输出操作符一样
您期待什么?png文件是二进制的,因此它们可能在某个地方包含' '
字符(具有数值0的字符)。
如果将png文件内容视为字符串(' ' terminated array of characters
)并将其打印为字符串,则它将在遇到第一个' '
字符后停止。
所以代码没有错,fileContents
正确地包含png文件(大小为1944字节)
size: 1944 // the png is 1944 bytes
sizeof: 8 // sizeof(fileContents) is the sizeof a pointer (fileContents type is char*) which is 8 bytes
length: 8 // the 9th character in the png file is ' ' (numeric 0)
random: ? // the 56th character in the png file
?PNG // the 5th-8th character is not printable, the 9th character is ' ' so cout stop here
使用无符号字符与二进制数据一起使用是一种很好的做法。由于所支持字体的限制,随机选择的字符可能无法在控制台窗口中正确显示。您也可以通过十六进制打印来验证相同的东西,并在十六进制编辑器中打开相同的文件来验证它。请不要忘记删除使用后分配的内存。