在Java中考虑这个例子:
public final class Meh
{
private static final String HELLO = "Hello world";
private static final Charset UTF32 = Charset.forName("UTF-32");
public static void main(final String... args)
throws IOException
{
final Path tmpfile = Files.createTempFile("test", "txt");
try (
final Writer writer = Files.newBufferedWriter(tmpfile, UTF32);
) {
writer.write(HELLO);
}
final String readBackFromFile;
try (
final Reader reader = Files.newBufferedReader(tmpfile, UTF32);
) {
readBackFromFile = CharStreams.toString(reader);
}
Files.delete(tmpfile);
System.out.println(HELLO.equals(readBackFromFile));
}
}
此程序打印true
。现在,一些注意事项:
Charset
是一个包含字符编码的类,两种方式;您可以使用CharsetDecoder
将字节流解码为字符流,或者CharsetEncoder
将字符流编码为字节流; char
vs byte
; char
只是一个16位无符号数:这是因为当Java诞生时,Unicode没有在现在所谓的BMP(基本多语言平面)之外定义代码点;是,在范围U + 0000-U + FFFF(包括端点)中定义的任何代码点。完成所有这些后,上面的代码执行以下操作:
String
,它首先将此文本转换为字节序列,然后再将其写入文件; CharStreams.toString()
不在标准JDK中;这是一个来自番石榴的课程。现在,关于C ......我的问题如下:
Charset
;聊天室的另一个评论是C,你是SOL,但C ++有codecvt ...... 是的,我知道UTF-32依赖于字节序;使用Java,默认情况下是BE。
但基本上:我将如何在C中编程?假设我想用C编写写作方或阅读方,我该怎么做?
答案 0 :(得分:0)
在C中,您通常使用像 libiconv , libunistring 或 ICU 这样的库。
如果您只想处理UTF-32,您可以直接编写和读取包含Unicode代码点的32位整数数组,无论是小端还是大端。与UTF-8或UTF-16不同,UTF-32字符串不需要任何特殊的编码和解码。您可以使用任何32位整数类型。我更喜欢C99' uint32_t
而不是C11' char32_t
。例如:
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
// Could also contain non-ASCII code points.
static const uint32_t hello[] = {
'H', 'e', 'l', 'l', 'o', ' ',
'w', 'o', 'r', 'l', 'd'
};
static size_t num_chars = sizeof(hello) / sizeof(uint32_t);
const char *path = "test.txt";
FILE *outstream = fopen(path, "wb");
// Write big endian 32-bit integers
for (size_t i = 0; i < num_chars; i++) {
uint32_t code_point = hello[i];
for (int j = 0; j < 4; j++) {
int c = (code_point >> ((3 - j) * 8)) & 0xFF;
fputc(c, outstream);
}
}
fclose(outstream);
FILE *instream = fopen(path, "rb");
// Get file size.
fseek(instream, 0, SEEK_END);
long file_size = ftell(instream);
rewind(instream);
if (file_size % 4) {
fprintf(stderr, "File contains partial UTF-32");
exit(1);
}
if (file_size > SIZE_MAX) {
fprintf(stderr, "File too large");
exit(1);
}
size_t num_chars_in = file_size / sizeof(uint32_t);
uint32_t *read_back = malloc(file_size);
// Read big endian 32-bit integers
for (size_t i = 0; i < num_chars_in; i++) {
uint32_t code_point = 0;
for (int j = 0; j < 4; j++) {
int c = fgetc(instream);
code_point |= c << ((3 - j) * 8);
}
read_back[i] = code_point;
}
fclose(instream);
bool equal = num_chars == num_chars_in
&& memcmp(hello, read_back, file_size) == 0;
printf("%s\n", equal ? "true" : "false");
free(read_back);
return 0;
}
(为简洁起见,省略了大多数错误检查。)
编译并运行该程序:
$ gcc -std=c99 -Wall so.c -o so
$ ./so
true
$ hexdump -C test.txt
00000000 00 00 00 48 00 00 00 65 00 00 00 6c 00 00 00 6c |...H...e...l...l|
00000010 00 00 00 6f 00 00 00 20 00 00 00 77 00 00 00 6f |...o... ...w...o|
00000020 00 00 00 72 00 00 00 6c 00 00 00 64 |...r...l...d|
0000002c