Delen via


System.Console-klasse

In dit artikel vindt u aanvullende opmerkingen in de referentiedocumentatie voor deze API.

De console is een besturingssysteemvenster waarin gebruikers communiceren met het besturingssysteem of met een consoletoepassing op basis van tekst door tekstinvoer in te voeren via het computertoetsenbord en door tekstuitvoer van de computerterminal te lezen. In het Windows-besturingssysteem wordt de console bijvoorbeeld het opdrachtpromptvenster genoemd en worden MS-DOS opdrachten geaccepteerd. De Console klasse biedt basisondersteuning voor toepassingen waaruit tekens worden gelezen en tekens naar de console worden geschreven.

Console-I/O-streams

Wanneer een consoletoepassing wordt gestart, koppelt het besturingssysteem automatisch drie I/O-streams aan de console: standaardinvoerstroom, standaarduitvoerstroom en standaardfoutuitvoerstroom. Uw toepassing kan gebruikersinvoer lezen uit de standaardinvoerstroom; normale gegevens naar de standaarduitvoerstroom schrijven; en schrijf foutgegevens naar de standaardstroom voor foutuitvoer. Deze streams worden aan uw toepassing gepresenteerd als de waarden van de Console.In, Console.Outen Console.Error eigenschappen.

De waarde van de In eigenschap is standaard een System.IO.TextReader object dat het toetsenbord vertegenwoordigt en de waarden van de Out en Error eigenschappen objecten zijn System.IO.TextWriter objecten die een consolevenster vertegenwoordigen. U kunt deze eigenschappen echter instellen op streams die het consolevenster of toetsenbord niet vertegenwoordigen; U kunt deze eigenschappen bijvoorbeeld instellen op streams die bestanden vertegenwoordigen. Als u de standaardinvoer, standaarduitvoer of standaardfoutstroom wilt omleiden, roept u respectievelijk de Console.SetIn, Console.SetOutof Console.SetError methode aan. I/O-bewerkingen die deze stromen gebruiken, worden gesynchroniseerd, wat betekent dat meerdere threads de streams kunnen lezen of naar de streams kunnen schrijven. Dit betekent dat methoden die gewoonlijk asynchroon zijn, zoals TextReader.ReadLineAsync, synchroon worden uitgevoerd als het object een consolestroom vertegenwoordigt.

Opmerking

Gebruik de Console klasse niet om uitvoer weer te geven in toepassingen zonder toezicht, zoals servertoepassingen. Aanroepen naar methoden zoals Console.Write en Console.WriteLine hebben geen effect in GUI-toepassingen.

Console klasseleden die normaal werken wanneer de onderliggende stroom naar een console wordt omgeleid, kan een uitzondering genereren als de stream bijvoorbeeld wordt omgeleid naar een bestand. Programmeer uw toepassing om uitzonderingen op te vangen System.IO.IOException wanneer u een standaardstream omleidt. U kunt ook de IsOutputRedirected, IsInputRedirecteden IsErrorRedirected eigenschappen gebruiken om te bepalen of een standaardstream wordt omgeleid voordat u een bewerking uitvoert die een System.IO.IOException uitzondering genereert.

Het is soms handig om de leden van de stroomobjecten die worden vertegenwoordigd door de In, Outen Error eigenschappen expliciet aan te roepen. Standaard leest de Console.ReadLine methode bijvoorbeeld invoer uit de standaardinvoerstroom. Op dezelfde manier schrijft de Console.WriteLine methode gegevens naar de standaarduitvoerstroom en worden de gegevens gevolgd door de standaardtekenreeks voor regelafbreking, die te vinden is op Environment.NewLine. De Console klasse biedt echter geen overeenkomstige methode voor het schrijven van gegevens naar de standaardstroom voor foutuitvoer of een eigenschap om de tekenreeks voor regelbeëindiging te wijzigen voor gegevens die naar die stroom zijn geschreven.

U kunt dit probleem oplossen door de eigenschap TextWriter.NewLine van de eigenschap Out of Error in te stellen op een andere regeleinde-tekenreeks. Met de volgende C#-instructie wordt bijvoorbeeld de tekenreeks voor regelbeëindiging voor de standaardfoutuitvoerstroom ingesteld op twee regelterugloop- en regelfeedreeksen:

Console.Error.NewLine = "\r\n\r\n";

U kunt vervolgens expliciet de WriteLine methode van het foutuitvoerstroomobject aanroepen, zoals in de volgende C#-instructie:

Console.Error.WriteLine();

Schermbuffer en consolevenster

Twee nauw verwante functies van de console zijn de schermbuffer en het consolevenster. Tekst wordt daadwerkelijk gelezen van of geschreven naar streams die eigendom zijn van de console, maar lijkt te worden gelezen van of geschreven naar een gebied dat eigendom is van de console, de zogenaamde schermbuffer. De schermbuffer is een kenmerk van de console en is ingedeeld als een rechthoekig raster met rijen en kolommen waar elk rasterknooppunt of tekencel een teken kan bevatten. Elk teken heeft een eigen voorgrondkleur en elke tekencel heeft een eigen achtergrondkleur.

De schermbuffer wordt weergegeven via een rechthoekig gebied dat het consolevenster wordt genoemd. Het consolevenster is een ander kenmerk van de console; het is niet de console zelf, een besturingssysteemvenster. Het consolevenster is gerangschikt in rijen en kolommen, is kleiner dan of gelijk aan de grootte van de schermbuffer en kan worden verplaatst om verschillende gebieden van de onderliggende schermbuffer weer te geven. Als de schermbuffer groter is dan het consolevenster, worden in de console automatisch schuifbalken weergegeven, zodat het consolevenster over het schermbuffergebied kan worden verplaatst.

Een cursor geeft de positie van de schermbuffer aan waar tekst momenteel wordt gelezen of geschreven. De cursor kan worden verborgen of zichtbaar gemaakt en de hoogte ervan kan worden gewijzigd. Als de cursor zichtbaar is, wordt de positie van het consolevenster automatisch verplaatst, zodat de cursor altijd in beeld is.

De oorsprong voor tekencelcoördinaten in de schermbuffer is de linkerbovenhoek en de posities van de cursor en het consolevenster worden gemeten ten opzichte van die oorsprong. Gebruik op nul gebaseerde indexen om posities op te geven; Dat wil gezegd, geef de bovenste rij op als rij 0 en de meest linkse kolom als kolom 0. De maximumwaarde voor de rij- en kolomindexen is Int16.MaxValue.

Unicode-ondersteuning voor de console

In het algemeen leest de console invoer en schrijft uitvoer met behulp van de huidige consolecodepagina, die de landinstelling van het systeem standaard definieert. Een codepagina kan alleen een subset van beschikbare Unicode-tekens verwerken, dus als u tekens probeert weer te geven die niet zijn toegewezen door een bepaalde codepagina, kan de console niet alle tekens weergeven of ze nauwkeurig weergeven. In het volgende voorbeeld ziet u dit probleem. Er wordt geprobeerd de tekens van het Cyrillische alfabet weer te geven van U+0410 naar U+044F naar de console. Als u het voorbeeld uitvoert op een systeem dat gebruikmaakt van consolecodepagina 437, wordt elk teken vervangen door een vraagteken (?), omdat Cyrillische tekens niet worden toegewezen aan de tekens in codepagina 437.

using System;

public class Example3
{
    public static void Main()
    {
        // Create a Char array for the modern Cyrillic alphabet,
        // from U+0410 to U+044F.
        int nChars = 0x044F - 0x0410 + 1;
        char[] chars = new char[nChars];
        ushort codePoint = 0x0410;
        for (int ctr = 0; ctr < chars.Length; ctr++)
        {
            chars[ctr] = (char)codePoint;
            codePoint++;
        }

        Console.WriteLine($"Current code page: {Console.OutputEncoding.CodePage}\n");
        // Display the characters.
        foreach (var ch in chars)
        {
            Console.Write("{0}  ", ch);
            if (Console.CursorLeft >= 70)
                Console.WriteLine();
        }
    }
}
// The example displays the following output:
//    Current code page: 437
//
//    ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?
//    ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?
//    ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?
Module Example
   Public Sub Main()
      ' Create a Char array for the modern Cyrillic alphabet, 
      ' from U+0410 to U+044F.
      Dim nChars As Integer = &h44F - &h0410
      Dim chars(nChars) As Char
      Dim codePoint As UInt16 = &h0410
      For ctr As Integer = 0 To chars.Length - 1
        chars(ctr) = ChrW(codePoint)
        codePoint += CType(1, UShort)
      Next   
         
      Console.WriteLine("Current code page: {0}", 
                        Console.OutputEncoding.CodePage)
      Console.WriteLine()
      ' Display the characters.
      For Each ch In chars
         Console.Write("{0}  ", ch)
         If Console.CursorLeft >= 70 Then Console.WriteLine()
      Next
   End Sub
End Module
' The example displays the following output:
'       Current code page: 437
'       
'       ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?
'       ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?
'       ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?
open System

// Create a char List for the modern Cyrillic alphabet,
// from U+0410 to U+044F.
let chars =
    [ for codePoint in 0x0410 .. 0x044F do
        Convert.ToChar codePoint ]

printfn "Current code page: %i\n" Console.OutputEncoding.CodePage
// Display the characters.
for ch in chars do
    printf "%c  " ch
    if Console.CursorLeft >= 70 then Console.WriteLine()

// The example displays the following output:
//    Current code page: 437
//
//    ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?
//    ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?
//    ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?  ?

Naast ondersteunende codepagina's ondersteunt de Console klasse UTF-8-codering met de UTF8Encoding klasse. Vanaf .NET Framework 4.5 ondersteunt de Console klasse ook UTF-16-codering met de UnicodeEncoding klasse. Unicode-tekens weergeven in de console. u de OutputEncoding eigenschap instelt op UTF8Encoding of UnicodeEncoding.

Voor ondersteuning voor Unicode-tekens moet de encoder een bepaald Unicode-teken herkennen en vereist ook een lettertype met de glyphs die nodig zijn om dat teken weer te geven. Als u Unicode-tekens wilt weergeven in de console, moet het lettertype van de console zijn ingesteld op een niet-raster of TrueType-lettertype, zoals Consolas of Lucida Console. In het volgende voorbeeld ziet u hoe u het lettertype programmatisch kunt wijzigen van een rasterlettertype in Lucida Console.

using System;
using System.Runtime.InteropServices;

public class Example2
{
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr GetStdHandle(int nStdHandle);

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    static extern bool GetCurrentConsoleFontEx(
           IntPtr consoleOutput,
           bool maximumWindow,
           ref CONSOLE_FONT_INFO_EX lpConsoleCurrentFontEx);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool SetCurrentConsoleFontEx(
           IntPtr consoleOutput,
           bool maximumWindow,
           CONSOLE_FONT_INFO_EX consoleCurrentFontEx);

    private const int STD_OUTPUT_HANDLE = -11;
    private const int TMPF_TRUETYPE = 4;
    private const int LF_FACESIZE = 32;
    private static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);

    public static unsafe void Main()
    {
        string fontName = "Lucida Console";
        IntPtr hnd = GetStdHandle(STD_OUTPUT_HANDLE);
        if (hnd != INVALID_HANDLE_VALUE)
        {
            CONSOLE_FONT_INFO_EX info = new CONSOLE_FONT_INFO_EX();
            info.cbSize = (uint)Marshal.SizeOf(info);
            bool tt = false;
            // First determine whether there's already a TrueType font.
            if (GetCurrentConsoleFontEx(hnd, false, ref info))
            {
                tt = (info.FontFamily & TMPF_TRUETYPE) == TMPF_TRUETYPE;
                if (tt)
                {
                    Console.WriteLine("The console already is using a TrueType font.");
                    return;
                }
                // Set console font to Lucida Console.
                CONSOLE_FONT_INFO_EX newInfo = new CONSOLE_FONT_INFO_EX();
                newInfo.cbSize = (uint)Marshal.SizeOf(newInfo);
                newInfo.FontFamily = TMPF_TRUETYPE;
                IntPtr ptr = new IntPtr(newInfo.FaceName);
                Marshal.Copy(fontName.ToCharArray(), 0, ptr, fontName.Length);
                // Get some settings from current font.
                newInfo.dwFontSize = new COORD(info.dwFontSize.X, info.dwFontSize.Y);
                newInfo.FontWeight = info.FontWeight;
                SetCurrentConsoleFontEx(hnd, false, newInfo);
            }
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct COORD
    {
        internal short X;
        internal short Y;

        internal COORD(short x, short y)
        {
            X = x;
            Y = y;
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    internal unsafe struct CONSOLE_FONT_INFO_EX
    {
        internal uint cbSize;
        internal uint nFont;
        internal COORD dwFontSize;
        internal int FontFamily;
        internal int FontWeight;
        internal fixed char FaceName[LF_FACESIZE];
    }
}
Imports System.Runtime.InteropServices

Public Module Example5
    ' <DllImport("kernel32.dll", SetLastError = true)>
    Private Declare Function GetStdHandle Lib "Kernel32" (
                   nStdHandle As Integer) As IntPtr

    ' [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    Private Declare Function GetCurrentConsoleFontEx Lib "Kernel32" (
                   consoleOutput As IntPtr,
                   maximumWindow As Boolean,
                   ByRef lpConsoleCurrentFontEx As CONSOLE_FONT_INFO_EX) As Boolean

    ' [DllImport("kernel32.dll", SetLastError = true)]
    Private Declare Function SetCurrentConsoleFontEx Lib "Kernel32" (
                   consoleOutput As IntPtr,
                   maximumWindow As Boolean,
                   consoleCurrentFontEx As CONSOLE_FONT_INFO_EX) As Boolean

    Private Const STD_OUTPUT_HANDLE As Integer = -11
    Private Const TMPF_TRUETYPE As Integer = 4
    Private Const LF_FACESIZE As Integer = 32
    Private INVALID_HANDLE_VALUE As IntPtr = New IntPtr(-1)

    Public Sub Main()
        Dim fontName As String = "Lucida Console"
        Dim hnd As IntPtr = GetStdHandle(STD_OUTPUT_HANDLE)
        If hnd <> INVALID_HANDLE_VALUE Then
            Dim info As CONSOLE_FONT_INFO_EX = New CONSOLE_FONT_INFO_EX()
            info.cbSize = CUInt(Marshal.SizeOf(info))
            Dim tt As Boolean = False
            ' First determine whether there's already a TrueType font.
            If GetCurrentConsoleFontEx(hnd, False, info) Then
                tt = (info.FontFamily And TMPF_TRUETYPE) = TMPF_TRUETYPE
                If tt Then
                    Console.WriteLine("The console already is using a TrueType font.")
                    Return
                End If
                ' Set console font to Lucida Console.
                Dim newInfo As CONSOLE_FONT_INFO_EX = New CONSOLE_FONT_INFO_EX()
                newInfo.cbSize = CUInt(Marshal.SizeOf(newInfo))
                newInfo.FontFamily = TMPF_TRUETYPE
                newInfo.FaceName = fontName
                ' Get some settings from current font.
                newInfo.dwFontSize = New COORD(info.dwFontSize.X, info.dwFontSize.Y)
                newInfo.FontWeight = info.FontWeight
                SetCurrentConsoleFontEx(hnd, False, newInfo)
            End If
        End If
    End Sub

    <StructLayout(LayoutKind.Sequential)> Friend Structure COORD
        Friend X As Short
        Friend Y As Short

        Friend Sub New(x As Short, y As Short)
            Me.X = x
            Me.Y = y
        End Sub
    End Structure

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> Friend Structure CONSOLE_FONT_INFO_EX
        Friend cbSize As UInteger
        Friend nFont As UInteger
        Friend dwFontSize As COORD
        Friend FontFamily As Integer
        Friend FontWeight As Integer
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=32)> Friend FaceName As String
    End Structure
End Module
module Example

open System
open System.Runtime.InteropServices

[<Literal>]
let STD_OUTPUT_HANDLE = -11

[<Literal>]
let TMPF_TRUETYPE = 4

[<Literal>]
let LF_FACESIZE = 32

let INVALID_HANDLE_VALUE = IntPtr(-1)


[<Struct>]
[<StructLayout(LayoutKind.Sequential)>]
type COORD =
    val mutable X: int16
    val mutable Y: int16

    internal new(x: int16, y: int16) =
        { X = x
          Y = y }

[<Struct>]
[<StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)>]
type CONSOLE_FONT_INFO_EX =
    val mutable cbSize: uint32
    val mutable nFont: uint32
    val mutable dwFontSize: COORD
    val mutable FontFamily: int
    val mutable FontWeight: int
    [<MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)>]
    val mutable FaceName: string

[<DllImport("kernel32.dll", SetLastError = true)>]
extern IntPtr GetStdHandle(int nStdHandle)

[<DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)>]
extern bool GetCurrentConsoleFontEx(IntPtr consoleOutput, bool maximumWindow, CONSOLE_FONT_INFO_EX lpConsoleCurrentFontEx)

[<DllImport("kernel32.dll", SetLastError = true)>]
extern bool SetCurrentConsoleFontEx(IntPtr consoleOutput, bool maximumWindow, CONSOLE_FONT_INFO_EX consoleCurrentFontEx)

[<EntryPoint>]
let main argv =
    let fontName = "Lucida Console"
    let hnd = GetStdHandle(STD_OUTPUT_HANDLE)
    if hnd <> INVALID_HANDLE_VALUE then
        let mutable info = CONSOLE_FONT_INFO_EX()
        info.cbSize <- uint32 (Marshal.SizeOf(info))
        // First determine whether there's already a TrueType font.
        if (GetCurrentConsoleFontEx(hnd, false, info)) then
            if (((info.FontFamily) &&& TMPF_TRUETYPE) = TMPF_TRUETYPE) then
                Console.WriteLine("The console already is using a TrueType font.")
            else
                // Set console font to Lucida Console.
                let mutable newInfo = CONSOLE_FONT_INFO_EX()
                newInfo.cbSize <- uint32 (Marshal.SizeOf(newInfo))
                newInfo.FontFamily <- TMPF_TRUETYPE
                newInfo.FaceName <- fontName
                // Get some settings from current font.
                newInfo.dwFontSize <- COORD(info.dwFontSize.X, info.dwFontSize.Y)
                newInfo.FontWeight <- info.FontWeight
                SetCurrentConsoleFontEx(hnd, false, newInfo) |> ignore
                Console.WriteLine("The console is now using a TrueType font.")

    // Return zero for success
    0

TrueType-lettertypen kunnen echter alleen een subset van glyphs weergeven. Het lettertype Lucida Console bevat bijvoorbeeld slechts 643 van de ongeveer 64.000 beschikbare tekens van U+0021 tot U+FB02. Als u wilt zien welke tekens een bepaald lettertype ondersteunt, opent u de lettertype-applet in het Configuratiescherm, kiest u de optie Een teken zoeken en kiest u het lettertype waarvan u de tekenset wilt onderzoeken in de lijst Lettertype van het venster Tekentoewijzing .

In Windows wordt lettertypekoppeling gebruikt om glyphs weer te geven die niet beschikbaar zijn in een bepaald lettertype. Zie Globalization Step-by-Step: Fonts voor meer informatie over lettertypekoppelingen om extra tekensets weer te geven. Gekoppelde lettertypen worden gedefinieerd in de subsleutel HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink van het register. Elke vermelding die aan deze subsleutel is gekoppeld, komt overeen met de naam van een basislettertype en de bijbehorende waarde is een tekenreeksmatrix die de lettertypebestanden en de lettertypen definieert die zijn gekoppeld aan het basislettertype. Elk element van de array definieert een gekoppeld lettertype en heeft de vorm lettertypebestandsnaam, lettertypenaam. In het volgende voorbeeld ziet u hoe u programmatisch een gekoppeld lettertype met de naam SimSun kunt definiëren in een lettertypebestand met de naam simsun.ttc waarin vereenvoudigde Han-tekens worden weergegeven.

using Microsoft.Win32;
using System;

public class Example
{
   public static void Main()
   {
      string valueName = "Lucida Console";
      string newFont = "simsun.ttc,SimSun";
      string[] fonts = null;
      RegistryValueKind kind = 0;
      bool toAdd;

      RegistryKey key = Registry.LocalMachine.OpenSubKey(
                 @"Software\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink",
                 true);
      if (key == null) {
         Console.WriteLine("Font linking is not enabled.");
      }
      else {
         // Determine if the font is a base font.
         string[] names = key.GetValueNames();
         if (Array.Exists(names, s => s.Equals(valueName,
                                      StringComparison.OrdinalIgnoreCase))) {
            // Get the value's type.
            kind = key.GetValueKind(valueName);

            // Type should be RegistryValueKind.MultiString, but we can't be sure.
            switch (kind) {
               case RegistryValueKind.String:
                  fonts = new string[] { (string) key.GetValue(valueName) };
                  break;
               case RegistryValueKind.MultiString:
                  fonts = (string[]) key.GetValue(valueName);
                  break;
               case RegistryValueKind.None:
                  // Do nothing.
                  fonts = new string[] { };
                  break;
            }
            // Determine whether SimSun is a linked font.
            if (Array.FindIndex(fonts, s =>s.IndexOf("SimSun",
                                       StringComparison.OrdinalIgnoreCase) >=0) >= 0) {
               Console.WriteLine("Font is already linked.");
               toAdd = false;
            }
            else {
               // Font is not a linked font.
               toAdd = true;
            }
         }
         else {
            // Font is not a base font.
            toAdd = true;
            fonts = new string[] { };
         }

         if (toAdd) {
            Array.Resize(ref fonts, fonts.Length + 1);
            fonts[fonts.GetUpperBound(0)] = newFont;
            // Change REG_SZ to REG_MULTI_SZ.
            if (kind == RegistryValueKind.String)
               key.DeleteValue(valueName, false);

            key.SetValue(valueName, fonts, RegistryValueKind.MultiString);
            Console.WriteLine("SimSun added to the list of linked fonts.");
         }
      }

      if (key != null) key.Close();
   }
}
Imports Microsoft.Win32

