JavaScriptで文字列をUTF-8文字コードとして処理する方法
JavaScriptで文字列をUTF-8文字コードとして処理する方法のメモです。動作確認環境はWindows 10、Google Chrome 79.0.3945.130です。
- 文字列を16進数UTF-8文字コードに変換して半角スペースで区切る
- 文字列を文字毎に10進数UTF-8文字コードに変換した二次元配列を作成する
- 文字列を文字毎に16進数UTF-8文字コードに変換した二次元配列を作成する
- 文字列を文字毎に16進数UTF-8文字コードに変換して半角スペースと改行で区切る
- 備考
文字列を16進数UTF-8文字コードに変換して半角スペースで区切る
const string1 = "あいうえお" Array.from((new TextEncoder()).encode(string1), x => x.toString(16).padStart(2, '0')).join(' ') // "e3 81 82 e3 81 84 e3 81 86 e3 81 88 e3 81 8a"
文字列を文字毎に10進数UTF-8文字コードに変換した二次元配列を作成する
const encoder= new TextEncoder() const string1 = "あいうえお" Array.from(string1, s => Array.from(encoder.encode(Array.from(s)))) // [227, 129, 130], [227, 129, 132], [227, 129, 134], [227, 129, 136], [227, 129, 138]
文字列を文字毎に16進数UTF-8文字コードに変換した二次元配列を作成する
const encoder= new TextEncoder() const string1 = "あいうえお" Array.from(string1, s => Array.from(encoder.encode(Array.from(s)), code => code.toString(16))) // ["e3", "81", "82"], ["e3", "81", "84"], ["e3", "81", "86"], ["e3", "81", "88"], ["e3", "81", "8a"]
文字列を文字毎に16進数UTF-8文字コードに変換して半角スペースと改行で区切る
const encoder= new TextEncoder() const string1 = "あいうえお" Array.from(string1).map(s => Array.from(encoder.encode(Array.from(s))).map(code => code.toString(16)).padStart(2, "0").join(" ")).join("\r\n") // "e3 81 82 // e3 81 84 // e3 81 86 // e3 81 88 // e3 81 8a"
備考
この投稿ではArray.from
関数の第2引数mapFn
を使用していますが、Array.from(...).map(mapFn)
と記載しても同様の結果が得られます。
Uint8Arrayのmap関数の注意あるいはTextEncoder.encodeの戻り値の注意
Uint8Array.of(0, 1, 2).map(x => x) // Uint8Array(3) [0, 1, 2] Uint8Array.of(0, 1, 2).map(x => 0.1) // Uint8Array(3) [0, 0, 0] !? Uint8Array.of(0, 1, 2).map(x => "a") // Uint8Array(3) [0, 0, 0] !?
現在の仕様ではUint8Array.map
関数はUint8Array
型を返します。Uint8Array.map
の結果は強制的にUint8Array
の要素に変換されるため、Array.map
関数と同じ感覚で使用すると想定外の挙動が起きます。この挙動はArray.from
関数でArray
型にしてしまうことで回避できます。TextEncoder.encode
関数の戻り値(Uint8Array
型)に対してmap
関数を適用したらハマったので共有します。
Array.from関数による対処例
Array.from(Uint8Array.of(0, 1, 2)).map(x => 0.1) // [0.1, 0.1, 0.1] Array.from(Uint8Array.of(0, 1, 2)).map(x => "a") // ["a", "a", "a"]
TextEncoder.encodeにおける再現と対処
(new TextEncoder('utf-8')).encode("abc").map(ch => ch.toString(16)) // Uint8Array(3) [61, 62, 63] ※整数に変換されている。 Array.from((new TextEncoder('utf-8')).encode("abc")).map(ch => ch.toString(16)) // ["61", "62", "63"] ※文字列のまま
TextEncoder.encodeにおける再現と対処(padStart関数が無意味になる)
(new TextEncoder('utf-8')).encode("abc").map(ch => ch.toString(16).padStart(3, "0")) // Uint8Array(3) [ 61, 62, 63 ] Array.from((new TextEncoder('utf-8')).encode("abc")).map(ch => ch.toString(16).padStart(3, "0")) // Array(3) [ "061", "062", "063" ]
参考
Rで二項分布とパーセント点の垂線を描画する
として、二項分布の曲線と95%点の垂線を描画します。
x <- dbinom(0:1000, 1000, 0.5) plot(x, type="l", xlim=c(400, 600), yaxs="i", xlab="X", ylab="Prob.") x1 <- qbinom(1-0.05, 1000, 0.5) #1-0.05 = 0.95 = 95% segments(x1, 0, x1, x[x1])
C#でWin32 API TaskDialog関数を呼び出すサンプルコード
C#でTaskDialogを表示するにはWin32 APIのTaskDialog関数(comctl32.dll)を呼び出すサンプルコードです。適当なC#のWindows フォーム アプリケーション (.NET Framework) プロジェクトのForm1にボタン(Button1)を作成して、Clickイベントの名前を合わせて実行してください。
関数の呼び出し自体よりもMAKEINTRESOURCEマクロを使用したTD_WARNING_ICONの定義の方が難関だと思います。C/C++におけるintの(WORD)キャストによるビット操作はuncheckedとビット演算子またはキャストにより実施可能です。
using System; using System.Runtime.InteropServices; using System.Windows.Forms; namespace TaskDialogSample { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private static class NativeMethods { [DllImport("comctl32.dll", ExactSpelling = true, CharSet = CharSet.Unicode)] public static extern int TaskDialog( IntPtr hwndOwner, IntPtr hInstance, string pszWindowTitle, string pszMainInstruction, string pszContent, TaskDialogCommonButtonFlags dwCommonButtons, IntPtr pszIcon, out int pnButton); } // MAKEINTRESOURCEに対応した変換 // 単純にnew IntPtr(-1)等とするとWORDへのキャストが実施されずエラーとなる。 private static IntPtr TD_WARNING_ICON => new IntPtr(unchecked((ushort)-1)); private static IntPtr TD_ERROR_ICON => new IntPtr(unchecked((ushort)-2)); private static IntPtr TD_INFORMATION_ICON => new IntPtr(unchecked((ushort)-3)); private static IntPtr TD_SHIELD_ICON => new IntPtr(unchecked((ushort)-4)); /// <summary> /// TASKDIALOG_COMMON_BUTTON_FLAGS /// </summary> [Flags] public enum TaskDialogCommonButtonFlags { OKButton = 0x0001, YesButton = 0x0002, NoButton = 0x0004, CancelButton = 0x0008, RetryButton = 0x0010, CloseButton = 0x0020 } private void Button1_Click(object sender, EventArgs e) { NativeMethods.TaskDialog( Handle, IntPtr.Zero, "TaskDialogSample", "Main Instruction", "Content", TaskDialogCommonButtonFlags.OKButton, TD_SHIELD_ICON, out var button); } } }
「Windowsの標準コントロール」と「C#の標準コントロール」
本文
前回の記事で平然と(Windows 10の)「標準コントロール」「コモンコントロール」と「C#の標準コントロール」という言葉を使ってしまったのですが、冷静に振り返ればこれらの言葉遣いは正しかったのかなと。多分に想像ですが、以下がその回答に近いかなと思います。
- Windows 10ではUser32.dllとComctl32.dllがコントロールを提供する。
- Comctl32.dllが提供するコントロールはコモンコントロール(参照:InitCommonControlsEx関数)。
- User32.dllが提供するコントロールは標準コントロール(参照:ICC_STANDARD_CLASSES定数)。
- RICHEDITは別枠?
- 標準コントロールは初期化不要。
- コモンコントロールはInitCommonControlsEx関数の呼び出しが必要。
- ユーザー定義のカスタムコントロールなども存在。
- mscorlib.dllのSystem.Windows.Forms名前空間で定義された.NET Framework依存のコントロール。