【问题标题】:Convert large block of binary into text in C将大块二进制转换为C中的文本
【发布时间】:2021-05-08 03:01:38
【问题描述】:

我有一个项目,我应该通过 getchar() 函数接收一个文件并将其中的二进制字符转换为文本。

这是我的代码,它一次只能为一个生成正确的 ASCII 数字。我不知道如何读取整个文本文件的二进制文件并进行转换:

#include <stdio.h>
#include <string.h>

typedef unsigned char byte;
typedef unsigned int uint;

int strbin_to_dec(const char *);

int main(void) {



char * wbin = "01001001";
  int c = 0;

  printf("%s to ascii %d.\n", wbin, strbin_to_dec(wbin));
  printf("The character is %c", strbin_to_dec(wbin));
  return 0;
}

int strbin_to_dec(const char * str) {
  uint result = 0;
  for (int i = strlen(str) - 1, j = 0; i >= 0; i--, j++) {
    byte k = str[i] - '0';
    k <<= j;
    result += k;
  }
  return result;
}

当我在变量“wbin”中输入一个字符的二进制值时,上面的代码可以工作,但我无法格式化它以接受来自 getchar() 的输入,因为 getchar 给出了一个 int 类型。上面的代码产生了结果:

01001001 to ascii 73.
The character is I

我要翻译的文件如下所示:

0010001001001000011011110111011100100000011011110110011001110100011001010110111000100000011010000110000101110110011001010010000001001001001000000111001101100001011010010110010000100000011101000110111100100000011110010110111101110101
011101000110100001100001011101000010000001110111011010000110010101101110001000000111100101101111011101010010000001101000011000010111011001100101001000000110010101101100011010010110110101101001011011100110000101110100011001010110010000100000011101000110100001100101001000000110100101101101011100000110111101110011011100110110100101100010011011000110010100101100
01110111011010000110000101110100011001010111011001100101011100100010000001110010011001010110110101100001011010010110111001110011001011000010000001101000011011110111011101100101011101100110010101110010001000000110100101101101011100000111001001101111011000100110000101100010011011000110010100101100
01101101011101010111001101110100001000000110001001100101001000000111010001101000011001010010000001110100011100100111010101110100011010000011111100100010
0010110101010011011010010111001000100000010000010111001001110100011010000111010101110010001000000100001101101111011011100110000101101110001000000100010001101111011110010110110001100101001011000010000001010100011010000110010100100000010100110110100101100111011011100010000001001111011001100010000001000110011011110111010101110010

【问题讨论】:

  • 您的问题是“如何从文件中读取字符”?事实上,看起来您甚至不需要从文件中读取,而是从重定向的stdin
  • 为什么不使用循环?
  • 但您希望它只翻译一个字符或整个字符串?
  • @EugeneSh。如果我正确地跟随你,那么这就是我正在做的事情,但我不知道现在如何翻译整个事情。从我使用 FILE 对象可以看出,这与读取文件不同。我是 C 新手,如果我的术语有问题,我深表歉意。
  • @GonçaloBastos 我需要翻译我帖子底部的整个文本块,这是一本书的引述,但我不知道如何遍历二进制文件并获取我想要的内容需要提供给函数。

标签: c binary bitwise-operators


【解决方案1】:

这是一项简单的任务,只需使用位移即可完成。另外,为了性能,下面使用fread,而不是使用getchar

此实现使用最少的 RAM(不使用 malloc),没有慢速字符串解析或数学函数,例如 strlenstrtolpow,并且可以处理任何无限大小/长度的流,包括截断的流不是 8 字节的倍数。

用法: ./a.out &lt; data.txt &gt; out.txt

#include <stdio.h>

