utf om data in mysql in te voeren werkt niet

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Daniel van Seggelen

Daniel van Seggelen

21/03/2017 21:45:50
Quote Anchor link
Ik heb bijv dit geval:

Ik gebruik de class: http://gasparesganga.com/labs/php-shapefile/#examples
voor in importeren van een shp bestand in mysql.
Ik krijg:

Quote:
Aïn Defla


Zo komt hij in de database.

Ik heb bij de database en het tabel erin het volgende gedaan

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
ALTER DATABASE databasename CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE tablename CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;


In het PHP script heb ik ook dit gedaan:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
header("Content-Type: text/html; charset=UTF-8");
mysqli_query($DBD->conn(),"SET NAMES 'utf8'");
mysqli_query($DBD->conn(),'SET CHARACTER SET utf8');


Maar nee hoor hij blijft de tekens niet opslaan.
Het komt van een geojson bestand. Als ik deze open in kladblok staat daar ook in:

Aïn Defl

Wat kan hier aan de hand zijn?
Gewijzigd op 21/03/2017 22:24:45 door Daniel van Seggelen
 
PHP hulp

PHP hulp

25/12/2024 07:32:00
 
Ivo P

Ivo P

21/03/2017 22:32:12
Quote Anchor link
Je bekijkt de data met een tool of een programma.

Is dat tooltje ook op de hoogte van het feit dat het om unicode gaat?

Je haalt het eerst op en vervolgens gaat het naar Kladblok. Volgens mij blinkt Kladblok nu niet direct uit in dat soort dingen.
 
Daniel van Seggelen

Daniel van Seggelen

21/03/2017 22:37:55
Quote Anchor link
Even wat details, ik gebruik de shp files van: http://www.gadm.org/

Ik bekijk de data zoals het hier staat: http://gasparesganga.com/labs/php-shapefile/#examples


in kladblok bekeek ik het alleen maar om te kijken wat voor encoding het kan zijn.

Ik maak in mijn php script duidelijk (denk ik) dat het om utf-8 gaat. Maar dit werkt zo dus niet.

dit is mijn script:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
ini_set('max_execution_time', 8000);
 ini_set('memory_limit', '-1');


include ("config.php");
include (DOC_ROOT."class/class.php");
$DBD = new DBD();
header('Content-Type: application/json; Charset=UTF-8');
mysqli_query($DBD->conn(),"SET NAMES 'utf8mb4_unicode_ci'");
mysqli_query($DBD->conn(),'SET CHARACTER SET utf8mb4_unicode_ci');

ini_set('display_errors',1);
error_reporting(E_ALL);
// Register autoloader
require_once(DOC_ROOT.'shp/php-shapefile-2.2.0/src/ShapeFileAutoloader.php');
\ShapeFile\ShapeFileAutoloader::register();

// Import classes
use \ShapeFile\ShapeFile;
use \ShapeFile\ShapeFileException;

try {
    // Open shapefile
    $ShapeFile = new ShapeFile(DOC_ROOT.'shp/files/gadm28_adm2.shp');
    
    // Read all the records
    while ($record = $ShapeFile->getRecord(ShapeFile::GEOMETRY_BOTH)) {
        if ($record['dbf']['_deleted']) continue;
        // Geometry
     //  echo $record['shp']['wkt'];
       $wkt = mysqli_real_escape_string($DBD->conn(),$record['shp']['wkt']);
        // DBF Data
//       echo $record['dbf']['ISO'].'<br/;
      
        $reg1 = mysqli_real_escape_string($DBD->conn(),$record['dbf']['NAME_0']);
        $reg2 = mysqli_real_escape_string($DBD->conn(),$record['dbf']['NAME_1']);
        $reg3 = mysqli_real_escape_string($DBD->conn(),$record['dbf']['NAME_2']);

$reg1 = iconv("UTF-8", "ISO-8859-1", $reg1);
$reg2 = iconv("UTF-8", "ISO-8859-1", $reg2);
$reg3 = iconv("UTF-8", "ISO-8859-1", $reg3);

      
                $reg1url = strtolower($DBD->normalize($reg1));
               $reg2url = strtolower($DBD->normalize($reg2));
             $reg3url = strtolower($DBD->normalize($reg3));
      ?>
<pre>
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php print_r($record['dbf']);?>
</pre>
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
<?php

        $r
= mysqli_query($DBD->conn(),"insert into adm3 (iso,SHAPE,Region1,Region2,Region3,Region1Url,Region2Url,Region3Url) values ('".$record['dbf']['ISO']."',GeomFromText('".$wkt."'),'".$reg1."','".$reg2."','".$reg3."','".$reg1url."','".$reg2url."','".$reg3url."')") or die (mysqli_error($DBD->conn()));
//echo "insert into adm3 (iso,SHAPE,Region1,Region2,Region3) values ('".$record['dbf']['ISO']."',GeomFromText('".$wkt."'),'".$reg1."','".$reg2."','".$reg3."')";


    }
    
}
catch (ShapeFileException $e) {
    // Print detailed error information
    exit('Error '.$e->getCode().' ('.$e->getErrorType().'): '.$e->getMessage());
}


