Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[.NET/PoSh] Issue met System.IO.StreamReader bij UTF8

Pagina: 1
Acties:

  • YellowOnline
  • Registratie: Januari 2005
  • Laatst online: 28-03-2023

YellowOnline

BEATI PAVPERES SPIRITV

Topicstarter
Dit kadert uiteraard binnen een groot script, maar ik kan het gemakkelijk reproduceren.

Ik sla het volgende op als een tekstbestand in UTF8-formaat D:\test.txt. Echt UTF8 overigens - alle threads die ik over dit onderwerp vond op internet (stackoverflow staat er vol van) blijkt het issue te zijn dat de input niet UTF8 is. De input is hier echt wel UTF8.

code:
1
2
3
4
5
6
7
8
9
10
start
à
ç
ê
©
€
é
è
$
stop


In de PoSh-console doe ik een goeie oude TYPE D:\test.txt en ik krijg de identieke lijst terug.

Nu draai ik de volgende code (PoSh, al gebruik ik de C# lexer) er tegen:

C#:
1
2
3
4
5
6
7
$InputFile = New-Object System.IO.StreamReader("D:\Test.txt", [Text.Encoding]::UTF8, $True)
While(!$InputFile.EndOfStream) 
    {
    $Line = $InputFile.ReadLine()
    $Line   
    }
$InputFile.Close()


Resultaat:
code:
1
2
3
4
5
6
7
8
9
10
start
?
?
?
?
?
?
?
$
stop


Ik heb geen idee waarom System.IO.StreamReader die karakters verkeerd leest. Als iemand ideeën heeft... Alvast bedankt!

[ Voor 3% gewijzigd door YellowOnline op 31-07-2013 14:30 ]


  • HMS
  • Registratie: Januari 2004
  • Laatst online: 17-11 00:33

HMS

Als je de StreamReader hebt gemaakt, wat zegt: MSDN: StreamReader.CurrentEncoding Property (System.IO)

Ander iets, weet je 100% zeker dat de input UTF-8 is?

edit:
Input file bevat alleen een 'é'. Input is opgeslagen met Sublime Text als UTF-8.

code:
1
2
3
4
5
6
7
8
9
PS> $InputFile = New-Object System.IO.StreamReader("D:\Test.txt", [Text.Encoding]::UTF8, $True)
PS> While(!$InputFile.EndOfStream)
>>     {
>>     $Line = $InputFile.ReadLine()
>>     $Line
>>     }
>> $InputFile.Close()
>>
é

[ Voor 52% gewijzigd door HMS op 31-07-2013 14:33 ]


  • YellowOnline
  • Registratie: Januari 2005
  • Laatst online: 28-03-2023

YellowOnline

BEATI PAVPERES SPIRITV

Topicstarter
HMS schreef op woensdag 31 juli 2013 @ 14:29:
Als je de StreamReader hebt gemaakt, wat zegt: MSDN: StreamReader.CurrentEncoding Property (System.IO)

Ander iets, weet je 100% zeker dat de input UTF-8 is?
100% zeker zoals gezegd in de TS. maar misschien haal ik alle twijfel weg met je suggestie te gebruiken:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
?
BodyName          : utf-8
EncodingName      : Unicode (UTF-8)
HeaderName        : utf-8
WebName           : utf-8
WindowsCodePage   : 1200
IsBrowserDisplay  : True
IsBrowserSave     : True
IsMailNewsDisplay : True
IsMailNewsSave    : True
IsSingleByte      : False
EncoderFallback   : System.Text.EncoderReplacementFallback
DecoderFallback   : System.Text.DecoderReplacementFallback
IsReadOnly        : True
CodePage          : 65001


Ivm. de WindowsCodePage en de CodePage: MSDN: Encoding.WindowsCodePage Property (System.Text)
'65001 utf-8 1200 *
Ik zie niet in hoe mijn inputfile niet UTF8 kan zijn als Excel, Notepad++, de PoSh-console en de StreamReader het er allemaal over eens blijken te zijn.

[ Voor 18% gewijzigd door YellowOnline op 31-07-2013 14:39 ]


  • HMS
  • Registratie: Januari 2004
  • Laatst online: 17-11 00:33

HMS

Het is 100% zeker weten toch je input. Bij mij wordt alleen het euro teken niet herkend als ik jouw code gebruik.

code:
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
PS C:\Users\Jos> type D:\test.txt
start
à
ç
ê
©
â'¬
é
è
$
stop
PS C:\Users\Jos> $InputFile = New-Object System.IO.StreamReader("D:\Test.txt", [Text.Encoding]::UTF8, $True)
PS C:\Users\Jos> While(!$InputFile.EndOfStream)
>>     {
>>     $Line = $InputFile.ReadLine()
>>     $Line
>>     }
>> $InputFile.Close()
>>
start
à
ç
ê
©
?
é
è
$
stop
PS C:\Users\Jos>


edit: Ik heb mijn input file voor je geupload: https://www.vandertil.eu/jos/Test.txt

edit2: Van MSDN: MSDN: Encoding.UTF8 Property (System.Text)
The UTF8Encoding object that is returned by this property may not have the appropriate behavior for your application. It uses replacement fallback to replace each string that it cannot encode and each byte that it cannot decode with a question mark ("?") character. [...]

[ Voor 33% gewijzigd door HMS op 31-07-2013 14:44 ]


  • YellowOnline
  • Registratie: Januari 2005
  • Laatst online: 28-03-2023

YellowOnline

BEATI PAVPERES SPIRITV

Topicstarter
HMS schreef op woensdag 31 juli 2013 @ 14:39:
Het is 100% zeker weten toch je input. Bij mij wordt alleen het euro teken niet herkend als ik jouw code gebruik.

code:
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
PS C:\Users\Jos> type D:\test.txt
start
à
ç
ê
©
â'¬
é
è
$
stop
PS C:\Users\Jos> $InputFile = New-Object System.IO.StreamReader("D:\Test.txt", [Text.Encoding]::UTF8, $True)
PS C:\Users\Jos> While(!$InputFile.EndOfStream)
>>     {
>>     $Line = $InputFile.ReadLine()
>>     $Line
>>     }
>> $InputFile.Close()
>>
start
à
ç
ê
©
?
é
è
$
stop
PS C:\Users\Jos>


edit: Ik heb mijn input file voor je geupload: https://www.vandertil.eu/jos/Test.txt
Edit 1
Ik heb het bestand eens opnieuw gemaakt en nu werkt het gewoon wel. Het testbestand wel te verstaan. Het is me een raadsel waarom. Ik ga het echte bestand eens opnieuw genereren en kijken ov het nu om een of andere reden wél werk. Duurt 600 seconden of zo.

Edit 2
De vraagtekens die ik hier zette was omdat ik niet weet hoe het teken uit de console - een rechthoekje - weer te geven op T.net. In de output zelf zijn het gewoon de verkeerde karakters, bijvoorbeeld François wordt François.

Edit 3
Meh. Opnieuw tegen origineel gedraaid en hetzelfde resultaat :(

Edit 4
Dit is de echte (1 200 000 lijnen) inputfile. Merk de UTF-8 op in de rechteronderhoek.

Afbeeldingslocatie: http://tweakers.net/ext/f/5iyL2S5phgoBYSn5dnocsc6k/full.jpg

Edit 5
Oh, interessant. Misschien ben ik in de war geweest en heb ik de dwingende UTF8 later toegevoegd aan de echte code, want nu ik verbose run zie ik dat de speciale karakters in de console wél kloppen. Wanneer het weggeschreven wordt echter niet meer. De output blijkt echter ANSI as UTF8.

Beetje meer code:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    $Filters = Get-Content $FilterFile
    $InputFile = New-Object System.IO.StreamReader($($ScriptPath + "\" + "Installs.csv"),[Text.Encoding]::UTF8,$True)
    $OutputFile = New-Object System.IO.StreamWriter($($ScriptPath + "\" + $(Get-Date -f yyyy-MM-dd) + " " + $(Get-Date -f HHmm) + " " + "Filtered.csv"))
    While(!$InputFile.EndOfStream) 
        {
        $Flag = 0
        $Line = $InputFile.ReadLine()
        ForEach ($Filter in $Filters)
            {
            If ($Line -Match [regex]::Escape($Filter))
                {
                $Flag = 1
                }
            }
        
        If ($Flag -EQ 0)
            {
            $OutputFile.WriteLine($Line)
            }
        }
    $OutputFile.Close()
    $InputFile.Close()


Eens verder op zoeken op de StreamWriter nu...

Edit 6
Het werkt! Ik zat op het verkeerde spoor door een voorbeeldfile te gebruiken ipv. het origineel en daardoor ook vereenvoudigde code te gebruiken waar een en ander ontbrak. Bedankt HMS om me er onbedoeld op te wijzen dat het probleem niet aan de input lag maar wel aan de output. Kon je ook niet weten aangezien de StreamWriter in de code in de TS weggeritst was.

De oplossing is expliciet UTF8 bij het schrijven mee te geven, ondanks dat MSDN beweert dat UTF8 default is (maar dus ANSI as UTF8 blijkt).

C#:
1
$OutputFile = New-Object System.IO.StreamWriter($($ScriptPath + "\" + $(Get-Date -f yyyy-MM-dd) + " " + $(Get-Date -f HHmm) + " " + "Filtered.csv"),$True,[Text.Encoding]::UTF8)

[ Voor 62% gewijzigd door YellowOnline op 31-07-2013 15:27 ]


  • HMS
  • Registratie: Januari 2004
  • Laatst online: 17-11 00:33

HMS

Toch mooi dat ik nog enige hulp heb kunnen bieden :P
Pagina: 1