Module Example2
    Public Sub Main()
        Dim valueName As String = "Lucida Console"
        Dim newFont As String = "simsun.ttc,SimSun"
        Dim fonts() As String = Nothing
        Dim kind As RegistryValueKind
        Dim toAdd As Boolean

        Dim key As RegistryKey = Registry.LocalMachine.OpenSubKey(
                 "Software\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink",
                 True)
        If key Is Nothing Then
            Console.WriteLine("Font linking is not enabled.")
        Else
            ' Determine if the font is a base font.
            Dim names() As String = key.GetValueNames()
            If Array.Exists(names, Function(s) s.Equals(valueName,
                                                     StringComparison.OrdinalIgnoreCase)) Then
                ' Get the value's type.
                kind = key.GetValueKind(valueName)

                ' Type should be RegistryValueKind.MultiString, but we can't be sure.
                Select Case kind
                    Case RegistryValueKind.String
                        fonts = {CStr(key.GetValue(valueName))}
                    Case RegistryValueKind.MultiString
                        fonts = CType(key.GetValue(valueName), String())
                    Case RegistryValueKind.None
                        ' Do nothing.
                        fonts = {}
                End Select
                ' Determine whether SimSun is a linked font.
                If Array.FindIndex(fonts, Function(s) s.IndexOf("SimSun",
                                      StringComparison.OrdinalIgnoreCase) >= 0) >= 0 Then
                    Console.WriteLine("Font is already linked.")
                    toAdd = False
                Else
                    ' Font is not a linked font.
                    toAdd = True
                End If
            Else
                ' Font is not a base font.
                toAdd = True
                fonts = {}
            End If

            If toAdd Then
                Array.Resize(fonts, fonts.Length + 1)
                fonts(fonts.GetUpperBound(0)) = newFont
                ' Change REG_SZ to REG_MULTI_SZ.
                If kind = RegistryValueKind.String Then
                    key.DeleteValue(valueName, False)
                End If
                key.SetValue(valueName, fonts, RegistryValueKind.MultiString)
                Console.WriteLine("SimSun added to the list of linked fonts.")
            End If
        End If

        If key IsNot Nothing Then key.Close()
    End Sub
End Module
open System
open Microsoft.Win32

let valueName = "Lucida Console"
let newFont = "simsun.ttc,SimSun"

let key =
    Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink", true)
if isNull key then
    printfn "Font linking is not enabled."
else
    // Determine if the font is a base font.
    let names = key.GetValueNames()

    let (fonts, kind, toAdd) =
        if names |> Array.exists (fun s -> s.Equals(valueName, StringComparison.OrdinalIgnoreCase)) then
            // Get the value's type.
            let kind = key.GetValueKind(valueName)

            // Type should be RegistryValueKind.MultiString, but we can't be sure.
            let fonts =
                match kind with
                | RegistryValueKind.String -> [| key.GetValue(valueName) :?> string |]
                | RegistryValueKind.MultiString -> (key.GetValue(valueName) :?> string array)
                | _ -> [||]

            // Determine whether SimSun is a linked font.
            let toAdd =
                not (fonts |> Array.exists (fun s -> s.IndexOf("SimSun", StringComparison.OrdinalIgnoreCase) >= 0))

            (fonts, kind, toAdd)
        else
            // Font is not a base font.
            ([||], RegistryValueKind.Unknown, true)

    if toAdd then
        // Font is not a linked font.
        let newFonts = Array.append fonts [| newFont |]

        // Change REG_SZ to REG_MULTI_SZ.
        if kind = RegistryValueKind.String then key.DeleteValue(valueName, false)

        key.SetValue(valueName, newFonts, RegistryValueKind.MultiString)
        printfn "SimSun added to the list of linked fonts."
    else
        printfn "Font is already linked."


if not (isNull key) then key.Close()

Unicode-ondersteuning voor de console heeft de volgende beperkingen:

  • UTF-32-codering wordt niet ondersteund. De enige ondersteunde Unicode-coderingen zijn respectievelijk UTF-8 en UTF-16, die worden vertegenwoordigd door respectievelijk de UTF8Encoding en UnicodeEncoding klassen.

  • Bidirectionele uitvoer wordt niet ondersteund.

  • Weergave van tekens buiten het meertalige basisvlak (van surrogaatparen) wordt niet ondersteund, zelfs niet als ze zijn gedefinieerd in een gekoppeld lettertypebestand.

  • Weergave van tekens in complexe scripts wordt niet ondersteund.

  • Het combineren van tekenreeksen, dat wil zeggen tekens die bestaan uit een basisteken en een of meer combinatietekens, wordt weergegeven als afzonderlijke tekens. Als u deze beperking wilt omzeilen, kunt u de tekenreeks normaliseren die moet worden weergegeven door de String.Normalize methode aan te roepen voordat u uitvoer naar de console verzendt. In het volgende voorbeeld wordt een tekenreeks met de combinatietekenreeks U+0061 U+0308 weergegeven als twee tekens voordat de uitvoertekenreeks wordt genormaliseerd en als één teken na de String.Normalize methode wordt aangeroepen.

    using System;
    using System.IO;
    
    public class Example1
    {
        public static void Main()
        {
            char[] chars = { '\u0061', '\u0308' };
    
            string combining = new String(chars);
            Console.WriteLine(combining);
    
            combining = combining.Normalize();
            Console.WriteLine(combining);
        }
    }
    // The example displays the following output:
    //       a"
    //       ä
    
    Module Example3
        Public Sub Main()
            Dim chars() As Char = {ChrW(&H61), ChrW(&H308)}
    
            Dim combining As String = New String(chars)
            Console.WriteLine(combining)
    
            combining = combining.Normalize()
            Console.WriteLine(combining)
        End Sub
    End Module
    ' The example displays the following output:
    '       a"
    '       ä
    
    open System
    
    let chars = [| '\u0061'; '\u0308' |]
    
    let combining = String chars
    Console.WriteLine combining
    
    let combining2 = combining.Normalize()
    Console.WriteLine combining2
    
    
    // The example displays the following output:
    //       a"
    //       ä
    

    Normalisatie is alleen mogelijk als de Unicode-standaard voor het teken een vooraf samengesteld formulier bevat dat overeenkomt met een bepaalde combinatietekenreeks.

  • Als een lettertype een symbool bevat voor een codepunt in het gebied voor privégebruik, wordt die glyph weergegeven. Omdat tekens in het gebied voor privégebruik echter toepassingsspecifiek zijn, is dit mogelijk niet het verwachte symbool.

In het volgende voorbeeld wordt een reeks Unicode-tekens op de console weergegeven. In het voorbeeld worden drie opdrachtregelparameters geaccepteerd: het begin van het bereik dat moet worden weergegeven, het einde van het bereik dat moet worden weergegeven en of de huidige consolecodering (false) of UTF-16-codering (true) moet worden gebruikt. Hierbij wordt ervan uitgegaan dat de console een TrueType-lettertype gebruikt.

using System;
using System.IO;
using System.Globalization;
using System.Text;

public static class DisplayChars
{
    private static void Main(string[] args)
    {
        uint rangeStart = 0;
        uint rangeEnd = 0;
        bool setOutputEncodingToUnicode = true;
        // Get the current encoding so we can restore it.
        Encoding originalOutputEncoding = Console.OutputEncoding;

        try
        {
            switch (args.Length)
            {
                case 2:
                    rangeStart = uint.Parse(args[0], NumberStyles.HexNumber);
                    rangeEnd = uint.Parse(args[1], NumberStyles.HexNumber);
                    setOutputEncodingToUnicode = true;
                    break;
                case 3:
                    if (!uint.TryParse(args[0], NumberStyles.HexNumber, null, out rangeStart))
                        throw new ArgumentException(string.Format("{0} is not a valid hexadecimal number.", args[0]));

                    if (!uint.TryParse(args[1], NumberStyles.HexNumber, null, out rangeEnd))
                        throw new ArgumentException(string.Format("{0} is not a valid hexadecimal number.", args[1]));

                    _ = bool.TryParse(args[2], out setOutputEncodingToUnicode);
                    break;
                default:
                    Console.WriteLine("Usage: {0} <{1}> <{2}> [{3}]",
                        Environment.GetCommandLineArgs()[0],
                        "startingCodePointInHex",
                        "endingCodePointInHex",
                        "<setOutputEncodingToUnicode?{true|false, default:false}>");
                    return;
            }

            if (setOutputEncodingToUnicode)
            {
                try
                {
                    // Set encoding using endianness of this system.
                    // We're interested in displaying individual Char objects, so
                    // we don't want a Unicode BOM or exceptions to be thrown on
                    // invalid Char values.
                    Console.OutputEncoding = new UnicodeEncoding(!BitConverter.IsLittleEndian, false);
                    Console.WriteLine("\nOutput encoding set to UTF-16");
                }
                catch (IOException)
                {
                    Console.OutputEncoding = new UTF8Encoding();
                    Console.WriteLine("Output encoding set to UTF-8");
                }
            }
            else
            {
                Console.WriteLine($"The console encoding is {Console.OutputEncoding.EncodingName} (code page {Console.OutputEncoding.CodePage})");
            }
            DisplayRange(rangeStart, rangeEnd);
        }
        catch (ArgumentException ex)
        {
            Console.WriteLine(ex.Message);
        }
        finally
        {
            // Restore console environment.
            Console.OutputEncoding = originalOutputEncoding;
        }
    }

