C語言 windows下Ansi和UTF-8編碼格式的轉換


  當我們使用MinGW-w64作為編譯器在windows系統環境下進行C語言編程時,如果源代碼文件(.c)保存格式為Ansi格式,則在打印漢字時不會出現亂碼;反之,如果我們使用UTF-8格式保存,則會出現亂碼,需要在編譯時加上“-fexec-charset=gbk”來解決亂碼問題。

#include <stdio.h>

int main()
{
    printf("%s\n", "你好,世界!");

    return 0;      
}

  

  那么,當我們使用C語言處理文件時,如果文件格式是UTF-8,如何轉換成Ansi格式呢?注意:在windows下,txt的保存格式中有UTF-8和帶有BOM的UTF-8兩個選項。如果選擇帶有BOM的UTF-8選項,則在讀取文件時會首先讀到三個標志着這個文件是由UTF-8格式編碼的字符,分別為EF BB BF。如果選擇UTF-8,則不會有這三個字符,而是直接一開始就讀到文件本身內容。詳情請看:https://blog.csdn.net/wang544831183/article/details/82349668

  1 // char.h
  2 // 頭文件
  3 // 定義結構體File,存儲文件信息
  4 // 定義結構體初始化函數以及其他函數
  5 
  6 #ifndef _H_CHAR_
  7 #define _H_CHAR_
  8 
  9 #include <stdio.h>
 10 #include <stdbool.h>
 11 #include <stdlib.h>
 12 #include <windows.h>
 13 
 14 unsigned char BOM[] = {0xEF, 0xBB, 0xBF};    // 帶有BOM的UTF-8編碼格式的文件會以這三個字符開頭
 15 
 16 // File結構體定義
 17 typedef struct file {
 18     char *filename;
 19     char *filemode;
 20     char *encoding;
 21     bool readable;
 22 } File;
 23 
 24 // 函數定義
 25 File *initializeFile(char *, char *);        // 初始化結構體
 26 bool isUTF8(char *);                        // 判斷文件是否為UTF-8編碼格式
 27 bool isReadable(char *);                    // 判斷filemode是否支持可讀選項
 28 bool charInString(char, char *);            // 判斷字符是否在字符串中
 29 void fprint(File *);                        // 打印結構體內容
 30 void fprintInfo(File *);                     // 打印結構體信息
 31 void deconstructFile(File *);                // 析構化結構體
 32 void fprintAnsi(File *);                    // 以Ansi格式打印
 33 // 轉換函數定義
 34 void Convert(const char* strIn, char* strOut, int sourceCodepage, int targetCodepage);
 35 void UTF82Ansi(PCHAR Src, PCHAR Dst);
 36 void Ansi2UTF8(PCHAR Src, PCHAR Dst);
 37 
 38 // 函數實現
 39 File *initializeFile(char *filename, char *filemode)
 40 {
 41     File *file = (File *)malloc(sizeof(File));
 42     file->filename = filename;
 43     file->filemode = filemode;
 44     file->encoding = "Ansi";
 45     file->readable = false;
 46 
 47     if (isUTF8(filename))
 48     {
 49         file->encoding = "UTF-8";
 50     }
 51 
 52     if (isReadable(filemode))
 53     {
 54         file->readable = true;
 55     }
 56 
 57     return file;
 58 }
 59 
 60 bool isUTF8(char *filename)
 61 {
 62     FILE *fp = fopen(filename, "r");
 63 
 64     if (fp == NULL)
 65     {
 66         printf("Unable to open file %s\n", filename);
 67         return false;
 68     }
 69 
 70     unsigned char *buffer = (unsigned char *)malloc(sizeof(unsigned char) * 3);
 71     fread(buffer, 3, 3, fp);
 72     fclose(fp);
 73 
 74     for (int i = 0; i < 3; i++)
 75     {
 76         if (buffer[i] != BOM[i])
 77         {
 78             return false;
 79         }
 80     }
 81 
 82     return true;
 83 }
 84 
 85 bool isReadable(char *filemode)
 86 {
 87     if (charInString('r', filemode) || charInString('+', filemode))
 88     {
 89         return true;
 90     }
 91     return false;
 92 }
 93 
 94 bool charInString(char ch, char *str)
 95 {
 96     while (*str != '\0')
 97     {
 98         if (ch == *str)
 99         {
100             return true;
101         }
102         ++str;
103     }
104     return false;
105 }
106 
107 void fprintInfo(File *file)
108 {
109     printf("filename: %s\nfilemode: %s\nencoding: %s\nreadble: %d\n", file->filename, file->filemode, file->encoding, file->readable);
110 }
111 
112 void fprint(File *file)
113 {
114     // 只有filemode中存在'r'或者'+'字符時,才可以調用fprint函數
115     if (!file->readable)
116     {
117         return;
118     }
119 
120     FILE *fp = fopen(file->filename, file->filemode);
121     char chr;
122 
123     if (fp == NULL)
124     {
125         printf("Failed to open file %s\n", file->filename);
126         return;
127     }
128 
129     while ((chr = fgetc(fp)) != EOF)
130     {
131         printf("%c", chr);
132     }
133 
134     puts("");
135     fseek(fp, 0, SEEK_SET);        // 重置到開頭
136 
137     while ((chr = fgetc(fp)) != EOF)
138     {
139         printf("%x ", (unsigned char)chr);
140     }
141     printf("\n\n");
142 
143     fclose(fp);
144 }
145 
146 void deconstructFile(File *file)
147 {
148     free(file);
149     file = NULL;
150 }
151 
152 void fprintAnsi(File *file)
153 {
154     if (!file->readable)
155     {
156         return;
157     }
158     if (file->encoding == "Ansi")
159     {
160         fprint(file);
161     }
162     else
163     {
164         FILE *fp = fopen(file->filename, file->filemode);
165         
166         int i = 0;
167         char ch;
168         char utf8[MAX_PATH] = {0};
169         char ansi[MAX_PATH] = {0};
170 
171         // 跳過頭三個BOM字符
172         fseek(fp, 3, SEEK_SET);
173         while ((ch = fgetc(fp)) != EOF)
174         {
175             utf8[i++] = ch;
176         }
177         utf8[i] = '\0';
178         UTF82Ansi(utf8, ansi);
179         printf("%s\n", ansi);
180 
181         fclose(fp);
182         fp = NULL;
183     }
184 }
185 
186 // 編碼格式轉換函數
187 void Convert(const char* strIn, char* strOut, int sourceCodepage, int targetCodepage)
188 {
189     int len = lstrlenA(strIn);
190     int unicodeLen = MultiByteToWideChar(sourceCodepage, 0, strIn, -1, NULL, 0);
191     wchar_t pUnicode[1024] = {0};
192     MultiByteToWideChar(sourceCodepage, 0, strIn, - 1, (LPWSTR)pUnicode, unicodeLen);
193 
194     BYTE pTargetData[2048] = {0};
195     int targetLen = WideCharToMultiByte(targetCodepage, 0, (LPWSTR)pUnicode, -1, (char*)pTargetData,0, NULL, NULL);
196     WideCharToMultiByte(targetCodepage, 0, (LPWSTR)pUnicode, -1,(char*)pTargetData, targetLen, NULL, NULL);
197     lstrcpyA(strOut,(char*)pTargetData);
198 }
199 void UTF82Ansi(PCHAR Src, PCHAR Dst)
200 {
201     Convert(Src,Dst,CP_UTF8,CP_ACP);
202 }
203 void Ansi2UTF8(PCHAR Src, PCHAR Dst)
204 {
205     Convert(Src,Dst,CP_ACP, CP_UTF8);
206 }
207 
208 #endif
char.h
 1 #include "char.h"
 2 
 3 int main()
 4 {
 5     File *ansi = initializeFile("ansi.txt", "r");
 6     fprintInfo(ansi);
 7     fprint(ansi);
 8     deconstructFile(ansi);
 9 
10     File *utf8 = initializeFile("utf-8-bom.txt", "r");
11     fprintInfo(utf8);
12     fprint(utf8);
13     fprintAnsi(utf8);
14     deconstructFile(utf8);        
15 
16     return 0;
17 }
main.c

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM