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



我写一个C代码如下,复制一个文件。 它确实适用于unicode文件(例如 EXE、RAR),我使用char数据类型数组来复制文件中的文件"块"。 我知道,char data-type只能将1字节存储为扩展ASCII标准。

fread()函数中,由于复制exe文件块(100字节),buffer[buflen]变量用作数组char,然后将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;
}

freadfwrite函数中使用chardata-typestruct(包含char)的原因是什么?

谢谢大家帮助我。

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

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

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

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

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

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

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

当使用另一种 UTF 编码(例如 UTF-16)时,所有字符都编码为 16 位数量,例如,如果您在小端架构中读取它们,但您在大端架构中编写它们(您应该将字符交换每两个字节以在目标架构中保留其 UTF 值),但同样, 可以有一些技巧来解决这个问题(有一个BOM特殊签名,允许检查数据中是否使用了字节序),因此,只要您逐字节复制文件,就不会对字符进行重新排序,并且最终图像与您之前的图像完全相同, 所以UTF不应该担心。

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

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

有关 UNICODE 的主要信息来源是 UNICODE 论坛,您可以在其中找到整个 UNICODE 系列的规范、指南甚至字符映射。 此处介绍了 UTF-8、UTF-16 和 UTF-32 编码。 对于 utf-5 和 utf-7,您必须按照上述链接进行操作。

最新更新