int main(int argc, char * argv[])
{
  unsigned char byte = 0;
  int bits = 0;

  for(;;)
  {
    char buffer[1024];
    int len = fread(buffer, 1, sizeof(buffer), stdin);

    // if there was a read error or EOF, stop
    if (len <= 0)
      break;

    for(int i = 0; i < len; ++i)
    {
      switch(buffer[i])
      {
        // if a binary 1, turn on bit zero
        case '1':
          byte |= 1;
          break;

        // if a binary 0, do nothing
        case '0':
          break;

        // if antyhing else, skip
        default:
          continue;
      }

      // incrment the counter, if we dont yet have 8 bits
      // shift all the bits left by one
      if (++bits < 8)
        byte <<= 1;
      else
      {
        // write out the complete byte
        fwrite(&byte, 1, 1, stdout);

        // reset for the next byte
        bits = 0;
        byte = 0;
      }
    }
  }

  // write out any remaining data if the input was not a multiple of 8 in length.
  if (bits)
    fwrite(&byte, 1, 1, stdout);

  return 0;
}

输入:

0010001001001000011011110111011100100000011011110110011001110100011001010110111000100000011010000110000101110110011001010010000001001001001000000111001101100001011010010110010000100000011101000110111100100000011110010110111101110101
011101000110100001100001011101000010000001110111011010000110010101101110001000000111100101101111011101010010000001101000011000010111011001100101001000000110010101101100011010010110110101101001011011100110000101110100011001010110010000100000011101000110100001100101001000000110100101101101011100000110111101110011011100110110100101100010011011000110010100101100
01110111011010000110000101110100011001010111011001100101011100100010000001110010011001010110110101100001011010010110111001110011001011000010000001101000011011110111011101100101011101100110010101110010001000000110100101101101011100000111001001101111011000100110000101100010011011000110010100101100
01101101011101010111001101110100001000000110001001100101001000000111010001101000011001010010000001110100011100100111010101110100011010000011111100100010
0010110101010011011010010111001000100000010000010111001001110100011010000111010101110010001000000100001101101111011011100110000101101110001000000100010001101111011110010110110001100101001011000010000001010100011010000110010100100000010100110110100101100111011011100010000001001111011001100010000001000110011011110111010101110010

输出:

"How often have I said to youthat when you have eliminated the impossible,whatever remains, however improbable,must be the truth?"-Sir Arthur Conan Doyle, The Sign Of Four

