微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何逐行阅读unicodeutf-8/二进制文件

嗨程序员,

我想逐行读一个由记事本创build的Unicode(UTF-8)文本文件,我不想在屏幕上显示Unicodestring,我只想读取和比较string!

代码逐行读取ANSI文件,并比较string

我想要的是

逐行阅读test_ansi.txt

在Windows上的Rails Bundler拒绝安装hpricot(甚至在手动gem安装得到错误:没有这样的文件加载 – hpricot)

Windows 10 Linux子系统 – Python – string到电脑剪贴板

msbuild只是部署没有构build

在Windows中进行字体平滑

在Windows操作系统上的java File.listFiles()不是逻辑顺序的

如果该行=“b”打印“YES!”

否则打印“不!

read_ansi_line_by_line.c

#include <stdio.h> int main() { char *inname = "test_ansi.txt"; FILE *infile; char line_buffer[BUFSIZ]; /* BUFSIZ is defined if you include stdio.h */ char line_number; infile = fopen(inname,"r"); if (!infile) { printf("nfile '%s' not foundn",inname); return 0; } printf("n%snn",inname); line_number = 0; while (fgets(line_buffer,sizeof(line_buffer),infile)) { ++line_number; /* note that the newline is in the buffer */ if (strcmp("bn",line_buffer) == 0 ){ printf("%d: YES!n",line_number); }else{ printf("%d: NO!n",line_number,line_buffer); } } printf("nnTotal: %dn",line_number); return 0; }

test_ansi.txt

a b c

编译

gcc -o read_ansi_line_by_line read_ansi_line_by_line.c

产量

test_ansi.txt 1: NO! 2: YES! 3: NO! Total: 3

现在我需要阅读由记事本创build的Unicode(UTF-8)文件,超过6个月后,我没有发现在C中的任何好的代码/库可以读取UTF-8编码的文件!我不知道为什么,但是我认为标准C不支持Unicode!

阅读Unicode二进制文件的确定!,但问题是二进制文件大部分已经在二进制模式下创build,这意味着如果我们想要读一个由记事本创build的Unicode(UTF-8)文件,我们需要将它从UTF-8文件到BINARY文件

代码将Unicodestring写入二进制文件,注意C文件以UTF-8编码并由GCC编译

我想要的是

将Unicode字符“ب”写入test_bin.dat

create_bin.c

#define UNICODE #ifdef UNICODE #define _UNICODE #else #define _MBCS #endif #include <stdio.h> #include <wchar.h> int main() { /*Data to be stored in file*/ wchar_t line_buffer[BUFSIZ]=L"ب"; /*opening file for writing in binary mode*/ FILE *infile=fopen("test_bin.dat","wb"); /*Writing data to file*/ fwrite(line_buffer,1,13,infile); /*Closing File*/ fclose(infile); return 0; }

编译

gcc -o create_bin create_bin.c

产量

create test_bin.dat

现在我想要逐行读取二进制文件并进行比较!

我想要的是

如果line =“ب”print“YES!”,请逐行阅读test_bin.dat。 否则打印“不!

read_bin_line_by_line.c

#define UNICODE #ifdef UNICODE #define _UNICODE #else #define _MBCS #endif #include <stdio.h> #include <wchar.h> int main() { wchar_t *inname = L"test_bin.dat"; FILE *infile; wchar_t line_buffer[BUFSIZ]; /* BUFSIZ is defined if you include stdio.h */ infile = _wfopen(inname,L"rb"); if (!infile) { wprintf(L"nfile '%s' not foundn",inname); return 0; } wprintf(L"n%snn",inname); /*Reading data from file into temporary buffer*/ while (fread(line_buffer,infile)) { /* note that the newline is in the buffer */ if ( wcscmp ( L"ب",line_buffer ) == 0 ){ wprintf(L"YES!n"); }else{ wprintf(L"NO!n",line_buffer); } } /*Closing File*/ fclose(infile); return 0; }

产量

test_bin.dat YES!

问题

这个方法非常长! 和不强大(软件工程初学者)

请任何一个知道如何阅读Unicode文件? (我知道它不容易!)请任何一个知道如何将Unicode文件转换为二进制文件? (简单的方法)请任何一个知道如何在二进制模式下读取Unicode文件? (我不确定)

谢谢。

应用程序分段错误,仅在使用MinGW在Windows上编译时

扫描Windows进程列表最有效的方法

如何在Ruby on Windows上获取文件创build时间?

简单的IParallelEnumerable <T>教程

如何创build通用键盘快捷键?

UTF-8的一个不错的属性是你不需要解码就可以比较它。 不管你先解码还是不解码,从strcmp返回的顺序都是一样的。 所以只要读取它作为原始字节并运行strcmp。

我找到了解决我的问题的方法,并且希望将解决方分享给任何有兴趣阅读C99中的UTF-8文件的人。

