将包含unicode文件的内容复制到c中的char数组中

时间:2016-05-22 16:11:03

标签: c unicode fread

我写了一个 c 代码如下,复制文件。它适用于unicode文件(例如exe,rar),我使用char数据类型数组来复制文件" block"在那里面。我知道,char data-type只能将1字节存储为扩展ASCII标准。

fread()函数中,buffer[buflen]变量用作char数组,因为复制了exe文件的块(100字节),然后将buffer[buflen]包含在另一个文件中。如何将unicode字符块存储在char中?为什么这段代码真正适用于unicode个文件而没有任何问题?

copyFile功能:

void copyFile(const char *src, const char *dst)
{
    const int buflen = 100;
    char buffer[buflen];
    long fileSize, curFileSize, offset = 0;
    FILE *r, *w;

    r = fopen(src, "r+b");
    w = fopen(dst, "w+b");

    fseek(r, 0, SEEK_END);
    fileSize = ftell(r);
    fseek(r, 0, SEEK_SET);

    while(fileSize - (curFileSize = ftell(r)) >= buflen)
    {
        fseek(r, offset * buflen, SEEK_SET);
        fread(&buffer, sizeof(buffer), 1, r);
        fwrite(&buffer, sizeof(buffer), 1, w);
        offset++;
    }

    if ((fileSize - curFileSize) != 0)
    {
        fseek(r, (offset - 1) + (curFileSize), SEEK_SET);
        fread(&buffer, fileSize - curFileSize, 1, r);
        fwrite(&buffer, fileSize - curFileSize, 1, w);
    }

    fclose(w);
    fclose(r);
}

entrypoint部分:

int main()
{
    copyFile("e:/1.exe", "e:/2.exe");
    return 0;
}

chardata-type函数中使用struct charfread(包含fwrite)的原因是什么?< / p>

感谢大家帮助我。

2 个答案:

答案 0 :(得分:3)

任何文件,无论编码如何,都只是一个字节序列。 char类型可以存储任何字节,因此您只需将文件字节复制为字节。 (char在C和C ++中用作字符类型和能够保存字节的数字类型。这可能令人困惑,但两种用法都是有效的。)

freadfwrite是根据char指定的,因为它们会读取和写入字节。

答案 1 :(得分:2)

嗯,您正在阅读的文件可能是编码,使用utf-8编码,这使得utf字符在U+0000 --- U+007f范围内与它们的ASCII对应物相同(这允许正常阅读,即使您没有UNICODE兼容的阅读器)。 iso-latin-?集中的字符通常映射为两个字符序列,而字符则映射为三个字符序列或更多。 只要您不修改您正在阅读的数据,存储的数据类型无关紧要 - 开始二进制或文本,或使用的编码---,副本将完全等于原始(或者您将不得不查看您的代码,因为它正在更改副本,使其看起来与原始版本不同)

通常,你不会有任何问题,只要你不打破任何这些序列(这意味着他们聚集到文件中并且你将它们分别写到不同的地方---在副本)这通常不会发生在文件副本中。确定UTF-8或UTF-16字符的开头相对容易,因为可以在数据流中向前或向后识别UNICODE编码中的所有字符。

对于UTF-8,字符由第一个字符组成,该字符编码此字符的字节数,以及n-1个字符的尾部(同样,易于检测)第一个字符将为{ {1}}(0b110xxxxx表示从现在开始的二进制表示中的八位字节)表示两个字节的字符,0b表示三个字节,依此类推,最多0b1110xxxx表示六个字节字节字符)其后的其余字符编码为0b1111110x。如果你继续前进,一旦你使用MSB设置了一个字节,你知道你在多字节序列前面,你必须在第一个0b10xxxxxx之前计算顶部的数量,并且你有数字组成字符的字节。向后看,你首先遇到一个0字符,你必须向后走,直到你得到一个0b10xxxxxx字符,这将是序列中的第一个字符。然后再次使用第一个程序。

在UTF-16中,程序几乎相同。 0b11xxxxxx下的字符编码为一个16位数字,相等或更高的字符使用16位数的代理对进行编码,它们具有以下模式:0x10000表示该对的前16位,第二个是0b110110xxxxxxxxxx。这一次,您需要将0b110111xxxxxxxxxx减去UTF字符编号,然后才能获得两个16位数量的0x10000部分中的x,但过程类似于使用的在utf-8。

xxxx...编码中,所有字符都存储为32位数量,因此目前还没有多序列编码的计划。所有字符都以32位数量传输。在撰写本文时,标准是V8.0并包含1,114,112个代码点。

当使用另一种UTF编码时,例如,UTF-16,所有字符都被编码为16位数量,例如,如果您在小端架构中读取它们,但是您在大端编写它们时可能会更改体系结构(你应该为每个字符交换两个字节以保存目标体系结构中的UTF值)但是同样可以有一些技巧来处理这个问题(有一个BOM特殊签名,允许检查字节顺序正在使用在数据中)所以,只要你一个字节地复制一个文件,就不会重新排序字符,最终的图像与你之前的图像完全相同,所以不应该关注UTF。

在可变长度编码(utf-5utf-7,utf-8和utf-16)中,如果您打破映射到实际UTF代码的多个序列之一,则会出现问题,因为这会使解码过程无法识别的字符(它变成非法字符)然后你通常在输出中得到一些特殊字符,表示检测到无效字符。在恒定长度编码(utf-32)中,只有在将文件拆分为32位边界的非倍数时才会得到损坏的字符。

UTF的设计目的是成为存储和发送几乎未绑定的字符集的有效方法,为实现这一点,它将最常见的字符映射(或尝试映射)为一个字节,将长度增加为选择更具体或罕见的字符。

关于UNICODE的主要信息来源是UNICODE FORUM,在那里您可以找到完整UNICODE系列的规格,指南甚至字符图。这里描述了UTF-8,UTF-16和UTF-32编码。对于utf-5utf-7,您必须按照上述链接。