从文件读取十六进制值

时间:2014-02-01 16:01:13

标签: c++ c file hex

我有一个简单的文本文件,我想把它读成十六进制。例如,以下文本在文本文件“315c4e”中,现在这些实际上是三个字节,我想将它们保存在单独的变量中(或者在数组中,这是可能的)。例如,第一个变量如uint8_t v1,应该包含31,换句话说,这个变量应该有00110001值(十六进制为31)。

我正在大学里做加密工作,我不得不从包含十六进制编码密文的文本文件中读取值。

3 个答案:

答案 0 :(得分:1)

普通setwsetprecision不会将读取的输入数量限制为两个字符,所以像这样:

infile >> std::setw(2) >> setprecision(2) >> std::hex >> ch;

......就行不通。在这种情况下,它可能就像读取2个字符的字符串一样简单,并自己进行转换:

#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <ctype.h>

unsigned char hstouc(std::string const &in) {
    static const std::string v{ "0123456789ABCDEF" };

    return v.find(toupper(in[0])) * 16 + v.find(toupper(in[1]));
} 

int main() {
    std::istringstream in{ "315c4e" };

    std::vector<unsigned char> vals;

    std::string temp;

    while (in >> std::setw(2) >> temp)
        vals.push_back(hstouc(temp));

    for (unsigned v : vals)
        std::cout << v << "\t";
}

如果您的输入是机器生成的,那可能就足够了。如果它可能是手动编辑(或任何其他可能产生错误输入的东西),您可能需要/想要在转换例程中添加一些错误检查。或者,您可能希望使用已经执行此类检查的strtoul之类的内容,然后将结果转换为unsigned char

答案 1 :(得分:0)

这个问题给了我以下功能的想法,我无法抗拒在这里发布。顺便说一下,有一个标准函数与此atob做同样的事情吗?

int atob(unsigned char c) {
    static char     x[256];
    int             i;
    if (x[0]==0) {
        for(i=0;i<256;i++) x[i] = -1; 
        for(i=0;i<10;i++) x[i+'0'] = i;
        for(i=0;i<6;i++) x[i+'a']= x[i+'A'] = i+10;
    }
    return(x[c]);
}

int main() {
    FILE    *ff;
    int     hex, c1, c2;

    ff = fopen("test.txt", "r");
    for(;;) {
        c1 = fgetc(ff);
        c2 = fgetc(ff);
        if (c2 == EOF) break;
        hex = atob(c1)*16 + atob(c2);
        printf("0x%02x ", hex);
    }
    fclose(ff);
}

答案 2 :(得分:0)

如果要读取由空格分隔的3个字节(6个字符)的元组:

#include <cstdint>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <vector>

struct ToHex
{
    typedef std::uint8_t byte;
    typedef std::istream::traits_type traits;
    byte& value;

    ToHex(byte& value)
    : value(value)
    {}

    void read(std::istream& stream) const {
        byte b[2];
        for(unsigned i = 0; i < 2; ++i) {
            traits::char_type ch = stream.get();
            if('0' <= ch && ch <= '9') b[i] = ch - '0';
            else if('a' <= ch && ch <= 'f') b[i] = ch - 'a' + 10;
            else if('A' <= ch && ch <= 'F') b[i] = ch - 'A' + 10;
            else {
                if(ch != traits::eof())
                    stream.putback(ch);
                stream.setstate(std::ios_base::failbit);
            }
        }
        value = b[0] * 16 + b[1]; // Rubbish if an extraction failed
    }
};

inline ToHex to_hex(ToHex::byte& value) {
    return ToHex(value);
}

inline std::istream& operator >> (std::istream& stream, const ToHex& value) {
    value.read(stream);
    return stream;
}

int main() {
    std::istringstream input(""
        "315c4e\n"
        "010c0e\n"
        "Failure");

    ToHex::byte a[3];
    input >> std::ws;
    while(input && ! input.eof()) {
        for(unsigned i = 0; i < 3; ++i) {
            input >> to_hex(a[i]);
        }
        if(input) {
            for(unsigned i = 0; i < 3; ++i)
                std::cout << std::hex << std::setw(2) << std::setfill('0') << (unsigned)a[i];
            std::cout  << '\n';
            input >> std::ws;
        }
    }
    if(input.fail()) {
        std::cerr << "Failure\n";
    }
}