Wanneer ik hem naar iso-8859-1 zet,

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
$reg1 = iconv("UTF-8", "ISO-8859-1", $reg1);

werken bepaalde tekens wel, maar heb nog niet alles kunnen testen
Gewijzigd op 21/03/2017 22:41:17 door Daniel van Seggelen
 
Ivo P

Ivo P

21/03/2017 23:48:04
Quote Anchor link
Maar waar komt nu je probleem naar voren?

Alleen in kladblok?
 
Daniel van Seggelen

Daniel van Seggelen

22/03/2017 07:40:35
Quote Anchor link
Nee uiteraard niet in kladblok, wat moet ik nu met kladblok.
Het probleem komt wanneer ik hem importeer in de mysql database
 
Ivo P

Ivo P

22/03/2017 10:05:06
Quote Anchor link
Ik neem aan dat jouw database niet letterlijk zegt "ik heb een probleem met die invoer".

Dus daarom mijn vraag: waarom ben jij van mening dat er een probleem IS?

Kennelijk kijk jij op de een of andere manier in de database. De vraag is: HOE / WAARMEE?
En de vervolgvraag is dan of die methode om kan gaan met unicode, danwel unicode verwacht.

Als je ergens 2 (rare) tekens ziet op een plek waar je eigenlijk 1 teken met een accent verwacht, dan is dat een signaal dat een multibyte (unicode) teken wordt weergegeven door een programma dat single byte karakters verwacht. (en dus niet om kan/wenst te gaan met unicode).
 
Daniel van Seggelen

Daniel van Seggelen

22/03/2017 14:55:55
Quote Anchor link
Vanuit het php bestand dat ik uitlees en in mysql wil plaatsen, komt het probleem dus.
Ik kijk met phpmyadmin in de database.
Mar zoals ik zei als ik hem naar iso-8859-1 zet, en dan invoer dan komt het wel goed in de database met UTF-8 terecht :)
 
Thomas van den Heuvel

Thomas van den Heuvel

22/03/2017 16:12:38
Quote Anchor link
Uhm.

Hoe werkt "DBD" precies?

En het instellen van de character encoding (hierna CE) waarmee je spreekt met je database via SET NAMES / CHARACTER SET wordt afgeraden. Hiervoor is set_charset().

Ik denk dat een van de volgende dingen aan de hand kan zijn:
- de CE van je brondata is niet van de CE die deze zegt te zijn, hierdoor vertaal je dingen fout
- het gaat fout bij het wegschrijven omdat de CE op de verkeerde manier is ingesteld
- het gaat fout bij het uitlezen omdat je daar wellicht de CE wel op de goede manier hebt ingesteld, maar de data zat fout in de database; omdat de connectie van de voorgeschreven CE is (congruent met tabeldefinities), wordt de foute data niet terugvertaald, hierdoor wordt de foute opslag ook niet teruggedraaid
- het gaat fout bij het weergeven omdat je in je meta-tag en/of je PHP-header niet de juiste CE opgeeft of dat deze ontbreekt

ALTER TABLE werkt uiteraard alleen als de data die in de database zat ook daadwerkelijk van de voorgeschreven (oude) CE was, anders wordt de data naar alle waarschijnlijkheid verkeerd vertaald naar de nieuwe CE.

