tag software para pagina oficial mp3tag mega editors descargar windows delphi delphi-xe7

windows - software - tag editor download



¿Writeln es capaz de soportar Unicode? (3)

Considera este programa:

{$APPTYPE CONSOLE} begin Writeln(''АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ''); end.

La salida en mi consola que usa la fuente Consolas es:

????????Z??????????????????????????????????????

La consola de Windows es bastante capaz de soportar Unicode como lo demuestra este programa:

{$APPTYPE CONSOLE} uses Winapi.Windows; const Text = ''АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ''; var NumWritten: DWORD; begin WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), PChar(Text), Length(Text), NumWritten, nil); end.

para lo cual el resultado es:

АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ

¿ Writeln puede persuadir a Writeln para que respete Unicode, o está Writeln inutilizado?


La unidad del System declara una variable llamada AlternateWriteUnicodeStringProc que permite la personalización de cómo Writeln realiza la salida. Este programa:

{$APPTYPE CONSOLE} uses Winapi.Windows; function MyAlternateWriteUnicodeStringProc(var t: TTextRec; s: UnicodeString): Pointer; var NumberOfCharsWritten, NumOfBytesWritten: DWORD; begin Result := @t; if t.Handle = GetStdHandle(STD_OUTPUT_HANDLE) then WriteConsole(t.Handle, Pointer(s), Length(s), NumberOfCharsWritten, nil) else WriteFile(t.Handle, Pointer(s)^, Length(s)*SizeOf(WideChar), NumOfBytesWritten, nil); end; var UserFile: Text; begin AlternateWriteUnicodeStringProc := MyAlternateWriteUnicodeStringProc; Writeln(''АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ''); Readln; end.

produce esta salida:

АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ

Soy escéptico sobre cómo he implementado MyAlternateWriteUnicodeStringProc y cómo interactuaría con Pascal I / O clásico. Sin embargo, parece comportarse como se desea para la salida a la consola.

La documentación de AlternateWriteUnicodeStringProc dice actualmente, espere, ...

Actualmente Embarcadero Technologies no tiene información adicional. ¡Por favor ayúdenos a documentar este tema usando la página de discusión!


Simplemente configure la página de códigos de salida de la consola a través de la rutina SetConsoleOutputCP() con la página de códigos cp_UTF8 .

program Project1; {$APPTYPE CONSOLE} uses System.SysUtils,Windows; Const Text = ''АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ''; VAR NumWritten: DWORD; begin ReadLn; // Make sure Consolas font is selected try WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), PChar(Text), Length(Text), NumWritten, nil); SetConsoleOutputCP(CP_UTF8); WriteLn; WriteLn(''АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ''); except on E: Exception do Writeln(E.ClassName, '': '', E.Message); end; ReadLn; end.

Productos:

АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ

WriteLn() traduce cadenas Unicode UTF16 a la página de códigos de salida seleccionada (cp_UTF8) internamente.

Actualizar:

Lo anterior funciona en Delphi-XE2 y superior. En Delphi-XE necesita una conversión explícita a UTF-8 para que funcione correctamente.

WriteLn(UTF8String(''АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ''));

Apéndice:

Si se realiza una salida a la consola en otra página de códigos antes de llamar a SetConsoleOutputCP(cp_UTF8) , el sistema operativo no enviará correctamente el texto en utf-8 . Esto puede solucionarse cerrando / volviendo a abrir el controlador de stdout.

Otra opción es declarar un nuevo controlador de salida de texto para utf-8 .

var toutUTF8: TextFile; ... SetConsoleOutputCP(CP_UTF8); AssignFile(toutUTF8,'''',cp_UTF8); // Works in XE2 and above Rewrite(toutUTF8); WriteLn(toutUTF8,''АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ'');


WriteConsoleW parece ser una función bastante mágica.

procedure WriteLnToConsoleUsingWriteFile(CP: Cardinal; AEncoding: TEncoding; const S: string); var Buffer: TBytes; NumWritten: Cardinal; begin Buffer := AEncoding.GetBytes(S); // This is a side effect and should be avoided ... SetConsoleOutputCP(CP); WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), Buffer[0], Length(Buffer), NumWritten, nil); WriteLn; end; procedure WriteLnToConsoleUsingWriteConsole(const S: string); var NumWritten: Cardinal; begin WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), PChar(S), Length(S), NumWritten, nil); WriteLn; end; const Text = ''АБВГДЕЖЅZЗИІКЛМНОПҀРСТȢѸФХѾЦЧШЩЪЫЬѢѤЮѦѪѨѬѠѺѮѰѲѴ''; begin ReadLn; // Make sure Consolas font is selected // Works, but changing the console CP is neccessary WriteLnToConsoleUsingWriteFile(CP_UTF8, TEncoding.UTF8, Text); // Doesn''t work WriteLnToConsoleUsingWriteFile(1200, TEncoding.Unicode, Text); // This does and doesn''t need the CP anymore WriteLnToConsoleUsingWriteConsole(Text); ReadLn; end.

Entonces en resumen:

WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), ...) compatible con UTF-16.

WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), ...) no es compatible con UTF-16.

Mi suposición sería que para soportar diferentes codificaciones ANSI, la clásica Pascal I / O usa la llamada WriteFile .

También tenga en cuenta que cuando se usa en un archivo en lugar de en la consola, también debe funcionar:

salida de archivo de texto unicode difiere entre XE2 y Delphi 2009?

Eso significa que el uso ciego de WriteConsole rompe la redirección de salida. Si usa WriteConsole , debe recurrir a WriteFile siguiente manera:

var NumWritten: Cardinal; Bytes: TBytes; begin if not WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), PChar(S), Length(S), NumWritten, nil) then begin Bytes := TEncoding.UTF8.GetBytes(S); WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), Bytes[0], Length(Bytes), NumWritten, nil); end; WriteLn; end;

Tenga en cuenta que la redirección de salida con cualquier codificación funciona bien en cmd.exe . Simplemente escribe la secuencia de salida al archivo sin cambios.

Sin embargo, PowerShell espera que la salida ANSI o el preámbulo correcto (/ BOM) se tengan que incluir al comienzo de la salida (¡o el archivo se malencinará!). Además, PowerShell siempre convertirá la salida en UTF-16 con preámbulo.

MSDN recomienda utilizar GetConsoleMode para averiguar si el identificador estándar es un identificador de consola, también se menciona el BOM:

WriteConsole falla si se utiliza con un identificador estándar que se redirige a un archivo. Si una aplicación procesa resultados multilingües que pueden redirigirse, determine si el manejador de salida es un manejador de consola (un método es llamar a la función GetConsoleMode y verificar si tiene éxito). Si el asa es un asa de consola, llame a WriteConsole. Si el identificador no es un controlador de consola, la salida se redirige y debe llamar a WriteFile para realizar la E / S. Asegúrese de anteponer un archivo de texto sin formato Unicode con una marca de orden de bytes. Para obtener más información, vea Usar marcas de orden de bytes.