    public static void DisplayRange(uint start, uint end)
    {
        const uint upperRange = 0x10FFFF;
        const uint surrogateStart = 0xD800;
        const uint surrogateEnd = 0xDFFF;

        if (end <= start)
        {
            uint t = start;
            start = end;
            end = t;
        }

        // Check whether the start or end range is outside of last plane.
        if (start > upperRange)
            throw new ArgumentException(string.Format("0x{0:X5} is outside the upper range of Unicode code points (0x{1:X5})",
                                                      start, upperRange));
        if (end > upperRange)
            throw new ArgumentException(string.Format("0x{0:X5} is outside the upper range of Unicode code points (0x{0:X5})",
                                                      end, upperRange));

        // Since we're using 21-bit code points, we can't use U+D800 to U+DFFF.
        if ((start < surrogateStart & end > surrogateStart) || (start >= surrogateStart & start <= surrogateEnd))
            throw new ArgumentException(string.Format("0x{0:X5}-0x{1:X5} includes the surrogate pair range 0x{2:X5}-0x{3:X5}",
                                                      start, end, surrogateStart, surrogateEnd));
        uint last = RoundUpToMultipleOf(0x10, end);
        uint first = RoundDownToMultipleOf(0x10, start);

        uint rows = (last - first) / 0x10;

        for (uint r = 0; r < rows; ++r)
        {
            // Display the row header.
            Console.Write("{0:x5} ", first + 0x10 * r);

            for (uint c = 0; c < 0x10; ++c)
            {
                uint cur = (first + 0x10 * r + c);
                if (cur < start)
                {
                    Console.Write($" {(char)(0x20)} ");
                }
                else if (end < cur)
                {
                    Console.Write($" {(char)(0x20)} ");
                }
                else
                {
                    // the cast to int is safe, since we know that val <= upperRange.
                    String chars = Char.ConvertFromUtf32((int)cur);
                    // Display a space for code points that are not valid characters.
                    if (CharUnicodeInfo.GetUnicodeCategory(chars[0]) ==
                                                    UnicodeCategory.OtherNotAssigned)
                        Console.Write($" {(char)(0x20)} ");
                    // Display a space for code points in the private use area.
                    else if (CharUnicodeInfo.GetUnicodeCategory(chars[0]) ==
                                                   UnicodeCategory.PrivateUse)
                        Console.Write($" {(char)(0x20)} ");
                    // Is surrogate pair a valid character?
                    // Note that the console will interpret the high and low surrogate
                    // as separate (and unrecognizable) characters.
                    else if (chars.Length > 1 && CharUnicodeInfo.GetUnicodeCategory(chars, 0) ==
                                                 UnicodeCategory.OtherNotAssigned)
                        Console.Write($" {(char)(0x20)} ");
                    else
                        Console.Write($" {chars} ");
                }

                switch (c)
                {
                    case 3:
                    case 11:
                        Console.Write("-");
                        break;
                    case 7:
                        Console.Write("--");
                        break;
                }
            }

            Console.WriteLine();
            if (0 < r && r % 0x10 == 0)
                Console.WriteLine();
        }
    }

    private static uint RoundUpToMultipleOf(uint b, uint u)
    {
        return RoundDownToMultipleOf(b, u) + b;
    }

    private static uint RoundDownToMultipleOf(uint b, uint u)
    {
        return u - (u % b);
    }
}
// If the example is run with the command line
//       DisplayChars 0400 04FF true
// the example displays the Cyrillic character set as follows:
//       Output encoding set to UTF-16
//       00400  Ѐ  Ё  Ђ  Ѓ - Є  Ѕ  І  Ї -- Ј  Љ  Њ  Ћ - Ќ  Ѝ  Ў  Џ
//       00410  А  Б  В  Г - Д  Е  Ж  З -- И  Й  К  Л - М  Н  О  П
//       00420  Р  С  Т  У - Ф  Х  Ц  Ч -- Ш  Щ  Ъ  Ы - Ь  Э  Ю  Я
//       00430  а  б  в  г - д  е  ж  з -- и  й  к  л - м  н  о  п
//       00440  р  с  т  у - ф  х  ц  ч -- ш  щ  ъ  ы - ь  э  ю  я
//       00450  ѐ  ё  ђ  ѓ - є  ѕ  і  ї -- ј  љ  њ  ћ - ќ  ѝ  ў  џ
//       00460  Ѡ  ѡ  Ѣ  ѣ - Ѥ  ѥ  Ѧ  ѧ -- Ѩ  ѩ  Ѫ  ѫ - Ѭ  ѭ  Ѯ  ѯ
//       00470  Ѱ  ѱ  Ѳ  ѳ - Ѵ  ѵ  Ѷ  ѷ -- Ѹ  ѹ  Ѻ  ѻ - Ѽ  ѽ  Ѿ  ѿ
//       00480  Ҁ  ҁ  ҂  ҃ - ҄  ҅  ҆  ҇ -- ҈  ҉  Ҋ  ҋ - Ҍ  ҍ  Ҏ  ҏ
//       00490  Ґ  ґ  Ғ  ғ - Ҕ  ҕ  Җ  җ -- Ҙ  ҙ  Қ  қ - Ҝ  ҝ  Ҟ  ҟ
//       004a0  Ҡ  ҡ  Ң  ң - Ҥ  ҥ  Ҧ  ҧ -- Ҩ  ҩ  Ҫ  ҫ - Ҭ  ҭ  Ү  ү
//       004b0  Ұ  ұ  Ҳ  ҳ - Ҵ  ҵ  Ҷ  ҷ -- Ҹ  ҹ  Һ  һ - Ҽ  ҽ  Ҿ  ҿ
//       004c0  Ӏ  Ӂ  ӂ  Ӄ - ӄ  Ӆ  ӆ  Ӈ -- ӈ  Ӊ  ӊ  Ӌ - ӌ  Ӎ  ӎ  ӏ
//       004d0  Ӑ  ӑ  Ӓ  ӓ - Ӕ  ӕ  Ӗ  ӗ -- Ә  ә  Ӛ  ӛ - Ӝ  ӝ  Ӟ  ӟ
//       004e0  Ӡ  ӡ  Ӣ  ӣ - Ӥ  ӥ  Ӧ  ӧ -- Ө  ө  Ӫ  ӫ - Ӭ  ӭ  Ӯ  ӯ
//       004f0  Ӱ  ӱ  Ӳ  ӳ - Ӵ  ӵ  Ӷ  ӷ -- Ӹ  ӹ  Ӻ  ӻ - Ӽ  ӽ  Ӿ  ӿ
Imports System.IO
Imports System.Globalization
Imports System.Text

