讀取檔案遇到0X1A意外終止的解決方案

來源:互聯網
上載者:User

在Windows的整合式開發環境中(Qt、VC、VS中均存在該問題)編寫有關檔案讀取的C/C++程式,出現讀取到0X1A的時候意外終止的情況,經調試檢查發現0X1A經過讀取之後被處理成0XFF(即EOF(-1)),但是Linux中(Redhat6.4以及Ubuntu14.04中測試)不存在這種解析錯誤的問題。關於出現這種問題的原因可參考:https://blog.csdn.net/zhoubl668/article/details/7054282。那麼解決辦法有兩種:

1、用二進位的方式讀取:

FILE * fp = fopen("file", "rb");//以二進位流讀取

以“.dcm”的檔案解析為例(將new.dcm的資訊解析成十六進位輸出到new.hex中去):

/* * 2018年4月20日16:37:10 * 二進位流的方式讀取 * */#include "stdafx.h"#define STRING_BUFFER 16char strbuf[STRING_BUFFER] = {0};int main(void){    unsigned int i = 0;    FILE * fpr = fopen("F:\\new.dcm", "rb");//以二進位流讀取    FILE * fpw = fopen("F:\\new.hex", "w");//輸出檔案    if(fpr == NULL || fpw == NULL){        printf("open file failure at line:%d\n", __LINE__);        exit(EXIT_FAILURE);    }    fprintf(fpw, "%08X: ", num);    while(!feof(fpr)){//直接用feof()可以判斷        int ch = fgetc(fpr);//一次讀取一個字元        strbuf[num % STRING_BUFFER] = (unsigned char)ch;//並記錄到16個字元一行的緩衝區中        fprintf(fpw, "%02X ", (unsigned char)ch);//將該字元(1Byte,如'A')寫到輸出檔案中(變成2Byte,'A'對應0X41)        num++;//讀取的字元數加1        if(num % 16 == 0){//輸出檔案格式化,讀取16個位元組換一行            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;}

2、判斷檔案讀取遇到EOF(0XFF)的原因是0X1A引起的還是到檔案末尾引起的:

FILE * fp = fopen("file", "r");//以文字檔讀取fseek(fp, 0, SEEK_END);const size_t len_file = ftell(fp);fseek(fp, 0, SEEK_SET);//擷取檔案長度後根據讀取的字元個數來判斷是否結束

同樣是對上面所述檔案進行讀取:

#include "stdafx.h"#define STRING_BUFFER 16char strbuf[STRING_BUFFER] = {0};int main(void){    unsigned int num = 0, i = 0;    FILE * fpr = fopen("F:\\new.dcm", "r");//以非二進位流讀取    FILE * fpw = fopen("F:\\new.hex", "w");    if(fpr == NULL || fpw == NULL){        printf("open file failure at line:%d\n", __LINE__);        exit(EXIT_FAILURE);    }    //擷取檔案長度    fseek(fpr, 0, SEEK_END);    const unsigned int len_file = ftell(fpr);    fseek(fpr, 0, SEEK_SET);    printf("%d\n", len_file);    fprintf(fpw, "%08X: ", num);    //不可以用feof()判斷,因為以文本形式讀取時0X1A已經被解析成0XFF    while(num < len_file){//根據讀取的字元數與檔案長度來判斷是否到達檔案末尾        int ch = fgetc(fpr);        if((unsigned char)ch == 0XFF){//如果讀取到0XFF,判斷是否是0X1A所引起的            strbuf[num % STRING_BUFFER] = 0X1A;            fprintf(fpw, "1A ");            fseek(fpr, num+1, SEEK_SET);            //不能用fseek(fpr, 1, SEEK_CUR);或fseek(fpr, ftell(fpr)+1, SEEK_SET);            //因為如果是遇到結束符EOF或0X1A時,ftell()的值即SEEK_CUR會變成4096的倍數        }        else{            strbuf[num % STRING_BUFFER] = (unsigned char)ch;            fprintf(fpw, "%02X ", (unsigned char)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;}

關於fgetc()傳回值為何為int以及對於EOF引起的另外一種讀取檔案意外結束的情況,可以參考fgetc函數的傳回值為什麼是 int 類型。這兩種意外結束不是一種情況,一個是邏輯不嚴謹導致的,一個就目前看來是微軟系統庫的問題。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.