Solution to unexpected termination of 0X1A in reading file

Keywords: Windows Qt Linux Ubuntu

In the integrated development environment of Windows (Qt, VC, VS all have this problem), write the C/C + + program about file reading. When it reads 0X1A, it ends unexpectedly. After debugging and checking, it is found that 0X1A is processed as 0XFF (EOF (- 1)) after reading, but there is no such problem of parsing error in Linux (tested in RedHat 6.4 and Ubuntu 14.04). For the reasons of this problem, please refer to: https://blog.csdn.net/zhoubl668/article/details/7054282 . Then there are two solutions:

1. Read in binary mode:

FILE * fp = fopen("file", "rb");//Read as binary stream

Take the file parsing of ". DCM" as an example (the information of new.dcm is parsed into hexadecimal and output to new.hex):

/*
 * 2018 April 20, 2016 16:37:10
 * Binary stream reading
 * 
*/
#include "stdafx.h"

#define STRING_BUFFER 16

char strbuf[STRING_BUFFER] = {0};

int main(void)
{
    size_t i = 0;

    FILE * fpr = fopen("F:\\new.dcm", "rb");//Read as binary stream
    FILE * fpw = fopen("F:\\new.hex", "w");//output file
    if(fpr == NULL || fpw == NULL){
        printf("open file failure at line:%d\n", __LINE__);
        exit(EXIT_FAILURE);
    }

    fprintf(fpw, "%08X: ", num);
    while(!feof(fpr)){//It can be judged directly by feof()
        unsigned char ch = fgetc(fpr);//Read one character at a time
        strbuf[num % STRING_BUFFER] = ch;//And record it in a 16 character line buffer
        fprintf(fpw, "%02X ", ch);//Write the character (1Byte, such as' A ') to the output file (change to 2byte, and' A 'corresponds to 0X41)
        num++;//Number of characters read plus 1
        if(num % 16 == 0){//Output file format, read 16 bytes and change to another line
            fprintf(fpw, "; ");
            for(i = 0; i<STRING_BUFFER; i++){//Resolve characters in buffer
                if(strbuf[i] > 31 && strbuf[i] < 127)
                    fprintf(fpw, "%c", strbuf[i]);
                else
                    fprintf(fpw, ".");
            }
            fprintf(fpw, "\n%08X: ", num);//Line feed
            memset(strbuf, 0, STRING_BUFFER);//Clear buffer
        }
    }

    fclose(fpr);
    fclose(fpw);

    printf("Complete!\n");
    return 0;
}

2. Determine whether the EOF (0XFF) encountered by file reading is caused by 0X1A or to the end of the file:

FILE * fp = fopen("file", "r");//Read as text file

fseek(fp, 0, SEEK_END);
const size_t len_file = ftell(fp);
fseek(fp, 0, SEEK_SET);

//After obtaining the length of the file, judge whether to end according to the number of characters read

Also read the above file:

#include "stdafx.h"

#define STRING_BUFFER 16

char strbuf[STRING_BUFFER] = {0};

int main(void)
{
    size_t num = 0, i = 0;

    FILE * fpr = fopen("F:\\new.dcm", "r");//Read as non binary stream
    FILE * fpw = fopen("F:\\new.hex", "w");
    if(fpr == NULL || fpw == NULL){
        printf("open file failure at line:%d\n", __LINE__);
        exit(EXIT_FAILURE);
    }

    //Get file length
    fseek(fpr, 0, SEEK_END);
    const size_t len_file = ftell(fpr);
    fseek(fpr, 0, SEEK_SET);

    printf("%d\n", len_file);

    fprintf(fpw, "%08X: ", num);
    //feof() cannot be used to judge, because 0X1A has been resolved to 0XFF when reading in text form
    while(num < len_file){//Determine whether to reach the end of the file according to the number of characters read and the length of the file
        unsigned char ch = fgetc(fpr);
        if((unsigned char)ch == 0XFF){//If 0XFF is read, judge whether it is caused by 0X1A
            strbuf[num % STRING_BUFFER] = 0X1A;
            fprintf(fpw, "1A ");
            fseek(fpr, num+1, SEEK_SET);
            //Fseek (FPR, 1, seek ﹣ cur) or fseek (FPR, fTell (FPR) + 1, seek ﹣ set) cannot be used;
            //Because if the end character EOF or 0X1A is encountered, the value of ftell(), that is, seek UU cur, will become a multiple of 4096
        }
        else{
            strbuf[num % STRING_BUFFER] = ch;
            fprintf(fpw, "%02X ", ch);
        }
        num++;
        if(num % 16 == 0){
            fprintf(fpw, "; ");
            for(i = 0; i<STRING_BUFFER; i++){
                if(strbuf[i] > 31 && strbuf[i] < 127)
                    fprintf(fpw, "%c", strbuf[i]);
                else
                    fprintf(fpw, ".");
            }
            fprintf(fpw, "\n%08X: ", num);
            memset(strbuf, 0, STRING_BUFFER);
        }
    }

    fclose(fpr);
    fclose(fpw);

    printf("Complete!\n");
    return 0;
}

Posted by silas101 on Mon, 30 Mar 2020 22:14:17 -0700