Mijn vermoeden, uitgaande van "Aïn Defla": ergens is niet ingesteld dat je utf8 gebruikt, dus de data wordt alsnog vertaald naar utf8. Voer maar eens een utf8_decode() uit op "Aïn Defla". Dit kan direct te maken hebben met het feit dat je niet op de goede manier een CE instelt bij het maken van de verbinding.

Dit heeft tevens implicaties voor de data die al in je database zit op het moment dat je deze repareert door gebruikmaking van set_charset()! Alle data in je database van voor de reparatie met gebruikmaking van set_charset() is waarschijnlijk 1x teveel utf8-geëncodeerd. Dit ging voorheen goed omdat de database er van uitging dat je latin1-data wenste te ontvangen, daarom werd bij het opvragen van data deze terugvertaald van utf8 naar "latin1" (maar je wilde eigenlijk utf8).
Gewijzigd op 22/03/2017 16:25:54 door Thomas van den Heuvel
 
Ivo P

Ivo P

22/03/2017 17:35:03
Quote Anchor link
bedenk ook dat phpmyadmin ook maar een php-script is.

En volgens mij gaat die er (default) niet vanuit dat er met unicode gewerkt wordt.

Dus dat 1 tool de waarden fout weergeeft, wil niet zeggen dat er ook echt een probleem is.
Zorg dat je script om de data goed is opgezet om met utf te werken. En maak ook een vergelijkbaar script dat de data ophaalt.
Beoordeel dan of het goed ging.

en gebruik niet een of andere willekeurige tool om die al de waarheid aan te houden
 
Thomas van den Heuvel

Thomas van den Heuvel

23/03/2017 01:53:37
Quote Anchor link
Ivo P op 22/03/2017 17:35:03:
bedenk ook dat phpmyadmin ook maar een php-script is.
En volgens mij gaat die er (default) niet vanuit dat er met unicode gewerkt wordt.


Dit maakt denk ik niet uit, zolang je maar consequent één character encoding (hierna weer CE te noemen) aanhoudt. Aangezien phpMyAdmin een pakket is denk ik dat dat intern wel snor zit.

set_charset() vormt in feite een contract tussen de applicatie en de database. Hierin worden (ten minste) twee dingen overeengekomen:
1. de applicatie levert data in de overeengekomen CE aan
2. de database retourneert data in de overeengekomen CE

In feite zeg je "dit is de CE die ik wens te gebruiken / gebruik in mijn applicatie".

De CE van de database/tabellen kan best verschillen van de CE die je gebruikt in je applicatie. MySQL zorgt onder water voor vertalingen. Maar omdat je niet expliciet instelt wat voor CE je gebruikt in je applicatie gaat MySQL mogelijk van een verkeerde default (latin1?) uit. Hiermee breek je (mogelijk onbewust) je eerder gemaakte belofte.

Dit is dan wat er achtereenvolgens gebeurt bij wegschrijven van UTF-8 (utf8) data:
MySQL gaat uit van latin1.
MySQL ontvangt (UTF-8) data en ziet dat deze in een utf8-tabel moet worden weggeschreven.
MySQL encodeert dan (nogmaals) de data naar utf8.

En het ophalen van data:
MySQL gaat uit van latin1.
MySQL ziet dat de data in utf8 tabellen zit.
De applicatie vraagt (impliciet) om latin1 dus MySQL vertaalt de data eenmalig van utf8 naar latin1.

Daarom lijkt het aan de buitenkant allemaal goed te gaan omdat MySQL onder water (overbodige) vertalingen uitvoert die de zaak weer recht lijken te breien.

Het gevaar bij het niet expliciet instellen van een CE is dus dat de data mogelijk dubbel ge-encodeerd wordt weggeschreven. Dit komt dan pas naar buiten bij een export of wanneer je je connectie repareert. Maar dan heb je dus nog steeds stront want de data die al in je database zat wordt dan op de verkeerde manier uitgelezen en is in zekere zin nog steeds "corrupt".

Dit alles is nogal moeilijk over te brengen maar het helpt al enorm veel als er enig bewustzijn wordt gecreëerd van het bestaan van character encoderingen en hoe je hier fatsoenlijk mee om zou moeten gaan... Misschien is de beste remedie nog altijd dat je tot je enkels nek toe in dit soort blubber staat en dan eenmalig uitzoekt hoe dit nu precies werkt :p.
Gewijzigd op 23/03/2017 02:01:37 door Thomas van den Heuvel
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.