void ReadUTF8(FILE* fp) { unsigned char iobuf[255] = {0}; while( fgets((char*)iobuf,sizeof(iobuf),fp) ) { size_t len = strlen((char *)iobuf); if(len > 1 && iobuf[len-1] == 'n') iobuf[len-1] = 0; len = strlen((char *)iobuf); printf("(%d) "%s" ",len,iobuf); if( iobuf[0] == 'n' ) printf("Yesn"); else printf("Non"); } } void ReadUTF16BE(FILE* fp) { } void ReadUTF16LE(FILE* fp) { } int main() { FILE* fp = fopen("test_utf8.txt","r"); if( fp != NULL) { // see http://en.wikipedia.org/wiki/Byte-order_mark for explaination of the BOM // encoding unsigned char b[3] = {0}; fread(b,2,fp); if( b[0] == 0xEF && b[1] == 0xBB) { fread(b,fp); // 0xBF ReadUTF8(fp); } else if( b[0] == 0xFE && b[1] == 0xFF) { ReadUTF16BE(fp); } else if( b[0] == 0 && b[1] == 0) { fread(b,fp); if( b[0] == 0xFE && b[1] == 0xFF) ReadUTF16LE(fp); } else { // we don't kNow what kind of file it is,so assume its standard // ascii with no BOM encoding rewind(fp); ReadUTF8(fp); } } fclose(fp); }

如果您使用Visual Studio 2005及更高版本,则fgets()可以解码UTF-8编码的文件。 像这样改变你的代码

infile = fopen(inname,"r,ccs=UTF-8");

我知道我不好…但是你甚至不考虑BOM! 这里大多数例子都会失败。

编辑:

字节顺序标记文件初始位置的几个字节,可以用来标识文件的编码。 一些编辑添加它们,很多时候他们只是以拙劣的方式破坏事情(我记得因为这个问题,我们花了几分钟时间来处理一个PHP文件的问题)。

一些RTFM: http : //en.wikipedia.org/wiki/Byte_order_mark http://blogs.msdn.com/oldnewthing/archive/2004/03/24/95235.aspx 什么是XML BOM,我如何检测它?

在这文章中编写了一个编码和解码例程,并解释了unicode是如何编码的:

http://www.codeguru.com/cpp/misc/misc/multi-lingualsupport/article.PHP/c10451/

它可以很容易地调整为C.简单地编码您的ANSI或解码UTF-8字符串并进行字节比较

编辑:OP后说,这是很难从C ++重写函数在这里模板:

需要什么:

+释放分配的内存(或等到进程结束或忽略)

+添加4个字节的功能

+告诉我,short和int不能保证是2和4字节长(我知道,但C真的很愚蠢!),最后

+找到一些其他的错误

#include <stdlib.h> #include <string.h> #define MASKBITS 0x3F #define MASKBYTE 0x80 #define MASK2BYTES 0xC0 #define MASK3BYTES 0xE0 #define MASK4BYTES 0xF0 #define MASK5BYTES 0xF8 #define MASK6BYTES 0xFC char* UTF8Encode2BytesUnicode(unsigned short* input) { int size = 0,cindex = 0; while (input[size] != 0) size++; // Reserve enough place; The amount of char* result = (char*) malloc(size); for (int i=0; i<size; i++) { // 0xxxxxxx if(input[i] < 0x80) { result[cindex++] = ((char) input[i]); } // 110xxxxx 10xxxxxx else if(input[i] < 0x800) { result[cindex++] = ((char)(MASK2BYTES | input[i] >> 6)); result[cindex++] = ((char)(MASKBYTE | input[i] & MASKBITS)); } // 1110xxxx 10xxxxxx 10xxxxxx else if(input[i] < 0x10000) { result[cindex++] = ((char)(MASK3BYTES | input[i] >> 12)); result[cindex++] = ((char)(MASKBYTE | input[i] >> 6 & MASKBITS)); result[cindex++] = ((char)(MASKBYTE | input[i] & MASKBITS)); } } } wchar_t* UTF8Decode2BytesUnicode(char* input) { int size = strlen(input); wchar_t* result = (wchar_t*) malloc(size*sizeof(wchar_t)); int rindex = 0,windex = 0; while (rindex < size) { wchar_t ch; // 1110xxxx 10xxxxxx 10xxxxxx if((input[rindex] & MASK3BYTES) == MASK3BYTES) { ch = ((input[rindex] & 0x0F) << 12) | ( (input[rindex+1] & MASKBITS) << 6) | (input[rindex+2] & MASKBITS); rindex += 3; } // 110xxxxx 10xxxxxx else if((input[rindex] & MASK2BYTES) == MASK2BYTES) { ch = ((input[rindex] & 0x1F) << 6) | (input[rindex+1] & MASKBITS); rindex += 2; } // 0xxxxxxx else if(input[rindex] < MASKBYTE) { ch = input[rindex]; rindex += 1; } result[windex] = ch; } } char* getUnicodetoUTF8(wchar_t* myString) { int size = sizeof(wchar_t); if (size == 1) return (char*) myString; else if (size == 2) return UTF8Encode2BytesUnicode((unsigned short*) myString); else return UTF8Encode4BytesUnicode((unsigned int*) myString); }

只是为了解决BOM的论点。 这是从记事本文件

[paul@paul-es5 tests]$ od -t x1 /mnt/hgfs/cdrive/test.txt 0000000 ef bb bf 61 0d 0a 62 0d 0a 63 0000012

在开始时有一个BOM

就个人而言,我不认为应该有一个BOM(因为它是一个字节格式),但那不是重点

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