Karakterkódolás felismerése egy szöveges állományban
Ma (igazából tegnap, de ma kellett rá végleges megoldás) belefutottunk abba a problémába, hogy egy kapott CSV állományról el kellett dönteni, hogy milyen kódolással és milyen sorvége jelekkel lett elkészítve.
A szóba jöhető karakterkódolások száma szerencsére eléggé limitált: Windows 1250 vagy UTF-8. Ezeket megvizsgálva arra jutottam, hogy lehetséges ilyen algoritmust készíteni, mert normál magyar karaktereket feltételezve UTF-8 kódolással 0xFA és 0xFC közötti karakterek nem jöhetnek, viszont Windows 1250-ben ezek az 'ú', 'ü', 'ű' karaketeket jelentik (nem ebben a sorrendben). Ugyanígy, UTF-8-ban egy ékezetes karakternél az első bájt értéke két 1-es és egy 0 bittel fog kezdődni (0b110xxxxx) és a következő bájt egy 1-es és egy 0 bittel kezdődik (0b10xxxxxx). Ezek alapján készült az alábbi egyszerű C forrás, hogy ezeket felismerje:
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
void CheckFileContents( char *filename, int *ccsid, int *lineterm )
{
char *buffer;
int f;
int bytes;
int i;
int currchar, prevchar;
*ccsid = 0;
*lineterm = 0;
prevchar = -1;
buffer = (char * ) malloc( 2048 );
f = open( filename, O_RDONLY, 0 );
if( f >= 0 ) {
bytes = read( f, buffer, 2048 );
while( bytes > 0 && ( *ccsid == 0 || *lineterm == 0 ) ) {
for( i = 0; i < bytes ; i ++ ) {
currchar = (int) buffer[i];
if( *ccsid == 0 ) {
if( ( prevchar & 0xE0 ) == 0xC0 &&
( currchar & 0xC0 ) == 0x80 ) {
*ccsid = 1208;
}
if( ( currchar >= 0xFA ) && ( currchar <= 0xFC ) ) {
*ccsid = 1250;
}
}
if( *lineterm == 0 ) {
if( prevchar == 0x0A && currchar != 0x0D ) {
*lineterm = 1;
}
if( prevchar == 0x0D && currchar != 0x0A ) {
*lineterm = 2;
}
if( prevchar == 0x0D && currchar == 0x0A ) {
*lineterm = 3;
}
if( prevchar == 0x0A && currchar == 0x0D ) {
*lineterm = 4;
}
}
prevchar = currchar;
}
bytes = read( f, buffer, 2048 );
}
close( f );
}
free( buffer );
return;
}
int main( void ) {
int ccsid, lineterm;
char lt[5][4] = { "????", "LF ", "CR ", "CRLF", "LFCR" };
CheckFileContents( "/home/iszell/csv/2010_FELH_20170308_1.csv",
&ccsid, &lineterm );
printf("CCSID: %d, line terminator code: %.4s\n", ccsid, lt[lineterm]);
}
- siz blogja
- A hozzászóláshoz be kell jelentkezni