Public Module DisplayChars
   Public Sub Main(args() As String)
      Dim rangeStart As UInteger = 0
      Dim rangeEnd As UInteger = 0
      Dim setOutputEncodingToUnicode As Boolean = True
      ' Get the current encoding so we can restore it.
      Dim originalOutputEncoding As Encoding = Console.OutputEncoding

    Try
         Select Case args.Length
            Case 2
               rangeStart = UInt32.Parse(args(0), NumberStyles.HexNumber)
               rangeEnd = UInt32.Parse(args(1), NumberStyles.HexNumber)
               setOutputEncodingToUnicode = True
            Case 3
               If Not UInt32.TryParse(args(0), NumberStyles.HexNumber, Nothing, rangeStart) Then
                  Throw New ArgumentException(String.Format("{0} is not a valid hexadecimal number.", args(0)))
               End If
               
               If Not UInt32.TryParse(args(1), NumberStyles.HexNumber, Nothing, rangeEnd) Then
                  Throw New ArgumentException(String.Format("{0} is not a valid hexadecimal number.", args(1)))
               End If
               
               Boolean.TryParse(args(2), setOutputEncodingToUnicode)
            Case Else
               Console.WriteLine("Usage: {0} <{1}> <{2}> [{3}]", 
                                 Environment.GetCommandLineArgs()(0), 
                                 "startingCodePointInHex", 
                                 "endingCodePointInHex", 
                                 "<setOutputEncodingToUnicode?{true|false, default:false}>")
               Exit Sub
         End Select
   
         If setOutputEncodingToUnicode Then
            ' This won't work before .NET Framework 4.5.
            Try 
               ' Set encoding Imports endianness of this system.
               ' We're interested in displaying individual Char objects, so 
               ' we don't want a Unicode BOM or exceptions to be thrown on
               ' invalid Char values.
               Console.OutputEncoding = New UnicodeEncoding(Not BitConverter.IsLittleEndian, False) 
               Console.WriteLine("{0}Output encoding set to UTF-16", vbCrLf)
            Catch e As IOException
               Console.OutputEncoding = New UTF8Encoding()
               Console.WriteLine("Output encoding set to UTF-8")
            End Try
         Else
            Console.WriteLine("The console encoding is {0} (code page {1})", 
                              Console.OutputEncoding.EncodingName,
                              Console.OutputEncoding.CodePage)
         End If
         DisplayRange(rangeStart, rangeEnd)
      Catch ex As ArgumentException
         Console.WriteLine(ex.Message)
      Finally
         ' Restore console environment.
         Console.OutputEncoding = originalOutputEncoding
      End Try
   End Sub

   Public Sub DisplayRange(rangeStart As UInteger, rangeEnd As UInteger)
      Const upperRange As UInteger = &h10FFFF
      Const surrogateStart As UInteger = &hD800
      Const surrogateEnd As UInteger = &hDFFF
       
      If rangeEnd <= rangeStart Then
         Dim t As UInteger = rangeStart
         rangeStart = rangeEnd
         rangeEnd = t
      End If

      ' Check whether the start or end range is outside of last plane.
      If rangeStart > upperRange Then
         Throw New ArgumentException(String.Format("0x{0:X5} is outside the upper range of Unicode code points (0x{1:X5})",
                                                   rangeStart, upperRange))                                   
      End If
      If rangeEnd > upperRange Then
         Throw New ArgumentException(String.Format("0x{0:X5} is outside the upper range of Unicode code points (0x{0:X5})",
                                                   rangeEnd, upperRange))
      End If
      ' Since we're using 21-bit code points, we can't use U+D800 to U+DFFF.
      If (rangeStart < surrogateStart And rangeEnd > surrogateStart) OrElse (rangeStart >= surrogateStart And rangeStart <= surrogateEnd )
         Throw New ArgumentException(String.Format("0x{0:X5}-0x{1:X5} includes the surrogate pair range 0x{2:X5}-0x{3:X5}", 
                                                   rangeStart, rangeEnd, surrogateStart, surrogateEnd))         
      End If
      
      Dim last As UInteger = RoundUpToMultipleOf(&h10, rangeEnd)
      Dim first As UInteger = RoundDownToMultipleOf(&h10, rangeStart)

      Dim rows As UInteger = (last - first) \ &h10

      For r As UInteger = 0 To rows - 1
         ' Display the row header.
         Console.Write("{0:x5} ", first + &h10 * r)

         For c As UInteger = 1 To &h10
            Dim cur As UInteger = first + &h10 * r + c
            If cur  < rangeStart Then
               Console.Write(" {0} ", Convert.ToChar(&h20))
            Else If rangeEnd < cur Then
               Console.Write(" {0} ", Convert.ToChar(&h20))
            Else 
               ' the cast to int is safe, since we know that val <= upperRange.
               Dim chars As String = Char.ConvertFromUtf32(CInt(cur))
               ' Display a space for code points that are not valid characters.
               If CharUnicodeInfo.GetUnicodeCategory(chars(0)) = 
                                   UnicodeCategory.OtherNotAssigned Then
                  Console.Write(" {0} ", Convert.ToChar(&h20))
               ' Display a space for code points in the private use area.
               Else If CharUnicodeInfo.GetUnicodeCategory(chars(0)) =
                                        UnicodeCategory.PrivateUse Then
                 Console.Write(" {0} ", Convert.ToChar(&h20))
               ' Is surrogate pair a valid character?
               ' Note that the console will interpret the high and low surrogate
               ' as separate (and unrecognizable) characters.
               Else If chars.Length > 1 AndAlso CharUnicodeInfo.GetUnicodeCategory(chars, 0) = 
                                            UnicodeCategory.OtherNotAssigned Then
                  Console.Write(" {0} ", Convert.ToChar(&h20))
               Else
                  Console.Write(" {0} ", chars) 
               End If   
            End If
            
            Select Case c
               Case 3, 11
                  Console.Write("-")
               Case 7
                  Console.Write("--")
            End Select
         Next

         Console.WriteLine()
         If 0 < r AndAlso r Mod &h10 = 0
            Console.WriteLine()
         End If
      Next
   End Sub

   Private Function RoundUpToMultipleOf(b As UInteger, u As UInteger) As UInteger
      Return RoundDownToMultipleOf(b, u) + b
   End Function

   Private Function RoundDownToMultipleOf(b As UInteger, u As UInteger) As UInteger
      Return u - (u Mod b)
   End Function
