如何使用Cocoa将文本翻译成二进制文件?

时间:2013-04-18 01:47:19

标签: macos cocoa binary

我正在制作一个简单的Cocoa程序,它可以将文本编码为二进制并将其解码回文本。我试图制作这个剧本,我甚至都没有完成这个。谁能帮我?这必须包括两个文本框和两个按钮或任何最好的,谢谢!

1 个答案:

答案 0 :(得分:0)

这有两个部分。

第一种是将字符串的字符编码为字节。您可以通过发送字符串dataUsingEncoding:消息来完成此操作。您选择哪种编码将决定它为每个字符提供哪些字节。从NSUTF8StringEncoding开始,然后在其工作后尝试使用其他编码,例如NSUnicodeStringEncoding

第二部分是将每个字节的每一位转换为'0'字符或'1'字符,例如,字母A,以UTF-8编码为单个字符byte,将表示为01000001

因此,将字符转换为字节,并将字节转换为表示位的字符。这两个是完全独立的任务;第二部分应该适用于任何字节流,包括任何有效的编码字符流,任何无效的编码字符流,以及任何完全没有文本的内容。

第一部分很容易:

- (NSString *) stringOfBitsFromEncoding:(NSStringEncoding)encoding
    ofString:(NSString *)inputString
{
    //Encode the characters to bytes using the UTF-8 encoding. The bytes are contained in an NSData object, which we receive.
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];

    //I did say these were two separate jobs.
    return [self stringOfBitsFromData:data];
}

对于第二部分,您需要遍历bytes数据。 C for循环将在那里完成工作,看起来像这样:

//This is the method we're using above. I'll leave out the method signature and let you fill that in.
- …
{
    //Find out how many bytes the data object contains.
    NSUInteger length = [data length];
    //Get the pointer to those bytes. “const” here means that we promise not to change the values of any of the bytes. (The compiler may give a warning if we don't include this, since we're not allowed to change these bytes anyway.)
    const char *bytes = [data bytes];

    //We'll store the output here. There are 8 bits per byte, and we'll be putting in one character per bit, so we'll tell NSMutableString that it should make room for (the number of bytes times 8) characters.
    NSMutableString *outputString = [NSMutableString stringWithCapacity:length * 8];

    //The loop. We start by initializing i to 0, then increment it (add 1 to it) after each pass. We keep looping as long as i < length; when i >= length, the loop ends.
    for (NSUInteger i = 0; i < length; ++i) {
        char thisByte = bytes[i];

        for (NSUInteger bitNum = 0; bitNum < 8; ++bitNum) {
            //Call a function, which I'll show the definition of in a moment, that will get the value of a bit at a given index within a given character.
            bool bit = getBitAtIndex(thisByte, bitNum);

            //If this bit is a 1, append a '1' character; if it is a 0, append a '0' character.
            [outputString appendFormat: @"%c", bit ? '1' : '0'];
        }
    }

    return outputString;
}

位101(或1100101)

比特实际上只是基数2中的数字。西方世界的人通常会在基数10中写出数字,但数字是一个数字,无论它写入什么基础,每个字符和每个字节,实际上每一点,都只是一个数字。

数字 - 包括位 - 从最低位开始计数,根据提升基数的指数来查找该位置的大小。我们需要位,因此base是2,所以我们的位置值是:

  • 2 ^ 0 = 1:那些位置(最低位)
  • 2 ^ 1 = 2:两个位置(下一个更高位)
  • 2 ^ 2 = 4:四肢
  • 2 ^ 3 = 8:八个地方

依此类推,最多2 ^ 7。 (请注意,最高指数恰好比我们之后的数字低一个;在这种情况下,7对8。)

如果这一切都提醒你在小时候读到“那个地方”,“十位”,“数百个地方”等等,它应该:它是完全相同的原则。

所以像65这样的字节(以UTF-8表示)完全代表字符&#39; A&#39;是以下的总和:

  2^7 × 0 = 0
+ 2^6 × 0 = 64
+ 2^5 × 1 = 0
+ 2^4 × 0 = 0
+ 2^3 × 0 = 0
+ 2^2 × 0 = 0
+ 2^1 × 0 = 0
+ 2^0 × 1 = 1
= 0 + 64 +0+0+0+0+0 + 1
= 64 + 1
= 65

当你小时候学习10号基数时,你可能会注意到10是“10”,100是“100”等。这在基数2中也是如此:因为10 ^ x是“1”在基数10中跟随x“0”s,因此在基数2中是2 ^ x“1”,接着是“x”0。因此,例如,基数2中的64是“1000000”(计算零并比较到上表)。

我们将使用这些精确的2次幂来测试每个输入字节中的每个位。

找到位

C有一对“移位”运算符,它们会在数字的低端插入零或删除数字。前者称为“左移”,写为<<,你可以猜对了。

我们想要左转。我们希望将1左移一个我们之后的位数。这相当于将2(我们的基数)提高到该数字的幂;例如,1 << 6 = 2 ^ 6 =“1000000”。

测试位

C也有一个用于位测试的运算符;它是&,按位AND运算符。 (不要将此与&&混淆,后者是逻辑 AND运算符。&&用于在做出决策时使用整个true / false值; &是一个用于处理值内位的工具。)

严格来说,&不测试单个位;它遍历两个输入值的位,并返回一个新值,其位是每个输入对的按位AND。所以,例如,

  01100101
& 00101011
----------
  00100001

当且仅当相应输入位的两个也为1时,输出中的每个位都为1.

将这两件事放在一起

我们将使用左移运算符给我们一个数字,其中一位,第n位, 设置 - 即2 ^ n - 然后使用按位AND运算符,用于测试在输入字节中是否也设置了相同的位。

//This is a C function that takes a char and an int, promising not to change either one, and returns a bool.
bool getBitAtIndex(const char byte, const int bitNum)
//It could also be a method, which would look like this:
//- (bool) bitAtIndex:(const int)bitNum inByte:(const char)byte
//but you would have to change the code above. (Feel free to try it both ways.)
{
    //Find 2^bitNum, which will be a number with exactly 1 bit set. For example, when bitNum is 6, this number is “1000000”—a single 1 followed by six 0s—in binary.
    const int powerOfTwo = 1 << bitNum;

    //Test whether the same bit is also set in the input byte.
    bool bitIsSet = byte & powerOfTwo;

    return bitIsSet;
}

我应该承认一点魔力

按位AND运算符计算为单个位 - 它不会仅计算为1或0.请记住上面的示例,&运算符返回33。 / p>

bool类型有点神奇:任何时候将任何值转换为bool,它会自动变为1或0.任何非0都会变为1;任何0变为0

Objective-C BOOL类型不执行此操作,这就是我在上面的代码中使用bool的原因。您可以自由地使用您喜欢的任何一个,除非您通常在处理任何需要BOOL的内容时使用BOOL,特别是在重写子类中的方法或实现协议时。您可以自由地来回转换,但不是无损转换(因为bool将如上所述更改非零值。)

哦,是的,你说过一些关于文本框的内容

当用户点击您的按钮时,获取输入字段的stringValue,使用合理的编码(例如UTF-8)和该字符串调用stringOfBitsFromEncoding:ofString:,并将结果字符串设置为输出字段的新stringValue

额外功劳:添加一个弹出按钮,用户可以使用该按钮选择编码。

额外额外功劳:使用所有可用编码填充弹出按钮,无需硬编码或刻录清单。