• 使用C++ c11标准的std::fstream的跨平台注意事项


    问题根因

    微软的visual studio 2015的VC编译器及以上版本都是支持大部分c11语法标准的,但在具体实现和工作原理上与GCC/G++依然有不少出入,导致即便写的代码是一致的,得到的结果却天差地别。甚至有时根本在另一平台上无法运行。

    案例展示

    #ifdef _WIN32
    #define PRV_DPT_LOGI(fmt, ...) fprintf(stdout, "PRV_DPT I: " fmt "
    ", __VA_ARGS__)
    #define PRV_DPT_LOGW(fmt, ...) fprintf(stdout, "PRV_DPT W: " fmt "
    ", __VA_ARGS__)
    #define PRV_DPT_LOGE(fmt, ...) fprintf(stdout, "PRV_DPT E: " fmt "
    ", __VA_ARGS__)
    #else
    #define PRV_DPT_LOGI(...) __android_log_print(ANDROID_LOG_INFO, "PRV_DPT", __VA_ARGS__)
    #define PRV_DPT_LOGW(...) __android_log_print(ANDROID_LOG_WARN, "PRV_DPT", __VA_ARGS__)
    #define PRV_DPT_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "PRV_DPT", __VA_ARGS__)
    #endif
    
    
    #ifdef _WIN32
    #define FAIL_EXIT(code) {system("pause");exit(code);}
    #else
    #define FAIL_EXIT(code) {exit(code);}
    #endif
    
    
    // the incorrect version
    // Ok on Linux/Android, but failed on Windows: incomplete bytes are read.
    void read_yuv_file(uint8_t * y_plane,
                       uint8_t * uv_plane,
                       uint64_t y_size,
                       uint64_t uv_size,
                       const char * file){
        std::fstream fs(file, std::ios::in);
        if (!fs.is_open()) {
    	PRV_DPT_LOGI("failed to open file [%s]!", file);
    	FAIL_EXIT(-1);
        }
        fs.read((char*)y_plane, y_size);
        uint64_t n_read = fs.gcount();
        if (n_read < y_size) {
    	PRV_DPT_LOGE("read_yuv_file failed: expected %lu bits, got %lu!", y_size, n_read);
    	FAIL_EXIT(-1);
        }
        fs.read((char*)uv_plane, uv_size);
        n_read = fs.gcount();
        if (n_read < uv_size) {
    	PRV_DPT_LOGE("read_yuv_file failed: expected %lu bits, got %lu!", uv_size, n_read);
    	FAIL_EXIT(-1);
        }
        fs.close();
    }
    

    上述代码在Linux/Android平台上是可以正确工作的,可以完整的将YUV格式的数据读取到对应的指针所指向的内存中;
    但当移植至windows平台上时,在visual studio 2015上却报错:

    PRV_DPT E: read_yuv_file failed: expected 691200 bits, got 0!
    program exit with code 0xffffff.
    

    显示文件读取不正确,读取到的字节数量为0。
    这是因为默认情况下,GCC默认读取格式是binary二进制流,而visual studio的vc则为text文本字符格式。
    因此,将缺省的默认读取格式指定清楚就可以跨平台无区别运行了。
    更正后的代码如下:

    #ifdef _WIN32
    #define PRV_DPT_LOGI(fmt, ...) fprintf(stdout, "PRV_DPT I: " fmt "
    ", __VA_ARGS__)
    #define PRV_DPT_LOGW(fmt, ...) fprintf(stdout, "PRV_DPT W: " fmt "
    ", __VA_ARGS__)
    #define PRV_DPT_LOGE(fmt, ...) fprintf(stdout, "PRV_DPT E: " fmt "
    ", __VA_ARGS__)
    #else
    #define PRV_DPT_LOGI(...) __android_log_print(ANDROID_LOG_INFO, "PRV_DPT", __VA_ARGS__)
    #define PRV_DPT_LOGW(...) __android_log_print(ANDROID_LOG_WARN, "PRV_DPT", __VA_ARGS__)
    #define PRV_DPT_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "PRV_DPT", __VA_ARGS__)
    #endif
    
    
    #ifdef _WIN32
    #define FAIL_EXIT(code) {system("pause");exit(code);}
    #else
    #define FAIL_EXIT(code) {exit(code);}
    #endif
    
    
    // the correct version
    // Working great on both Linux/Android and Windows.
    void read_yuv_file(uint8_t * y_plane,
                       uint8_t * uv_plane,
                       uint64_t y_size,
                       uint64_t uv_size,
                       const char * file){
        std::fstream fs(file, std::ios::in|std::ios::binary);
        if (!fs.is_open()) {
    	PRV_DPT_LOGI("failed to open file [%s]!", file);
    	FAIL_EXIT(-1);
        }
        fs.read((char*)y_plane, y_size);
        uint64_t n_read = fs.gcount();
        if (n_read < y_size) {
    	PRV_DPT_LOGE("read_yuv_file failed: expected %lu bits, got %lu!", y_size, n_read);
    	FAIL_EXIT(-1);
        }
        fs.read((char*)uv_plane, uv_size);
        n_read = fs.gcount();
        if (n_read < uv_size) {
    	PRV_DPT_LOGE("read_yuv_file failed: expected %lu bits, got %lu!", uv_size, n_read);
    	FAIL_EXIT(-1);
        }
        fs.close();
    }
    
  • 相关阅读:
    Python基础之函数与装饰器
    Python基础(字符编码与文件处理)
    周末练习(一)
    字典(习题)
    IOS代码库
    (转载)二叉树
    单链表的初始化和创建(尾插法)
    (转载)C语言单链表实现19个功能完全详解
    (转载)ios view的frame和bounds之区别(位置和大小)
    (转载)OC语法总结
  • 原文地址:https://www.cnblogs.com/thisisajoke/p/13260428.html
Copyright © 2020-2023  润新知