本文共 6531 字,大约阅读时间需要 21 分钟。
1、简介
uu 编码 将3字节BIN数据转换成4字节可打印ASCII字符。
uuencode 编码方式用于将任意的二进制文件转换为文本文件,比如email.转换后的文件中仅包含可打印字符. uuencode 运算法则将连续的 3字节编码转换成 4字节(8-bit 到 6-bit)的可打印字符.
2、示例 从二进制文件中读取 3字节的数据, 表示如下(a7 表示 a字节的第 7位): a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0 c7c6c5c4c3c2c1c0 转换它们到4字节里为如下所示: 0 0 a7a6a5a4a3a2 0 0 a1a0b7b6b5b4 0 0 b3b2b1b0c7c6 0 0 c5c4c3c2c1c0 然后, 每个字节再加 0x20转换为可打印的字符. 注意: 如果是一个 0字节那它应该被转换为0x60而不是0x20, 因为(前引用'`')优于 0x20(空格' '). 例如: 从文件中读取的 3字节如下: 14 0F A8 00010100 00001111 10101000 转换为 6-bit: 000101 000000 111110 101000 每字节高两位补 0后为: 00000101 00000000 00111110 00101000 最后每字节再加 0x20,则 4字节输出应该为: 25 60 5E 48 注意: 00字节被转换为 0x60而不是 0x20. 因此, 在一个 uuencoded文件中仅包含字符 0x21 '!'到 0x60 '`',它们都是可打印和可被 email传送的. 这个转换过程也意味着 uuencoded 文件要比原文件大 33%的. 3、 编码与解码
3.1编码 outbuf [4] 输出 uu编码数据. inbytep [3] 输入二进制数据. #define ENCODE_BYTE(b) (((b) == 0) ? 0x60 : ((b) + 0x20)) outbuf [0] = ENCODE_BYTE ((inbytep [0] & 0xFC) >> 2); outbuf [1] = ENCODE_BYTE (((inbytep [0] & 0x03) << 4) + ((inbytep [1] & 0xF0) >> 4)); outbuf [2] = ENCODE_BYTE (((inbytep [1] & 0x0F) << 2) + ((inbytep [2] & 0xC0) >> 6)); outbuf [3] = ENCODE_BYTE (inbytep [2] & 0x3F); 3.2 解码 linep [4] 输入 uu编码数据. outbyte [3] 输出二进制数据. #define DECODE_BYTE(b) ((b == 0x60) ? 0 : b - 0x20) outbyte [0] = DECODE_BYTE (linep [0]); outbyte [1] = DECODE_BYTE (linep [1]); outbyte [0] <<= 2; outbyte [0] |= (outbyte [1] >> 4) & 0x03; outbyte [1] <<= 4; outbyte [2] = DECODE_BYTE (linep [2]); outbyte [1] |= (outbyte [2] >> 2) & 0x0F; outbyte [2] <<= 6; outbyte [2] |= DECODE_BYTE (linep [3]) & 0x3F;
4、源码
4.1编码
#include "stdio.h" #include "stdlib.h" #define MAX_LINELEN 45 #define ENCODE_BYTE(b) (((b) == 0) ? 0x60 : ((b) + 0x20)) typedef unsigned char BYTE; int main (int argc, char *argv []) { FILE *infile = NULL; FILE *outfile = NULL; int linelen; int linecnt; BYTE inbuf [MAX_LINELEN]; BYTE *inbytep; char outbuf [5]; if (argc != 3) { fprintf (stderr, "Syntax: uuencode <infile> <outfile>\n"); exit (1); } /* Try and open the input file (binary) */ infile = fopen (argv[1], "rb"); if (infile == NULL) { fprintf (stderr, "uuencode: Couldn't open input file %s\n", argv[1]); exit (1); } /* Try and open the output file (text) */ outfile = fopen (argv[2], "wt"); if (outfile == NULL) { fprintf (stderr, "uuencode: Couldn't open output file %s\n", argv[2]); exit (1); } /* Write the 'begin' line, giving it a mode of 0600 */ fprintf (outfile, "begin 600 %s\n", argv[1]); do { /* Read a line from input file */ linelen = fread (inbuf, 1, MAX_LINELEN, infile); /* Write the line length byte */ fputc (ENCODE_BYTE (linelen), outfile); /* Encode the line */ for (linecnt = linelen, inbytep = inbuf; linecnt > 0; linecnt -= 3, inbytep += 3) { /* Encode 3 bytes from the input buffer */ outbuf [0] = ENCODE_BYTE ((inbytep [0] & 0xFC) >> 2); outbuf [1] = ENCODE_BYTE (((inbytep [0] & 0x03) << 4) + ((inbytep [1] & 0xF0) >> 4)); outbuf [2] = ENCODE_BYTE (((inbytep [1] & 0x0F) << 2) + ((inbytep [2] & 0xC0) >> 6)); outbuf [3] = ENCODE_BYTE (inbytep [2] & 0x3F); outbuf [4] = '\0'; /* Write the 4 encoded bytes to the file */ fprintf (outfile, "%s", outbuf); } fprintf (outfile, "\n"); } while (linelen != 0); /* Write the 'end' marker */ fprintf (outfile, "end\n"); /* Tidy up and return */ fclose (infile); fclose (outfile); return 0; }
4.2 解码
/* * uudecode.c - * Simple uudecode utility * Jim Cameron, 1997 */ #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> /* We all hate magic numbers! */ #define LINE_BUF_SIZE 256 /* Decode a byte */ #define DECODE_BYTE(b) ((b == 0x60) ? 0 : b - 0x20) typedef unsigned char BYTE; int main (int argc, char *argv[]) { FILE *infile = NULL; FILE *outfile = NULL; char linebuf [LINE_BUF_SIZE]; char *linep = NULL; char *tempcp = NULL; int linelen = 0; int linecnt = 0; char outfname [LINE_BUF_SIZE]; BYTE outbyte [3]; /* Check that we have the right number of arguments */ if (argc != 2) { fprintf (stderr, "Syntax: uudecode <filename>\n"); exit (1); } /* Open the input file */ infile = fopen (argv[1], "rt"); if (infile == NULL) { fprintf (stderr, "uudecode: Couldn't open file %s\n", argv[1]); exit (1); } /* uu-encoded files always have a 'begin' marker, so go and look for this */ for (;;) { /* Read a line */ if (fgets (linebuf, LINE_BUF_SIZE, infile) == NULL) { fprintf (stderr, "uudecode: Not a valid uu-encoded file\n"); exit (1); } /* See if it is the 'begin' marker */ if ((strncmp (linebuf, "begin", 5) == 0) && isspace (linebuf[5])) { break; } } /* If we have reached this point, we have found a begin marker */ linep = linebuf + 5; /* Next comes the mode, which we ignore */ while (isspace (*linep)) { linep++; } if (*linep == '\0') { fprintf (stderr, "uudecode: Not a valid uu-encoded file\n"); exit (1); } while (isdigit (*linep)) { linep++; } while (isspace (*linep)) { linep++; } if (*linep == '\0') { fprintf (stderr, "uudecode: Not a valid uu-encoded file/n"); exit (1); } /* The rest of the begin line is the output file name */ strcpy (outfname, linep); tempcp = outfname; while (!isspace (*tempcp) && (*tempcp != '\0')) { tempcp++; } *tempcp = '\0'; /* Now open the output file */ outfile = fopen (outfname, "wb"); if (outfile == NULL) { fprintf (stderr, "uudecode: Couldn't open output file %s\n", outfname); exit (1); } /* Now for the uu-decode proper */ do { if (fgets (linebuf, LINE_BUF_SIZE, infile) == NULL) { fprintf (stderr, "uudecode: Read error\n"); exit (1); } /* The first byte of the line represents the length of the DECODED line */ linelen = DECODE_BYTE (linebuf[0]); linep = linebuf + 1; for (linecnt = linelen; linecnt > 0; linecnt -= 3, linep += 4) { /* Check for premature end-of-line */ if ((linep[0] == '\0') || (linep[1] == '\0') || (linep[2] == '\0') || (linep[3] == '\0')) { fprintf (stderr, "uudecode: Error in encoded block\n"); exit (1); } /* Decode the 4-byte block */ outbyte[0] = DECODE_BYTE (linep[0]); outbyte[1] = DECODE_BYTE (linep[1]); outbyte[0] <<= 2; outbyte[0] |= (outbyte[1] >> 4) & 0x03; outbyte[1] <<= 4; outbyte[2] = DECODE_BYTE (linep[2]); outbyte[1] |= (outbyte[2] >> 2) & 0x0F; outbyte[2] <<= 6; outbyte[2] |= DECODE_BYTE (linep[3]) & 0x3F; /* Write the decoded bytes to the output file */ if (linecnt > 3) { if (fwrite (outbyte, 1, 3, outfile) != 3) { fprintf (stderr, "uudecode: Error writing to output file\n"); exit (1); } } else { if (fwrite (outbyte, 1, linecnt, outfile) != linecnt) { fprintf (stderr, "uudecode: Error writing to output file\n"); exit (1); } linecnt = 3; } } } while (linelen != 0); /* All is ok, tidy up and exit */ fclose (infile); fclose (outfile);
return 0; }
转载地址:http://rqdoi.baihongyu.com/