fread()或fseek()在win32上失败但不在mac32上失败

时间:2013-01-27 19:36:02

标签: c++

如果在mac32上运行,它运行正常;如果我在win32上运行它,我会在像素139处得到一个意外的文件结束,如果我注释掉fseek(在我的测试.tga图像上只搜索0个字节,所以不应该有所作为)我得到了在像素35处意外结束文件。但是标题读取完全正常;这只是数据。

对于不同的编译器/架构,2个函数的实现方式是否不同?

struct TGAHeader
{   
    char    idlength;
    char    colourmaptype;
    char    datatypecode;
    short   colourmaporigin;
    short   colourmaplength;
    char    colourmapdepth;
    short   x_origin;
    short   y_origin;
    short   width;
    short   height;
    char    bitsperpixel;
    char    imagedescriptor;
};    

bool read()
{
    printf("Reading TGA file...\n");

    header.idlength = fgetc(TGAFile);
    header.colourmaptype = fgetc(TGAFile);
    header.datatypecode = fgetc(TGAFile);
    fread(&header.colourmaporigin,2,1,TGAFile);
    fread(&header.colourmaplength,2,1,TGAFile);
    header.colourmapdepth = fgetc(TGAFile);
    fread(&header.x_origin,2,1,TGAFile);
    fread(&header.y_origin,2,1,TGAFile);
    fread(&header.width,2,1,TGAFile);
    fread(&header.height,2,1,TGAFile);
    header.bitsperpixel = fgetc(TGAFile);
    header.imagedescriptor = fgetc(TGAFile);

    printf("...TGA file has been read\n\n");
    printf("ID length:         %d\n",header.idlength);
    printf("Colourmap type:    %d\n",header.colourmaptype);
    printf("Image type:        %d\n",header.datatypecode);
    printf("Colour map offset: %d\n",header.colourmaporigin);
    printf("Colour map length: %d\n",header.colourmaplength);
    printf("Colour map depth:  %d\n",header.colourmapdepth);
    printf("X origin:          %d\n",header.x_origin);
    printf("Y origin:          %d\n",header.y_origin);
    printf("Width:             %d\n",header.width);
    printf("Height:            %d\n",header.height);
    printf("Bits per pixel:    %d\n",header.bitsperpixel);
    printf("Descriptor:        %d\n",header.imagedescriptor);

    bytesToRead = header.bitsperpixel / 8;

    if(!errCheck())
    {
        m_bLoaded = false;
        return false;
    }
    //set stream position indicator to the start of the data
    fseek(TGAFile,(header.idlength+(header.colourmaptype * header.colourmaplength)),SEEK_CUR);

    //allocate space to store data
    releaseTGAData();
    pixelData = new unsigned char*[header.width*header.height];
    for(int i=0;i<header.width*header.height;i++)
        pixelData[i] = new unsigned char[bytesToRead];

    for(int i=0;i<header.width * header.height;i++)
    {
        if (fread(pixelData[i],1,bytesToRead,TGAFile) != bytesToRead)
        {
            printf("Unexpected end of file at pixel %d\n",i);
            m_bLoaded = false;
            releaseTGAData();
            return false;
        }
    }
    fclose(TGAFile);

    return true;
}

编辑:这是加载函数

bool load(const char* inFilename = NULL)
{
    m_bLoaded = false;
    if(NULL!=filename)
        delete [] filename;
    filename = new char[128];

    //if the filename has not been selected by the programmer
    if(NULL==inFilename)
    {
        //ask the user for it
        printf("please enter the filename of an uncompressed TGA file:\n");
        scanf("%s", filename);
    }
    else sprintf(filename, inFilename);

    if ((TGAFile = fopen(filename,"r")) == NULL)
    {
        printf("File open failed, please try again\n");
        return false;
    }
    if(!read())
        return false;

    m_bLoaded=true;
    return true;
}

3 个答案:

答案 0 :(得分:2)

问题是您以文本模式打开文件。在Windows上,输入函数将字节序列0x0d 0x0a(Windows换行序列"\r\n")转换为单个字符。

Windows很可能也会检查字节0x19(我认为)是 CTRL - Z 并且是文件结尾的字符视窗。

答案 1 :(得分:1)

您的问题很可能是由处理非二进制文件时窗口处理文件读取的不同方式引起的,但更有效的解决方案是使用#pragma pack或属性(alligned( 1))对于头部结构并在一个fread调用中读取整个头部

答案 2 :(得分:1)

由于文件包含二进制数据,因此必须在Windows上调用"rb"时使用fopen()作为打开模式。在Unix上,b是可选的(但无害),因此如果您的代码是可移植的,请在两个系统上使用相同的模式。

如果您在Windows上打开文件而未指定b,则会获得“CRLF&#39;映射(因此回车换行序列"\r\n"将映射到换行符"\n" - 其中换行符只是换行符的另一个名称)。并且第一个control-Z字节标记文件的结尾。