【讨论】:

    【解决方案2】:

    这是我做的功能!我不知道您是否将该文件用作执行参数,例如:./text.exe -f binary.txt!但我不会在程序中添加条目!文件是我自己定义的!

    我已经创建了一个写入文件的函数,但是如果你想使用 ./text.exe -f binary.txt > translatefile.txt 之类的命令,你可以简单地删除函数 write_to_file!不要忘记删除您不想要的打印,因为参数“>”将打印所有内容!

    代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void binary_to_char(char *str);
    void write_to_file(char *text);
    
    int main(void)
    {
    
        printf("Getting line from file\n");
    
        FILE *file;
        char *line = NULL;
        size_t len = 0;
        ssize_t stringLength;
    
        file = fopen("binary.txt", "r");
        if (file == NULL)
        {
            fprintf(stderr, "[ERROR]: cannot open file -- binary.txt");
            perror("");
            exit(1);
        }
    
        while ((stringLength = getline(&line, &len, file)) != -1)
        {
            printf("\n%s", line);
            binary_to_char(line);
        }
        free(line);
        fclose(file);
    
        return 0;
    }
    
    void binary_to_char(char *str)
    {
        char binary[9];
        char *text = malloc((strlen(str) + 1) * sizeof(char));
        char c;
        int pos = 0;
        int letter_pos = 0;
        printf("\nConverting into characters\n");
        for (size_t j = 0; j < strlen(str) / 8; j++)
        {
            for (int i = 0; i < 8; i++)
            {
                binary[i] = str[pos];
                pos++;
            }
            c = strtol(binary, 0, 2);
            text[letter_pos] = c;
            letter_pos++;
        }
        printf("\n%s\n", text);
        write_to_file(text);
        free(text);
    }
    
    void write_to_file(char *text)
    {
        printf("\nContent saved to translatedfile.txt\n");
        FILE *fp;
    
        fp = fopen("translatedfile.txt", "w+");
        fprintf(fp, "%s", text);
    
        fclose(fp);
    }
    

    文件 binary.txt 的内容:

    001000100100100001101111011101110010000001101111011001100111010001100101011011100010000001101000011000010111011001100101001000000100100100100000011100110110000101101001011001000010000001110100011011110010000001111001011011110111010101110100011010000110000101110100001000000111011101101000011001010110111000100000011110010110111101110101001000000110100001100001011101100110010100100000011001010110110001101001011011010110100101101110011000010111010001100101011001000010000001110100011010000110010100100000011010010110110101110000011011110111001101110011011010010110001001101100011001010010110001110111011010000110000101110100011001010111011001100101011100100010000001110010011001010110110101100001011010010110111001110011001011000010000001101000011011110111011101100101011101100110010101110010001000000110100101101101011100000111001001101111011000100110000101100010011011000110010100101100011011010111010101110011011101000010000001100010011001010010000001110100011010000110010100100000011101000111001001110101011101000110100000111111001000100010110101010011011010010111001000100000010000010111001001110100011010000111010101110010001000000100001101101111011011100110000101101110001000000100010001101111011110010110110001100101001011000010000001010100011010000110010100100000010100110110100101100111011011100010000001001111011001100010000001000110011011110111010101110010
    

    【讨论】:

    • 这个答案很差。它不仅需要先读取整个输入(对于读取stdin 并限制输入大小无用),它还使用mallocstrlenstrol 只是为了做一个简单的事情可以做的事情位移操作。
    • @Geoffrey 好的,我只是想帮忙!
    【解决方案3】:

    从文件中读取所有输入,并一次将 8 个字符传递给转换器函数以返回一个字符。每个 char 为 8 位,文件中的每个字符代表 1 位。

    char string_to_character(char * in)
    {
      char ret = 0;
      int i;
      for(i = 7; i >= 0; i--)
        if(in[i] == '1')
          ret += 1 << (7 - i);
    
      return ret;
    }
    

    此函数会将文件中的每 8 个字符解码为一个字符。只需为整个输入字符串调用偏移量为 8 个字符的函数并将结果保存在某处。

    编辑:一定要包含并链接数学库 math.h。 编辑 2:应该 >= 不是 >

    用于循环...

    假设您将整个文件作为一个长字符串。

    int num_chars = (sizeof(input) / sizeof(char)) / 8;
    int i;
    char output[num_chars + 1];
    for(i = 0; i < num_chars; i++)
       output[i] = string_to_character(input + (i * 8));
    
    printf("%s", output);
    

    这是我从程序中得到的结果

    “我有多少次对你说,当你排除了不可能的事情后,剩下的事情,无论多么不可能,都必须是事实?”——亚瑟爵士 柯南道尔,四的标志

    编辑:左移位与 pow

    【讨论】:

    • 这不仅需要读入整个文件,还需要使用pow 来完成一个简单的OR 可以完成的事情,而左移简直太疯狂了。
    • @Geoffrey Fair,从长远来看,左移效率更高。问题需要读取整个文件,这是不可避免的。
    • 是的,需要读取整个文件,但是您不需要将整个文件缓冲到 RAM 中,当您按照 OP 的要求从 stdin 读取时也不需要。输入的长度是不确定的,可能是无限的。看我的回答。
    • 它肯定会运行得更慢,因为磁盘访问时间比内存访问慢数百倍 说什么?无论如何,您都必须从磁盘上读取文件。这是一个从标准输入到malloc'ed-region 的读取,从-binary-out-of-malloc'ed-region 转换,与从-binary-off-of-stdin 转换的问题。我看不出后者不是胜利。另见this questionits answer
    • 为什么要反复阅读文件?我认为单次通过就可以了。
    猜你喜欢
    • 2014-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-04
    • 1970-01-01
    • 1970-01-01
    • 2013-08-20
    • 1970-01-01
    相关资源
    最近更新 更多