End Module
' If the example is run with the command line
'       DisplayChars 0400 04FF true
' the example displays the Cyrillic character set as follows:
'       Output encoding set to UTF-16
'       00400  Ѐ  Ё  Ђ  Ѓ - Є  Ѕ  І  Ї -- Ј  Љ  Њ  Ћ - Ќ  Ѝ  Ў  Џ
'       00410  А  Б  В  Г - Д  Е  Ж  З -- И  Й  К  Л - М  Н  О  П
'       00420  Р  С  Т  У - Ф  Х  Ц  Ч -- Ш  Щ  Ъ  Ы - Ь  Э  Ю  Я
'       00430  а  б  в  г - д  е  ж  з -- и  й  к  л - м  н  о  п
'       00440  р  с  т  у - ф  х  ц  ч -- ш  щ  ъ  ы - ь  э  ю  я
'       00450  ѐ  ё  ђ  ѓ - є  ѕ  і  ї -- ј  љ  њ  ћ - ќ  ѝ  ў  џ
'       00460  Ѡ  ѡ  Ѣ  ѣ - Ѥ  ѥ  Ѧ  ѧ -- Ѩ  ѩ  Ѫ  ѫ - Ѭ  ѭ  Ѯ  ѯ
'       00470  Ѱ  ѱ  Ѳ  ѳ - Ѵ  ѵ  Ѷ  ѷ -- Ѹ  ѹ  Ѻ  ѻ - Ѽ  ѽ  Ѿ  ѿ
'       00480  Ҁ  ҁ  ҂  ҃ - ҄  ҅  ҆  ҇ -- ҈  ҉  Ҋ  ҋ - Ҍ  ҍ  Ҏ  ҏ
'       00490  Ґ  ґ  Ғ  ғ - Ҕ  ҕ  Җ  җ -- Ҙ  ҙ  Қ  қ - Ҝ  ҝ  Ҟ  ҟ
'       004a0  Ҡ  ҡ  Ң  ң - Ҥ  ҥ  Ҧ  ҧ -- Ҩ  ҩ  Ҫ  ҫ - Ҭ  ҭ  Ү  ү
'       004b0  Ұ  ұ  Ҳ  ҳ - Ҵ  ҵ  Ҷ  ҷ -- Ҹ  ҹ  Һ  һ - Ҽ  ҽ  Ҿ  ҿ
'       004c0  Ӏ  Ӂ  ӂ  Ӄ - ӄ  Ӆ  ӆ  Ӈ -- ӈ  Ӊ  ӊ  Ӌ - ӌ  Ӎ  ӎ  ӏ
'       004d0  Ӑ  ӑ  Ӓ  ӓ - Ӕ  ӕ  Ӗ  ӗ -- Ә  ә  Ӛ  ӛ - Ӝ  ӝ  Ӟ  ӟ
'       004e0  Ӡ  ӡ  Ӣ  ӣ - Ӥ  ӥ  Ӧ  ӧ -- Ө  ө  Ӫ  ӫ - Ӭ  ӭ  Ӯ  ӯ
'       004f0  Ӱ  ӱ  Ӳ  ӳ - Ӵ  ӵ  Ӷ  ӷ -- Ӹ  ӹ  Ӻ  ӻ - Ӽ  ӽ  Ӿ  ӿ
module DisplayChars

open System
open System.IO
open System.Globalization
open System.Text

type uint = uint32

let inline roundDownToMultipleOf b u = u - (u % b)

let inline roundUpToMultipleOf b u = roundDownToMultipleOf b u |> (+) b

let displayRange (start: uint) (``end``: uint) =

    let upperRange = 0x10FFFFu
    let surrogateStart = 0xD800u
    let surrogateEnd = 0xDFFFu

    let start, ``end`` =
        if ``end`` <= start then ``end``, start
        else start, ``end``

    // Check whether the start or end range is outside of last plane.
    if start > upperRange then
        invalidArg "start"
            (String.Format("0x{0:X5} is outside the upper range of Unicode code points (0x{1:X5})", start, upperRange))
    if ``end`` > upperRange then
        invalidArg "end"
            (String.Format("0x{0:X5} is outside the upper range of Unicode code points (0x{0:X5})", ``end``, upperRange))

    // Since we're using 21-bit code points, we can't use U+D800 to U+DFFF.
    if (start < surrogateStart && ``end`` > surrogateStart) || (start >= surrogateStart && start <= surrogateEnd) then
        raise
            (ArgumentException
                (String.Format
                    ("0x{0:X5}-0x{1:X5} includes the surrogate pair range 0x{2:X5}-0x{3:X5}", start, ``end``,
                     surrogateStart, surrogateEnd)))
    let last = roundUpToMultipleOf 0x10u ``end``
    let first = roundDownToMultipleOf 0x10u start

    let rows = (last - first) / 0x10u

    for r in 0u .. (rows - 1u) do
        // Display the row header.
        printf "%05x " (first + 0x10u * r)

        for c in 0u .. (0x10u - 1u) do
            let cur = (first + 0x10u * r + c)
            if cur < start || ``end`` < cur then
                printf " %c " (Convert.ToChar 0x20)
            else
                // the cast to int is safe, since we know that val <= upperRange.
                let chars = Char.ConvertFromUtf32(int cur)
                // Display a space for code points that are not valid characters.
                if CharUnicodeInfo.GetUnicodeCategory(chars[0]) = UnicodeCategory.OtherNotAssigned then
                    printf " %c " (Convert.ToChar 0x20)
                else
                    // Display a space for code points in the private use area.
                    if CharUnicodeInfo.GetUnicodeCategory(chars[0]) = UnicodeCategory.PrivateUse then
                        printf " %c " (Convert.ToChar 0x20)
                    else if chars.Length > 1
                            && CharUnicodeInfo.GetUnicodeCategory(chars, 0) = UnicodeCategory.OtherNotAssigned then
                        printf " %c " (Convert.ToChar 0x20)
                    else printf " %s " chars

            match c with
            | 3u
            | 11u -> printf "-"
            | 7u -> printf "--"
            | _ -> ()

        Console.WriteLine()
        if (0u < r && r % 0x10u = 0u) then Console.WriteLine()



[<EntryPoint>]
let main args =
    // Get the current encoding so we can restore it.
    let originalOutputEncoding = Console.OutputEncoding

    try
        try
            let parsedArgs =
                match args.Length with
                | 2 ->
                    Some
                        {| setOutputEncodingToUnicode = true
                           rangeStart = uint.Parse(args[0], NumberStyles.HexNumber)
                           rangeEnd = uint.Parse(args[1], NumberStyles.HexNumber) |}
                | 3 ->
                    let parseHexNumberOrThrow (value: string) parameterName =
                        (uint.TryParse(value, NumberStyles.HexNumber, null))
                        |> function
                        | (false, _) ->
                            invalidArg parameterName (String.Format("{0} is not a valid hexadecimal number.", value))
                        | (true, value) -> value

                    let setOutputEncodingToUnicode =
                        match bool.TryParse args[2] with
                        | true, value -> value
                        | false, _ -> true

                    Some
                        {| setOutputEncodingToUnicode = setOutputEncodingToUnicode
                           rangeStart = parseHexNumberOrThrow args[0] "rangeStart"
                           rangeEnd = parseHexNumberOrThrow args[1] "rangeEnd" |}
                | _ ->
                    printfn "Usage: %s <%s> <%s> [%s]" (Environment.GetCommandLineArgs()[0]) "startingCodePointInHex"
                        "endingCodePointInHex" "<setOutputEncodingToUnicode?{true|false, default:false}>"
                    None

            match parsedArgs with
            | None -> ()
            | Some parsedArgs ->
                if parsedArgs.setOutputEncodingToUnicode then
                    // This won't work before .NET Framework 4.5.
                    try
                        // Set encoding using endianness of this system.
                        // We're interested in displaying individual Char objects, so
                        // we don't want a Unicode BOM or exceptions to be thrown on
                        // invalid Char values.
                        Console.OutputEncoding <- UnicodeEncoding(not BitConverter.IsLittleEndian, false)
                        printfn "\nOutput encoding set to UTF-16"

                    with :? IOException ->
                        printfn "Output encoding set to UTF-8"
                        Console.OutputEncoding <- UTF8Encoding()
                else
                    printfn "The console encoding is %s (code page %i)" (Console.OutputEncoding.EncodingName)
                        (Console.OutputEncoding.CodePage)

                displayRange parsedArgs.rangeStart parsedArgs.rangeEnd
        with :? ArgumentException as ex -> Console.WriteLine(ex.Message)
    finally
        // Restore console environment.
        Console.OutputEncoding <- originalOutputEncoding
    0

// If the example is run with the command line
//       DisplayChars 0400 04FF true
// the example displays the Cyrillic character set as follows:
//       Output encoding set to UTF-16
//       00400  Ѐ  Ё  Ђ  Ѓ - Є  Ѕ  І  Ї -- Ј  Љ  Њ  Ћ - Ќ  Ѝ  Ў  Џ
//       00410  А  Б  В  Г - Д  Е  Ж  З -- И  Й  К  Л - М  Н  О  П
//       00420  Р  С  Т  У - Ф  Х  Ц  Ч -- Ш  Щ  Ъ  Ы - Ь  Э  Ю  Я
//       00430  а  б  в  г - д  е  ж  з -- и  й  к  л - м  н  о  п
//       00440  р  с  т  у - ф  х  ц  ч -- ш  щ  ъ  ы - ь  э  ю  я
//       00450  ѐ  ё  ђ  ѓ - є  ѕ  і  ї -- ј  љ  њ  ћ - ќ  ѝ  ў  џ
//       00460  Ѡ  ѡ  Ѣ  ѣ - Ѥ  ѥ  Ѧ  ѧ -- Ѩ  ѩ  Ѫ  ѫ - Ѭ  ѭ  Ѯ  ѯ
//       00470  Ѱ  ѱ  Ѳ  ѳ - Ѵ  ѵ  Ѷ  ѷ -- Ѹ  ѹ  Ѻ  ѻ - Ѽ  ѽ  Ѿ  ѿ
//       00480  Ҁ  ҁ  ҂  ҃ - ҄  ҅  ҆  ҇ -- ҈  ҉  Ҋ  ҋ - Ҍ  ҍ  Ҏ  ҏ
//       00490  Ґ  ґ  Ғ  ғ - Ҕ  ҕ  Җ  җ -- Ҙ  ҙ  Қ  қ - Ҝ  ҝ  Ҟ  ҟ
//       004a0  Ҡ  ҡ  Ң  ң - Ҥ  ҥ  Ҧ  ҧ -- Ҩ  ҩ  Ҫ  ҫ - Ҭ  ҭ  Ү  ү
//       004b0  Ұ  ұ  Ҳ  ҳ - Ҵ  ҵ  Ҷ  ҷ -- Ҹ  ҹ  Һ  һ - Ҽ  ҽ  Ҿ  ҿ
//       004c0  Ӏ  Ӂ  ӂ  Ӄ - ӄ  Ӆ  ӆ  Ӈ -- ӈ  Ӊ  ӊ  Ӌ - ӌ  Ӎ  ӎ  ӏ
//       004d0  Ӑ  ӑ  Ӓ  ӓ - Ӕ  ӕ  Ӗ  ӗ -- Ә  ә  Ӛ  ӛ - Ӝ  ӝ  Ӟ  ӟ
//       004e0  Ӡ  ӡ  Ӣ  ӣ - Ӥ  ӥ  Ӧ  ӧ -- Ө  ө  Ӫ  ӫ - Ӭ  ӭ  Ӯ  ӯ
//       004f0  Ӱ  ӱ  Ӳ  ӳ - Ӵ  ӵ  Ӷ  ӷ -- Ӹ  ӹ  Ӻ  ӻ - Ӽ  ӽ  Ӿ  ӿ

Algemene bewerkingen

De Console klasse bevat de volgende methoden voor het lezen van console-invoer en het schrijven van console-uitvoer:

  • De overbelasting van de ReadKey methode leest een afzonderlijk teken.

  • De ReadLine methode leest een hele regel invoer.

  • De overladen methoden converteren een exemplaar van een waardetype, een tekenreeks of een set objecten naar een opgemaakte of niet-opgemaakte string en schrijven die string vervolgens naar de console.

  • Een parallelle set WriteLine methode-overbelastingen levert dezelfde tekenreeks op als de Write overbelastingen, maar voegt ook een regelafbrekingstekenreeks toe.

De Console klasse bevat ook methoden en eigenschappen om de volgende bewerkingen uit te voeren:

  • De grootte van de schermbuffer ophalen of instellen. De eigenschap BufferHeight en BufferWidth laten u respectievelijk de bufferhoogte en -breedte ophalen of instellen, en de methode SetBufferSize laat u de buffergrootte instellen in één methodeaanroep.

  • De grootte van het consolevenster ophalen of instellen. Met de eigenschappen WindowHeight en WindowWidth kunt u de hoogte en breedte van het venster ophalen of instellen, respectievelijk, en met de SetWindowSize methode kunt u de venstergrootte in één keer instellen.

  • De grootte van de cursor ophalen of instellen. De CursorSize eigenschap geeft de hoogte van de cursor in een tekencel op.

  • De positie van het consolevenster ten opzichte van de schermbuffer ophalen of instellen. Met de eigenschappen WindowTop en WindowLeft kunt u de bovenste rij en meest linkse kolom van de schermbuffer ophalen of instellen die zichtbaar is in het consolevenster, en met de SetWindowPosition methode kunt u deze waarden instellen in één methode-aanroep.

  • Haal de positie van de cursor op of stel deze in door de CursorTop en CursorLeft eigenschappen op te halen of in te stellen, of stel de positie van de cursor in door de methode aan te SetCursorPosition roepen.

  • Verplaats of wis gegevens in de schermbuffer door de MoveBufferArea of Clear methode aan te roepen.

  • Haal de voor- en achtergrondkleuren op of stel deze in met behulp van de ForegroundColor en BackgroundColor eigenschappen, of stel de achtergrond en voorgrond in op de standaardkleuren door de ResetColor methode aan te roepen.

  • Speel het geluid van een pieptoon via de consoleluidspreker af door de methode aan te Beep roepen.

.NET Core-notities

In .NET Framework op het bureaublad gebruikt de Console klasse de codering die wordt geretourneerd door GetConsoleCP en GetConsoleOutputCP, meestal een codepaginacodering. Code bijvoorbeeld, op systemen waarvan de cultuur Engels (Verenigde Staten) is, is codepagina 437 de codering die standaard wordt gebruikt. .NET Core kan echter slechts een beperkte subset van deze coderingen beschikbaar maken. Als dit het geval is, Encoding.UTF8 wordt deze gebruikt als de standaardcodering voor de console.

Als uw app afhankelijk is van specifieke codepaginacoderingen, kunt u deze nog steeds beschikbaar maken door het volgende te doen voordat u methoden Console aanroept:

  1. Haal het EncodingProvider object op uit de CodePagesEncodingProvider.Instance eigenschap.

  2. Geef het EncodingProvider object door aan de Encoding.RegisterProvider methode om de aanvullende coderingen beschikbaar te maken die worden ondersteund door de coderingsprovider.

De Console klasse gebruikt vervolgens automatisch de standaardsysteemcodering in plaats van UTF8, mits u de coderingsprovider hebt geregistreerd voordat u uitvoermethoden aanroept Console .

Voorbeelden

In het volgende voorbeeld ziet u hoe u gegevens leest van en schrijft naar de standaardinvoer- en uitvoerstromen. Houd er rekening mee dat deze streams kunnen worden omgeleid met behulp van de SetIn en SetOut methoden.

using System;

public class Example4
{
    public static void Main()
    {
        Console.Write("Hello ");
        Console.WriteLine("World!");
        Console.Write("Enter your name: ");
        string name = Console.ReadLine();
        Console.Write("Good day, ");
        Console.Write(name);
        Console.WriteLine("!");
    }
}
// The example displays output similar to the following:
//       Hello World!
//       Enter your name: James
//       Good day, James!
Public Class Example4
    Public Shared Sub Main()
        Console.Write("Hello ")
        Console.WriteLine("World!")
        Console.Write("Enter your name: ")
        Dim name As String = Console.ReadLine()
        Console.Write("Good day, ")
        Console.Write(name)
        Console.WriteLine("!")
    End Sub
End Class
' The example displays output similar to the following:
'        Hello World!
'        Enter your name: James
'        Good day, James!
module Example

open System

[<EntryPoint>]
let main argv =
    Console.Write("Hello ")
    Console.WriteLine("World!")
    Console.Write("Enter your name: ")
    let name = Console.ReadLine()
    Console.Write("Good day, ")
    Console.Write(name)
    Console.WriteLine("!")
    0
    
// The example displays output similar to the following:
//       Hello World!
//       Enter your name: James
//       Good day, James!