Чтение из файла как шестнадцатеричное значение

0

У меня есть простой текстовый файл, и я хочу прочитать его как шестнадцатеричный. Например, следующий текст находится в текстовом файле "315c4e", теперь это фактически три байта, я хочу сохранить их в отдельных переменных (или в массиве, который когда-либо возможен). Например, первая переменная say uint8_t v1 должна содержать 31, другими словами, эта переменная должна иметь значение 00110001 (которое равно 31 в шестнадцатеричном формате).

Я занимаюсь криптографическим заданием в своем колледже, и мне приходилось считывать значения из текстовых файлов, содержащих шестнадцатеричные шифрованные тексты.

  • 2
    Если ваш текстовый файл содержит «315c4e», то это 6 символов ascii. Вы хотите преобразовать ascii в шестнадцатеричный код, а затем, например, найти stackoverflow.com/questions/3212848/…
  • 0
    Если вы читаете файл, который при печати отображает шестнадцатеричные данные, считайте этот файл как символьные данные и преобразуйте символы с помощью шестнадцатеричного двоичного алгоритма.
Теги:
file
hex

3 ответа

1

Нормальный setw и setprecision не будет ограничивать объем ввода для чтения двух символов, так что- то вроде этого:

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.

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";
    }
}
  • 0
    «315c4e» только для примера, входной файл может содержать гораздо больше символов.
  • 0
    @KhurramShehzad Вот почему я добавил «010c0e» и «Failure» для ввода
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);
}
  • 0
    Вы можете скопировать 2 символа в буфер char [3] с нулевым символом в конце и sscanf(buf,"%x",...); в теме.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню