1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <string.h>
#include <locale.h>
#if (defined(WIN32) || defined(_WIN32))
#include <windows.h>
#define WIN_CODEPAGE 1252
#endif
#define NOM_FIC "monFichierUTF8.txt"
#define BOM_UTF8 "\xEF\xBB\xBF"
#define TAILLE_BOM (sizeof(BOM_UTF8)/sizeof(char))
#define MAX_TAILLE_CAR_UTF8 4
#define MAX_LIG 128
typedef struct{
char *tab;
long int taille;
long int pos;
}FichierBuffer;
/*Retourne 0 : erreur de lecture du fichier.
Retourne 1 : succes
Retourne -1 : erreur d'allocation dynamique*/
static char initialiserFichierBuffer(FILE *f, FichierBuffer *fb){
if (fseek(f,0,SEEK_END) != 0)
return 0;
fb->taille = (ftell(f)); /*Taille du fichier en octet*/
if (fb->taille == -1)
return 0;
rewind(f); /*Revenir au debut du fichier*/
fb->tab = (char*)malloc((fb->taille+1)*sizeof(char));
if (fb->tab == NULL)
return -1;
if (fread (fb->tab,sizeof(char),fb->taille,f) != (size_t)fb->taille){
free(fb->tab);
return 0;
}
fb->pos = 0;
return 1;
}
static char prochainCarac(FichierBuffer *fb, char *carac){
if (fb->pos >= fb->taille)
return 0;
*carac = fb->tab[fb->pos];
fb->pos ++;
return 1;
}
/*
Encodage des caracteres UTF-8 :
0xxxxxxx 1 octet codant 1 à 7 bits
110xxxxx 10xxxxxx 2 octets codant 8 à 11 bits
1110xxxx 10xxxxxx 10xxxxxx 3 octets codant 12 à 16 bits
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 4 octets codant 17 à 21 bits*/
/*Masques pour determiner la taille du code du caractere*/
#define MASQUE_1 128 /*1000 0000 : caractere encode sur 1 octet*/
#define MASQUE_2 32 /*0010 0000 : caractere encode sur 2 octet*/
#define MASQUE_3 16 /*0001 0000 : caractere encode sur 3 octet*/
#define MASQUE_4 8 /*0000 1000 : caractere encode sur 4 octet*/
/*Masques pour recuperer les valeurs du caractere*/
#define MASQUE_C1 127 /*0111 1111* : valeur d'un caracetre encode sur 1 octet*/
#define MASQUE_C2 31 /*0001 1111* : valeur d'un caracetre encode sur 2 octet (1er) */
#define MASQUE_C3 15 /*0000 1111* : valeur d'un caracetre encode sur 3 octet (1er) */
#define MASQUE_C4 7 /*0000 0111* : valeur d'un caractere encode sur 4 octet (1er) */
#define MASQUE_C 63 /*0011 1111* : valeur d'un caractere encode sur 2,3 ou 4 octet (2em, 3em ou 4em) */
static int getTailleCarac(char carac1){
if ((carac1 & MASQUE_1) == 0)
return 1;
if ((carac1 & MASQUE_2) == 0)
return 2;
if ((carac1 & MASQUE_3) == 0)
return 3;
if ((carac1 & MASQUE_4) == 0)
return 4;
return 0;
}
static char prochainCaracUnicode(FichierBuffer *fb,wchar_t *wc){
int tcarac;
char carac[MAX_TAILLE_CAR_UTF8] = {0,0,0,0};
*wc = (wchar_t)0;
if (prochainCarac(fb,carac) == 0) /*Lecture du premier octet, qui determine la taille du caractere encode*/
return 0; /*retour de fin du fichier*/
tcarac = getTailleCarac(carac[0]);
if (tcarac == 0) /*Si caractere non UTF8 detecte*/
return -1;
switch(tcarac){
case 1:
*wc = carac[0] & MASQUE_C1;
break;
case 2:
prochainCarac(fb,carac + 1);
*wc = (carac[0] & MASQUE_C2) << 6;
*wc = *wc | (carac[1] & MASQUE_C);
break;
case 3:
prochainCarac(fb,carac + 1);
prochainCarac(fb,carac + 2);
*wc = (carac[0] & MASQUE_C3) << 12;
*wc = *wc | ((carac[1] & MASQUE_C) << 6);
*wc = *wc | (carac[2] & MASQUE_C);
break;
case 4:
prochainCarac(fb,carac + 1);
prochainCarac(fb,carac + 2);
prochainCarac(fb,carac + 3);
*wc = (carac[0] & MASQUE_C4) << 18;
*wc = *wc | ((carac[1] & MASQUE_C) << 12);
*wc = *wc | ((carac[2] & MASQUE_C) << 6);
*wc = *wc | (carac[3] & MASQUE_C);
break;
}
return 1;
}
#define CR L'\x0D'
static char lireLigne(FichierBuffer *fb, wchar_t *lig){
char ok, finLig, finFic ;
int i = 0;
do{
ok = (prochainCaracUnicode(fb, lig + i));
if (ok == -1) /*Si erreur de lecture*/
return -1;
finFic = (ok == 0);
finLig = (lig[i] == L'\n');
if (!finLig)
i++;
} while ((i < MAX_LIG) &&(!finFic) && (!finLig));
if (i >= MAX_LIG)
return -1; /*Si ligne trop longue*/
if ((i > 1) && (lig[i-1] == CR)) /*Suppression du caractere d'un eventuel caractere de retour charriot (CR)*/
i--;
lig[i] = L'\0'; /*Caractere de fin de ligne*/
if (finFic)
return 0;
return 1;
}
static char lireBOM(FichierBuffer *fb){
char bom[TAILLE_BOM];
unsigned int i;
char ok = 1;
bom[TAILLE_BOM-1] = '\0';
for (i = 0; ((i < TAILLE_BOM -1) && ok); i++)
ok = prochainCarac (fb,bom+i);
if (!ok)
return 0;
return (strcmp(bom,BOM_UTF8) == 0);
}
static void supprimerFichierBuffer(FichierBuffer *fb){
free(fb->tab);
fb->pos = 0;
fb->taille = 0;
}
int main(void){
FichierBuffer fb;
wchar_t wc[MAX_LIG];
char cont;
FILE *f = fopen(NOM_FIC,"rb");
if (f == NULL){
printf("Erreur : echec ouverture fichier\n");
return 1;
}
if (!initialiserFichierBuffer(f,&fb)){
printf("Erreur : echec inititialisation lecture\n");
return 1;
}
fclose(f);
if (!lireBOM(&fb)){
printf("Erreur : mauvais encodage UTF8\n");
return 1;
}
setlocale(LC_ALL,"");
#if (defined(WIN32) || defined(_WIN32))
SetConsoleOutputCP(WIN_CODEPAGE); /*Changer le codepage de la console pour un affichage correct\n*/
#endif
do{
cont = lireLigne(&fb,wc);
if (cont != -1){ /*Si pas d'erreur lors de la lecture de la ligne*/
fputws(wc,stdout);
putwchar(L'\n');
}
}
while (cont == 1);
if (cont == -1)
printf("Erreur : echec lecture fichier\n");
supprimerFichierBuffer(&fb);
return 0;
} |
Partager