インストールの許可がないためにPHPなど他言語でサクッとスクリプトを書くこともできないがエクセルで設計書を書くことを強いられるような過酷な状況の時のためのメモ書き
C:\result.txtに一行ずつフォーマットされた文字列が出力される。
VSCodeのPowerShell拡張から実行したらテンプレ部分が文字化けしてしまったけど、PowerShellのターミナルから実行したら文字化けしなかったので多分大丈夫。
インストールの許可がないためにPHPなど他言語でサクッとスクリプトを書くこともできないがエクセルで設計書を書くことを強いられるような過酷な状況の時のためのメモ書き
C:\result.txtに一行ずつフォーマットされた文字列が出力される。
VSCodeのPowerShell拡張から実行したらテンプレ部分が文字化けしてしまったけど、PowerShellのターミナルから実行したら文字化けしなかったので多分大丈夫。
aタグをコンソールから押す方法についてやっと理解できたのでメモ。
こんなHTML内のaタグをJavaScriptからクリックしたい。
element.dispatchEvent()を使ってみる。dispatchEventは引数にEventオブジェクトを取って、要素に任意のイベントを割り当てることができる。
上記の場合は、Eventオブジェクトのコンストラクタに'click'を指定して、aタグにクリックイベントを発生させようとしている。
が、画面遷移は発生しない。
click()メソッドを実行して、クリック動作をシミュレーションすることができ、aタグによる遷移を発生させることができる。
aタグのhref属性を削除したうえで、イベントオブジェクトを確認してみる。
Eventオブジェクトではなく、PointerEventオブジェクトが割り当てられている模様。
PointerEvent
インターフェイスは、接触点の形状、イベントを生成した機器の種類、接触面に加えられた圧力の量など、ポインターによって生成された DOM イベントの状態を表します。
-----mdc web docs
クラス図
PointerEventはEventオブジェクトをプロトタイプとして継承しているので(多分)、Eventオブジェクトで指定できる'click'イベントも指定可能。
PointerEventによる発火であればログ出力して画面遷移。
🥰🥰🥰
最近部屋の片づけをしており、大量の本やCDを整理しています。
折角だから捨てる前に全部CDを取り込んでおこう…ということでアルバムを一つ一つasunderから取り込んでいるのですが、面倒な課題にぶつかってしまいました。
1. 曲・アルバム・作曲者の表記揺れが多すぎる問題
昔聞いていた曲には19世紀の古典的な曲が多く、再演・再奏された録音を収録している場合、アルバムが違うだけで「同じ曲なのにタイトルが違う」ということが頻発します。
J.Strauss Ⅱ Wo die Zitronen blühen
→ヨハンシュトラウス2世 シトロンの花咲くところ
→ヨハン・シュトラウスⅡ世 レモンの花咲くところ
→ヨハン・シュトラウス2世 シトロンの花咲く国
曲名が違うだけならそこまで神経質にならずともよいですが、作曲者名に揺れがあると「その作曲者の曲だけ聞きたい」という場合不便を極めます。
ということで、表記揺れを一括で直せるように楽曲ファイルのメタデータを編集できるようにしたいと思います。類似のMP3タグ編集ソフトで同等のことはできるのかもしれませんが、調べていません。どうせ勉強だし。
2. バイナリを読む
とりあえず、AACとかその他の音楽ファイルの形式は考えず、MP3のタグ(ID3V2)を編集することだけ考えます。
タグを編集する場合、バイナリ(0と1で構成された、テキスト以外のデータ)の読み書きを直接行うことになります。
ID3V2タグにはヘッダーも存在しますが、ここでは最初にタグの本体の中身を見ることにします。
バイナリエディタの左側のパネルの各セルには、1バイトの情報が表示されており、右側のパネルにはバイトに対応する文字がエンコードされて表示されています。
言わでものことかもしれませんが、1バイトはここでは16進表記されているので、'54'なら16 * 5 * 4で10進数の84となります。16進数をリテラル表記する際の'0x'という接頭辞をつけて表記するなら、0x54となります。
さて、上掲の画像の中で、エンコードされた文字列を見ていると、「TSSE」や「TRCK」、「TPE1」という大文字の文字列が目につきます。
この文字列からID3V2タグの「フレーム」と呼ばれる、楽曲のメタデータのより具体的な情報を格納する部分が開始します。「TSSE」などは各フレームの名称で、「TSSE」はエンコード設定に関する情報、「TRCK」はトラック番号、「TPE1」は主なるアーティストを指します。
今回は、「TRCK」について見ていきたいと思います。上掲の画像のうち、赤枠で囲った部分がフレーム名の「TRCK」を表す部分。
水色の枠で囲った部分が、フレームの本体サイズを表す部分で、今回は「00 00 00 05」なので、5バイトであることがわかります。本来はSyncsafe Integerという表記法に対応したサイズの計算が必要ですが、今回は割愛。
緑色の枠で囲った部分が、フラグを表す部分ですが、通常は使用されません。
そして、最後に、オレンジの枠で囲った部分が、フレームの本体で、ここにトラック番号が格納されています。サイズは先ほどフレームの本体サイズを表記していた箇所に従って5バイトとなります。
さて、フレームのサイズに従ってトラック番号を表す箇所を見てみると、「01 FF FE 31 00」と記されています。
31 = 0x31はUnicode(文字コードの標準規格)では'1'を指します。バイナリエディタで見ていた曲はアルバムの1曲目なので、正しそうですね。
ただ、0x31の前には、0x01,0xFF,0xFEというバイト列が並んでいます。0x01や0xFFや0xFEには対応する文字が無いようですが…。
3. 0x01,0xFFFEとは
Unicodeエンコーディング(UTF-16またはUTF-8)が使用されているデータ・ファイルには、ファイルの最初の数バイトにバイト順序マーク(BOM)が含まれている場合があります。キャラクタ・セットUTF-16が使用されているデータ・ファイルでは、ファイルの最初の2バイトの値{0xFE,0xFF}は、ファイルがビッグ・エンディアンのデータを含んでいることを示すBOMです。{0xFF,0xFE}という値は、ファイルにリトル・エンディアンのデータが含まれていることを示すBOMです。
https://docs.oracle.com/cd/E57425_01/121/SUTIL/GUID-CFEED713-D459-42F4-A777-7AAA654451AC.html
0xFF,0xFEが使用されている場合、続くデータはリトルエンディアン(=多バイトをメモリに格納する際の方式1つ。リトルエンディアンの場合下位バイトを先に格納する)ことを明示しています。このような記号をBOM(Byte Order Mark)と呼びます。
(ただし、UTF-8のBOMは0xEFBBBFで、これはUTF-8で書き込まれていることを明示するために使われるのであって、今見ているファイルがUTF-8で書き込まれているはずなのに0xFFEが書き込まれているのはなぜなのかはよくわかりません。)
せんずるに、0XFFFEは文字コードとしては定義されない値であり、今回はUTF-8のファイルとしてバイナリデータを扱うので、楽曲に関するメタデータとして考慮する必要はないということです。
ただし、読み込んだバイト列をエンコードする際に弾きだす必要はありますね。
0x01については、unicodeの制御文字のようで、意味としては'START OF HEADING'=ヘッダ開始を表す符号にすぎないようで、これも文字列として扱わないように弾く必要あり。そのほかunicodeには0x000~0x001Fまでの制御文字があるようです。
書くことが思いつかず前の記事から2週間以上空いてしまいました。
前々回まで、StreamAPIの練習として適当に作成していた図書館の貸し出しをモデルにしたプロジェクトを書いていましたが、今回はStreamAPIとは別方向の改修を行いたいと思います。
1.前回までのコード
面倒なのでDBは使わない方針でしたが、そのため、書籍一覧を保持するBookListクラスのオブジェクトは以上のように初期化されていました。
上記のコードでbookListが保持しているBookクラスのオブジェクトには、貸出履歴や貸出回数を管理するメンバ変数が存在しますが、当然のことながら、JVM(Java Virtual Machine)が終了した時点でそれらの変数は解放されてしまいます。
そこで今回は、DBを使わずにXMLファイルを読み込むことでBookListの初期化を行いたいと思います。
XMLファイルを読み込む練習がしたいだけなので、DB使えよ…みたいな指摘はなしで。
2.XMLファイルとは
.xmlファイルとは、ファイル名の拡張子(末尾部分)が「.xml」のファイルで、XML(Extensible Markup Language)で記述されたテキストファイルのこと。ソフトウェアの設定ファイルなどによく見られる。
IT用語辞典 e-Words(https://e-words.jp/w/.xml%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB.html)
xmlファイルでは、自分で任意のタグを用意することでデータを定義することができます。
例えば今回改修範囲であるBookクラス(書籍名・著者・ページ数などを保持するクラス)をXMLで表現すると以下のようになります。
3.JAXBの利用
さて、XML形式で外出しした書籍一覧情報ですが、これを実際のコード内で活用するには、
という手順を踏む必要があります。
こういった場合に使用できるAPIに、JAXB(Java Architecture XML Binding)があります。
JAXB(Java Architecture XML Binding)は、[…]XMLファイルを読み込むというよりも、「XMLファイルとJavaのオブジェクトを結び付ける」動作をします。JAXBを利用することで、XMLとJavaオブジェクトを相互変換できます。
Java本格入門p.262
JAXBはかつてはJavaの標準ライブラリ(Eclipseのパッケージエクスプローラ内のJRE システムライブラリーに格納されているパッケージ)であったが、現在は削除されているため、自力で導入する必要があります。導入については割愛。
【BookList.java】
JAXBクラスのunmarshalメソッド(XMLからJavaオブジェクトへの変換を行うメソッド)を使用しています。引数にInputStreamを渡していますが、InputStreamの代わりにReaderクラスオブジェクトが指定されているオーバーロードもあるので、BufferedReaderでも大丈夫です。
第二引数にはBooksクラスのクラスリテラル(そのクラスを表すClassクラスのオブジェクト)が指定されます。
では、肝心のBooksクラスはどうなっているかというと、
【Books.java】
@XmlRootElementは、オブジェクトをXML要素として表現するための注釈で、XMLのルートタグ(最上位の要素)と、ツリー構造で表現されるJavaのオブジェクトの、最上位のクラスを結び付けます。ここでは、Bookオブジェクトを格納するArrayListではなく、クラスに注釈を付与している点に注意しておきます。
@XmlElementも同様に、XML要素とオブジェクトを結び付ける注釈です。
このように、注釈型を用いるだけで、XML要素がJavaオブジェクトにマッピング(関連づけ・割り当て)されます。
4.実際に動かす
先掲のBookList.java内のbookListをwatch式で見てみます。
個人的には、@XmlRootElement注釈はBooksクラスに付与したのに、Booksクラスのメンバ変数であるbookListにバインドされているのが親切なような不気味なような…。
ともかく、XMLの各要素がBook型のリストに格納され、各BookオブジェクトはXMLタグで囲われた値を保持していることがわかります。ただし、
<book>タグの属性であるidは、Bookクラスのメンバ変数であるidにはバインドされていません。
タグ内の属性をバインドするには、@XmlAttribute注釈型を用います。
getterに@XmlAttributeを付与していることに注意します。メンバ変数に直接付与してもバインドされません。注意しましょう。
きちんとidもバインドされています。もっとも、XMLで"0001"だったidはint型の1として扱われ、0埋めではなくなっていますが…。
パス…ファイルシステムのリソースの在処を示す。 標準のDOSパスの場合、パスは3つの部分から構成される。
https://learn.microsoft.com/ja-jp/dotnet/standard/io/file-path-formats
URI…
JavaのURIクラスには、上で説明したスキームやクエリを取得するメソッドのほか、URIオブジェクトを生成するcreateメソッドが用意されています。
public static URI create(String str)
パラメータには、URIとして分析可能な文字列を渡します。
2.1. エラーになる表現もある
URIクラスのcreateメソッド※を利用して、URIクラスのオブジェクトを作成し、さらに、URIクラスのオブジェクトを利用してPathsクラスのgetメソッドからPathを指定します。
最後に、MessageFormatクラスのformatメソッド※でURIクラスオブジェクトとPathクラスオブジェクトの文字列表現を出力。
適当に4つ並べてみなしたが、この中で正しくPathクラスオブジェクトを取得できるのは1つだけです。
※MessageFormat.formatメソッド…第一引数のpatternに変数を埋め込む書式パターン、第二引数以降に埋め込む変数を指定して、メッセージの指定部分のみを変更する。
2.2. 解答編
【失敗例1】
ドライブの"C"をスキームとして分析してしまうためエラー。
【失敗例2】
スキーム(https:など)を指定しない相対パスで生成したURIクラスオブジェクトを引数にしてgetを呼び出すとillegalArgumentExceptionがスローされます。
なお、
のように、URIクラスオブジェクトを利用せず、Pathsクラスのgetメソッドに相対パスを文字列で指定した場合は、正しくリソースのパスを指定することができます。
相対パスで指定した場合、ルートはプロジェクトのフォルダになります(上掲の例だとJavaStudy)。
【失敗例3】
windowsのディレクトリ区切り文字であるバックスラッシュ(/)を利用しているパターン。
"Illegal character in opaque part at index 5"
=>"opaque"はURIのデータ格納部分。バックスラッシュで区切りを表現してはいけない。
【成功例】
パスはwindowsの区切り文字であるバックスラッシュで表現されていることがわかります。また、URIのスキーム部はパスとしては表現されないこともわかります。
なお、Ubuntuで実行した場合、
パスの区切り文字はスラッシュとなります。