我写了一个 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;
}
在char
和data-type
函数中使用struct
char
或fread
(包含fwrite
)的原因是什么?< / p>
感谢大家帮助我。
答案 0 :(得分:3)
任何文件,无论编码如何,都只是一个字节序列。 char
类型可以存储任何字节,因此您只需将文件字节复制为字节。 (char
在C和C ++中用作字符类型和能够保存字节的数字类型。这可能令人困惑,但两种用法都是有效的。)
fread
和fwrite
是根据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-5,utf-7,utf-8和utf-16)中,如果您打破映射到实际UTF代码的多个序列之一,则会出现问题,因为这会使解码过程无法识别的字符(它变成非法字符)然后你通常在输出中得到一些特殊字符,表示检测到无效字符。在恒定长度编码(utf-32)中,只有在将文件拆分为32位边界的非倍数时才会得到损坏的字符。
UTF的设计目的是成为存储和发送几乎未绑定的字符集的有效方法,为实现这一点,它将最常见的字符映射(或尝试映射)为一个字节,将长度增加为选择更具体或罕见的字符。
关于UNICODE的主要信息来源是UNICODE FORUM,在那里您可以找到完整UNICODE系列的规格,指南甚至字符图。这里描述了UTF-8,UTF-16和UTF-32编码。对于utf-5和utf-7,您必须按照上述链接。