提问人:Brian 提问时间:9/8/2023 最后编辑:Brian 更新时间:9/13/2023 访问量:111
将无符号 char * 保存到文件并读取它会在 Windows 中产生意外结果
Saving unsigned char * to file and reading it produces unexpected results in Windows
问:
下面的代码在 Ubuntu 中工作正常。我正在使用 glad 和 glfw 为 openGL 加载纹理。
#include <vector>
#include <iostream>
#include <fstream>
using namespace std;
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
const bool loadResavedImages = true;
GLFWwindow* window;
void loadTexture( char const *filename, unsigned int &texture )
{
cout << filename << endl;
//static int texturesLoaded = 0;
glGenTextures( 1, &texture );
glBindTexture( GL_TEXTURE_2D, texture );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
int width, height, nrChannels;
stbi_set_flip_vertically_on_load( true );
unsigned char * data = NULL;
char newFileName[ 50 ];
snprintf( newFileName, sizeof(char) * ( strlen( filename ) - 3 ), "%s", filename );
ifstream readFile( newFileName );
if( loadResavedImages && readFile )
{
if( readFile.is_open() )
{
readFile >> width >> height;
data = new unsigned char[ width * height * 4 ];
readFile.read( (char *)data, width * height * 4 );
}
else
{
cout << "shouldnt happendfklgdskf" << endl;
}
readFile.close();
}
else
{
readFile.close();
data = stbi_load( filename, &width, &height, &nrChannels, 0 );
//saved images
//save to a file
ofstream saveFile( newFileName );
if( saveFile.is_open() )
{
saveFile << width << " " << height;
saveFile.write( (char *)&data[ 0 ], width * height * 4 );
}
else
cout << "WHY!?!?!SDSGGFGAGSSG" << endl;
saveFile.close();
}
for( int i = 0; i < width * height * 4; i++ )
{
cout << int( data[ i ] ) << " ";
}
if ( data )
{
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
glGenerateMipmap( GL_TEXTURE_2D );
}
else
{
cout << "failed to load texture " << filename <<endl;
exit( 0 );
}
if( loadResavedImages && readFile )
delete [] data;
else
{
stbi_image_free( data );
}
}
// main
int main()
{
glfwInit();
window = glfwCreateWindow( 500, 500, "Window", NULL, NULL );
glfwMakeContextCurrent( window );
if ( !gladLoadGLLoader( (GLADloadproc)glfwGetProcAddress ) )
{
cout << "Failed to initialize GLAD" << endl;
return 0;
}
//load texture
unsigned int texture;
loadTexture( "twirl.png", texture );
return 0;
}
当在 Ubuntu 上加载这个 400x400 纹理“旋转.png”时,它主要是空的透明空间,我们预计最后会得到一堆 0。
如果您从数据文件“twirl”保存并重新加载此纹理,则预计它会在 Ubuntu 上输出相同的内容。
如果在 Windows 上运行,则最后的输出会有所不同。我们的输出是
205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205 205
...等 而不是预期的空白空间
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
等。。
为什么这会发生在 Windows 上以及如何让它正确加载和保存?
答:
1赞
Brian
9/10/2023
#1
由于在默认文本模式下打开文件时会自动进行字符转换,因此更改了两行代码
ifstream readFile( newFileName );
//...
//...
ofstream saveFile( newFileName );
//...
自
ifstream readFile( newFileName, ios_base::binary );
//...
//...
ofstream saveFile( newFileName, ios_base::binary );
//...
修复了 Windows 中的问题。
评论
(char *)&data[ 0 ]
(char *)data
data
width
height
0
205
205
0xCD
0xCD
ifstream readFile( newFileName );
也许该文件甚至没有打开,所以它根本没有读取任何内容。您显示的输出将与该输出一致,这意味着如果您的代码无法读取,我希望数据与您在调试模式下运行 msvc 时收到的数据完全相同。原因是@RemyLebeau很久以前提到的。MSVC 在调试模式下用0xcd填充堆内存:stackoverflow.com/questions/127386/...msvc