Mark Down to PDF ~Pandocを使ってPDFを生成~(失敗)

イントロダクション

Atomを使用してMDファイルを作成しているのですが、インストールしたパッケージの動きがイマイチ、PDFではなくHTMLが生成されるので、別な方法を使うことにしました。

理想としては、コマンドで複数ファイルをいっぺんにPDFに変換できるとよいです。

PANDOCを使う

PANDOCというツールがあるようです。詳細はこちらのページが本家のサイトです。

このページにはWindows用のインストーラーがあったのでインストールはクリックで終りました。

コマンドプロンプトで確認すると下のように、コマンドで実行することができます。

使い方は、こちらのページにあるように、下のようなコマンドで実行できるようです。

HTML fragment:

pandoc MANUAL.txt -o example1.html
Standalone HTML file:

pandoc -s MANUAL.txt -o example2.html
HTML with table of contents, CSS, and custom footer:

pandoc -s --toc -c pandoc.css -A footer.html MANUAL.txt -o example3.html
LaTeX:

pandoc -s MANUAL.txt -o example4.tex
From LaTeX to markdown:

pandoc -s example4.tex -o example5.text
reStructuredText:

pandoc -s -t rst --toc MANUAL.txt -o example6.text
Rich text format (RTF):

pandoc -s MANUAL.txt -o example7.rtf
Beamer slide show:

pandoc -t beamer SLIDES -o example8.pdf
DocBook XML:

pandoc -s -t docbook MANUAL.txt -o example9.db
Man page:

pandoc -s -t man pandoc.1.md -o example10.1
ConTeXt:

pandoc -s -t context MANUAL.txt -o example11.tex
Converting a web page to markdown:

pandoc -s -r html http://www.gnu.org/software/make/ -o example12.text
From markdown to PDF:

pandoc MANUAL.txt --pdf-engine=xelatex -o example13.pdf

そして、今回注目したいのが、以下の部分のコマンドです。

From markdown to PDF:

pandoc MANUAL.txt --pdf-engine=xelatex -o example13.pdf

しかし、「.txt」から変換しているようです。細かい部分はさておきにしてとりあえずは動かしてみます。

xelatex not found. Please select a different --pdf-engine or install xelatex

上のようなメッセージが出ました。こちらのサイトを参考にすると変換するエンジンに「xelatex」を使用するということがわかりました。

では、インストール方法は?

大まかにこちらのサイトにある情報が「xelatex」のインストールに関連する情報であろうと思います。
抽象的な言い方なのは、英語だからです。しかし、ばっちりとインストールについての記載がありました。

そして、以下のリンクからかくOSでのインストールができるようです。

結局はインストールファイルを落とすようです。

そして、上にも書きましたが、下のコマンドを実行します。

pandoc 変換するファイル --pdf-engine=xelatex -o example13.pdf

実際に実行したコマンドは以下のものです。

pandoc "0-1 教材の概要.md" --pdf-engine=xelatex -o example13.pdf

しかし、なかなかファイルが生成されず、おかしいと思っていたら下のように不足するものをインストールするダイアログが表示されました。

これが、何個か続いた後に。。。変換処理が走ったのですが、ワーニングが出ました。

どうやら下のようなコマンドでやるのが良いみたいです。(参考ページ)

pandoc 変換するファイル.md -o 変換後.pdf --pdf-engine=xelatex -V documentclass=bxjsarticle -V classoption=pandoc

そして、次には下のようなワーニングが出ました。

Missing character: There is no ① (U+2460) in font [lmroman10-regular]:mapping=tex-text;!

どうやら、フォントの設定を行う必要があるようです。参照先はこちらです。

XELATEXを使う

つまるところ、こちらのファイルを作成して下のようなコマンドで実行すれば、必要なファイルをインストールしてくれるようです。

xelatex test

上のコマンドは、以下の手順で実行しました。

  1. こちらのファイルの内容を書きだした「test.tex」というファイルを作成
  2. このファイルのあるディレクトリに移動
  3. xelatex testとコマンドを実行

すると下のようなファイルをダウンロードしてくれます。

======================================================================

(C:\Program Files\MiKTeX\tex/latex/everysel\everysel.sty
(C:\Program Files\MiKTeX\tex/latex/everysel\everysel-2011-10-28.sty))
(C:\Program Files\MiKTeX\tex/latex/ctex/config\ctexopts.cfg)
(C:\Program Files\MiKTeX\tex/latex/ctex/engine\ctex-engine-xetex.def
(C:\Program Files\MiKTeX\tex/xelatex/xecjk\xeCJK.sty
(C:\Program Files\MiKTeX\tex/latex/l3packages/xtemplate\xtemplate.sty)
(C:\Program Files\MiKTeX\tex/latex/fontspec\fontspec.sty
(C:\Program Files\MiKTeX\tex/latex/fontspec\fontspec-xetex.sty
(C:\Program Files\MiKTeX\tex/latex/base\fontenc.sty)
(C:\Program Files\MiKTeX\tex/latex/fontspec\fontspec.cfg)))
(C:\Program Files\MiKTeX\tex/xelatex/xecjk\xeCJK.cfg)))

エラーが出る

UTF-8 decoding error in - at byte offset 87 (8a).

これはコマンドプロンプトの文字コードをUTF-8に変換することで解決:

chcp 65001

参考になるサイトとしてはこのサイトがエラーに対応する方法がありました。

PDFをまとめる

下のようなコマンドで、1ファイルにまとめることができるようです。

dir /b /s *.md | pandoc -f markdown -o output.pdf --pdf-engine=lualatex

dir /b /s *.md

このコマンドで、MDファイルの一覧を表示して、

pandoc -f markdown -o output.pdf --pdf-engine=lualatex

このコマンドで、PDFを出力します。。。しかし、エラーが出て解決できなくなりました。

最終的に

Windowsの設定(フォントの設定)が足りないらしく。。。うまくいきませんでした。

Windows コマンドプロンプト 事始め

コマンドプロンプト

コマンドプロンプトを使用してやるとGUIでは面倒な操作を簡単にできます。
例えば、フォルダをたくさん作成するとかファイルをいろんな場所に移動するなど。。。

しかし、コマンドプロンプトの画面が何を意味しているのか?わからないことには使うこともできません。

ちょっと使えるようになると、とても「オレってすげぇ~」と感じるかもしれません(笑)。

コマンドプロンプトの画面

初期表示したときは、ユーザーディレクトリが表示されます。
例えば、Windowsのユーザーが「Takunoji」の場合は、下のように表示されます。

C:\User\Takunoji

そして、Cドライブをネットにさらすのはよろしくないので、画像は、別のディレクトリになっていますが、イメージとしては下のようなものです。※Usersまでは共通なので。。。

そして、上の画像にある「C:\Users」というのがカレントディレクトリになります。

CDコマンドで移動することができます、そして移動したときには、カレントディレクトリがその移動先に代わります。

細かい部分は動画にて解説しました。

ますは、CDコマンドと、DIRコマンドを覚えましょう。

単純なものですので、フォルダ表示しながら解説しました。カレントディレクトリを示すC:\などは「パス」といいファイル、もしくはディレクトリの場所を示すものです。

でわでわ。。。

android Tesseract エラー: シンボルを見つけられません

エラー: シンボルを見つけられません

シンボル: クラス Size
場所: クラス com.googlecode.leptonica.android.Pix

エラー: パッケージandroid.support.annotationは存在しません

上のようなエラーが出ました。同様に下のようなエラーも出ました。

同様に、以下のクラスも見つかりませんでした。

  • com.googlecode.leptonica.android.Binarize
  • com.googlecode.leptonica.android.Box
  • com.googlecode.leptonica.android.Boxa
  • com.googlecode.leptonica.android.Constants
  • com.googlecode.leptonica.android.Edge
  • com.googlecode.leptonica.android.JpegIO
  • com.googlecode.leptonica.android.MorphApp
  • com.googlecode.leptonica.android.Rotate
  • com.googlecode.tesseract.android.TessBaseAPI.PageSegMode

解決策

プロジェクトのbuild.gradleに以下のコードを追加する

implementation 'androidx.appcompat:appcompat:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

そして、足りないパッケージの追加は下の画面よりできるはず。。。

Android Studio Tesseractの設定とエラー compileSdkVersion is not specified.

調査するときのポイント

実際に自分が調べていくときに「使えるな!」と思った方法です。

  1. エラーメッセージをコピって検索する
  2. エラーメッセージを翻訳して日本語にする

色々なサイト、ブログ記事を追いかけるように、みて、試して問題解決に向けて調べていきます。

しかし、途中で「根本的な仕組みを理解したほうが早い」場合もあるので、頭の片隅にそれを置いておくと良いかもしれません。

compileSdkVersion is not specified.

上記のようなエラーメッセージが出て、ビルドができない状態になりました。

調べてみるとこちらのページに下のような記述がありました。

プロジェクト下の build.gradle に以下を記載していますか?

allprojects {
repositories {
mavenLocal()
jcenter()
maven {
url "$rootDir/../node_modules/react-native/android"
}
google()
}
}

これは、プロジェクトのbuild.gradleを修正すると言うことを意味しているので下の図の「AndroidOpenCV」と書かれているものを修正しました。

最終的に下のようになりました。

allprojects {
    repositories {
        google()
        jcenter()
        maven {
            url 'https://maven.google.com/'
            name 'Google'
        }
    }
}

Could not find method maven() for arguments

次に出力されたエラーメッセージは上のものです。

mavenのホームディレクトリ(インストールした場所)を指定しなくてはいけないけど、全く違う場所を指定しているので出力されたエラーです。

Mavenプラグインを使用

参考サイトはこちらのAndroidドキュメントです。

しかし、これは必要ないと判断しました。

maven {
    url 'https://maven.google.com/'
    name 'Google'
}

そして、初めのエラー対応を考えます。

ふと気がつく

「compileSdkVersion is not specified.」このメッセージは日本語にすると「compileSdkVersionが指定されていません。」になります。

ここを中心に調べていくとGradleのページに着きました。
しかし、有益な情報は見つからず。。。

プロジェクトの設定を見てみる

ヘッダーメニューからFile -> Project Structureを選択

Gradleのバージョンを6.5に設定しました。

Could not find com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2.

次に上のエラーが出ました。
こちらのページには次のような追記をしてください。とあったのでそのようにしました。

buildscript {
  repositories {
    maven {
      url "https://plugins.gradle.org/m2/"
    }
  }
  dependencies {
    classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5"
  }
}

apply plugin: "com.jfrog.bintray"

Could not find org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.32.

さらに次のエラーが出ました。

ERROR: Could not find org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.32.
Searched in the following locations:
  - https://dl.google.com/dl/android/maven2/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.4.32/kotlin-stdlib-jdk8-1.4.32.pom
If the artifact you are trying to retrieve can be found in the repository but without metadata in 'Maven POM' format, you need to adjust the 'metadataSources { ... }' of the repository declaration.
Required by:
    project : > com.android.tools.build:gradle:7.0.0-alpha14

下の部分に注目

adjust the 'metadataSources { ... }' of the repository declaration.

次のように、プロジェクトのbuild.gradleを修正

buildscript {
    repositories {
        google()
        jcenter()
    }
    ・
    ・
    ・

下のようなエラーが出たので、「Fix Gradle wrapper and re-import project」をクリック

ダウンロードが始まり、「Could not find 〜」と言うようなエラーが出ます、対象になる場所を削除・コメントアウトしました。
<プロジェクトのbuild.gradle>

//apply plugin: 'com.github.dcendents.android-maven'
//apply plugin: 'com.jfrog.bintray'

そして、次の部分もコメントアウトしました。プル下フォルダのbuild.gradleです。

tess/tess-two/build.gradle

//install {
//    repositories.mavenInstaller {
//        pom.project {
//            name = 'tess-two'
//
//            packaging = 'aar'
//            groupId = 'com.rmtheis'
//            artifactId = 'tess-two'
//
//            developers {
//                developer {
//                    id = 'rmtheis'
//                    name = 'Robert Theis'
//                    email = 'robert.m.theis@gmail.com'
//                }
//            }
//            licenses {
//                license {
//                    name = 'The Apache Software License, Version 2.0'
//                    url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
//                    distribution = 'repo'
//                }
//            }
//            scm {
//                url 'https://github.com/rmtheis/tess-two'
//            }
//        }
//    }
//}
//
//bintray {
//    user = properties.getProperty("bintray.user")
//    key = properties.getProperty("bintray.apikey")
//    configurations = ['archives']
//    pkg {
//        repo = 'maven'
//        name = 'tess-two'
//        userOrg = user
//        publish = true
//    }
//}

Gradle DSL method not found: 'implementation()'

次のエラーです。Android Studioに下のようなエラーがあったので、「Open Gradle wrapper file」をクリックします。

すると、gradle.propertiesファイルが開くので、新しいものを設定します。gradleの新しいバージョンです。

distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-rc-1-all.zip

ここまできたらNDKの設定

ヘッダーメニューのTools -> SDK Managerをクリックします。
そして、「SDK Tools」タブを選択します。

そして、[NDK (Side by side)] と [CMake] のチェックボックスをオン
参考ページの内容は以下の通りです。

  1. プロジェクトを開いて、[Tools] > [SDK Manager] をクリックします。
  2. [SDK Tools] タブをクリックします。
  3. [NDK (Side by side)] と [CMake] のチェックボックスをオンにします。

Unable to find method 'org.gradle.api.artifacts.result.ComponentSelectionReason.getDescription()

これは、再起動したら通常通りにビルドが走り、同じエラーが出ました。

そして、Tesseract

こちらのページにある手順を実行します。

export ANDROID_HOME=/path/to/your/android-sdk
git clone git://github.com/rmtheis/tess-two tess
cd tess
./gradlew assemble

まとめると、TesseractをGitからプルしてコンパイルするということです。

このコマンドを実行するのに手間取ったのが、「path/to/your」の部分です。あらかじめNDKのインストール先を理解している必要があります。
NDKのインストール先

android-sdkのインストール先/ndk/ビルド番号?/

実際に自分の場合は下のようにコマンドを叩きました。

~/Android/sdk/ndk/22.1.7171670/ndk-build

結構な時間がかかります。

コンパイル終了後

アプリケーションのbuild.gradleにGradleのデーモン(裏側で動くプロセス)を終了するためにAndroid Studioを再起動します。

あと、Android Studioのアップグレードも行いました。

次のエラー

2つあります。それは、下のような形で出力されたエラーですので、メッセージも複数あります。

This version of the Android Support plugin for IntelliJ IDEA (or Android Studio) cannot open this project, please retry with version 2020.3.1 or newer.
Please remove usages of `jcenter()` Maven repository from your build scripts and migrate your build to other Maven repositories.
This repository is deprecated and it will be shut down in the future.
See http://developer.android.com/r/tools/jcenter-end-of-service for more information.
Currently detected usages in: root project 'AndroidOpenCV', project ':app', project ':eyes-two', ...

下の方のエラーを先に対応しました。プロジェクトのbuild.gradleを修正、しかしこれは意味がありませんでした。

    repositories {
        google()
        //jcenter()
    }

エラーが変わりました。

tried to access method sun.security.util.ECUtil.getECParameters(Ljava/security/Provider;)Ljava/security/AlgorithmParameters; from class sun.security.ec.ECKeyPairGenerator

これには、gradle.propertiesに以下のものを追加することで解決できそうです。がダメでした。。。

org.gradle.java.home=JDKへのパス

次の方法を試します。参考にしたサイトはこちらです。

そしたら次のエラーになりました。

Could not get unknown property 'Os' for task

tess-twoのbuild.gradleの以下の行です

def ndkBuildExt = Os.isFamily(Os.FAMILY_WINDOWS) ? ".cmd" : ""

結局のところ

GUIでは原因がわからなくなってきたので、コマンド実行に切り替えることにしいました。

実行するコマンドは「./gradlew clean」です。

しかし。。。

解決には至りませんでした。。。

諦める

考え方を変えることにしました。もともとOpenCVを動かしていたプロジェクトにTesseractを追加する形での設定を行なっていましたが、諦めて、TesseractプロジェクトにOpenCVを追加する形に変更します

つまりは、追加した部分を削除します。そして、新たにTeserractプロジェクトを作成する方向でやり直すことにします。

ビルドを動くようにする

build.gradle(プロジェクト用)を修正して下のようにします。Tesseractを依存関係から外します。
さらに、buildバージョンも修正して4.1.3にします。

buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.3'
//        classpath 'com.android.tools.build:gradle:7.0.0-alpha14'
//        classpath 'com.android.tools.build:gradle:1.1.2'

        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2'
        //classpath 'com.github.dcendents:android-maven-plugin:1.2'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        maven {
            url 'https://maven.google.com/'
            name 'Google'
        }
    }
}

ext {
    // The following are only a few examples of the types of properties you can define.
    compileSdkVersion = 30
    // You can also create properties to specify versions for dependencies.
    // Having consistent versions between modules can avoid conflicts with behavior.
    supportLibVersion = "30.0.2"
}

ここまできて、依存関係が解決しないエラーが起きました。なのでclasspathを追加して、repositoryも追加しました。

buildscript {
    repositories {
        google()
        maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.3'
        classpath 'com.android.tools.build:aaptcompiler:4.1.3'
        classpath 'com.android.tools.lint:lint-gradle-api:27.1.3'
        classpath 'com.android.tools.build:gradle-api:4.1.3'
        classpath 'com.android.tools:common:27.1.3'
        classpath 'com.android.tools.analytics-library:tracker:27.1.3'
        classpath 'com.android.tools.analytics-library:shared:27.1.3'
        classpath 'com.android.tools:repository:27.1.3'
        classpath 'com.android.tools.build.jetifier:jetifier-core:1.0.0-beta09'

        classpath 'com.android.tools.build:builder:4.1.3'
        classpath 'com.android.tools.build:bundletool:0.14.0'
        classpath 'androidx.databinding:databinding-compiler-common:4.1.3'
        classpath 'com.android.tools.analytics-library:crash:27.1.3'
        classpath 'com.android.tools:sdk-common:27.1.3'
        classpath 'com.android.tools.build:apkzlib:4.1.3'
        classpath 'com.android.tools:sdklib:27.1.3'
        classpath 'com.android.tools.layoutlib:layoutlib-api:27.1.3'
        classpath 'com.android.tools.build.jetifier:jetifier-processor:1.0.0-beta09'
        classpath 'org.ow2.asm:asm-commons:7.0'
        classpath 'org.jdom:jdom2:2.0.6'
        classpath 'com.android.tools:repository:27.1.3'
        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2'
        //classpath 'com.github.dcendents:android-maven-plugin:1.2'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

compileSdkVersion is not specified. Please add it to build.gradle

こんなエラーも出ました。
そして、調べるとandroid{}を追加すればOKと言うところにたどり着き以下のようなbuild.gradleになりました。

// Top-level build file where you can add configuration options common to all sub-projects/modules.

apply plugin: 'com.android.application'

buildscript {
    repositories {
        google()
        maven { url 'https://maven.aliyun.com/nexus/content/groups/public' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.3'
        classpath 'com.android.tools.build:aaptcompiler:4.1.3'
        classpath 'com.android.tools.lint:lint-gradle-api:27.1.3'
        classpath 'com.android.tools.build:gradle-api:4.1.3'
        classpath 'com.android.tools:common:27.1.3'
        classpath 'com.android.tools.analytics-library:tracker:27.1.3'
        classpath 'com.android.tools.analytics-library:shared:27.1.3'
        classpath 'com.android.tools:repository:27.1.3'
        classpath 'com.android.tools.build.jetifier:jetifier-core:1.0.0-beta09'

        classpath 'com.android.tools.build:builder:4.1.3'
        classpath 'com.android.tools.build:bundletool:0.14.0'
        classpath 'androidx.databinding:databinding-compiler-common:4.1.3'
        classpath 'com.android.tools.analytics-library:crash:27.1.3'
        classpath 'com.android.tools:sdk-common:27.1.3'
        classpath 'com.android.tools.build:apkzlib:4.1.3'
        classpath 'com.android.tools:sdklib:27.1.3'
        classpath 'com.android.tools.layoutlib:layoutlib-api:27.1.3'
        classpath 'com.android.tools.build.jetifier:jetifier-processor:1.0.0-beta09'
        classpath 'org.ow2.asm:asm-commons:7.0'
        classpath 'org.jdom:jdom2:2.0.6'
        classpath 'com.android.tools:repository:27.1.3'
        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2'
        //classpath 'com.github.dcendents:android-maven-plugin:1.2'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
//        jcenter()
//        maven {
//            url 'https://maven.google.com/'
//            name 'Google'
//        }
    }

}

ext {
    // The following are only a few examples of the types of properties you can define.
    compileSdkVersion = 30
    // You can also create properties to specify versions for dependencies.
    // Having consistent versions between modules can avoid conflicts with behavior.
    supportLibVersion = "30.0.2"
}
//task clean(type: Delete) {
//    delete rootProject.buildDir
//}

android {
    compileSdkVersion 30
    buildToolsVersion '30.0.2'

    defaultConfig {
        applicationId ""
        minSdkVersion 15
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

ビルドも通りました。

でわでわ。。。

Java Network 〜 Socket通信で受付を行う〜

Socket通信処理の受付

Socket通信処理の実装を行いました。Githubに下のようなコードをコミットしてあります。

今回の内容について

  • まずはコードを見る
  • 処理の概要について
  • 通信処理について
  • 受信処理について
  • 感想

以上のような内容を記載します。

まずはコードを見る

下のように実装しました。
メインメソッドは一番下にあります。色々と試していたら長いコードになってしまいました。

/**
 * 低レベルSocketサーバー。
 * サーバーとクライアントの関係を理解するためのサンプルコード。
 * 単体アプリとする
 * @author 作成者の名前
 */
public class NaturalBornServlet extends Thread {
    private static final boolean DEBUG = true;
    /** 受け付けるおポート番号 */
    public static final int PORT_NO = 8081;
    /** 自分自身のインスタンス */
    private static NaturalBornServlet main;

    /** リクエスト */
    private BufferedReader request;
    /** レスポンス */
    private PrintWriter response;

    /** サーバーソケット */
    private ServerSocket server;
    /** 改行コード */
    private final char SEP = (char) 10;

    /**
     * 外部からの起動を禁止する。プライベートコンストラクタ。
     */
    private NaturalBornServlet() {
        try {
            server = new ServerSocket(PORT_NO);
        } catch (IOException e) {
            System.out.println("*** サーバーソケットの起動に失敗しました。 ***");
            e.printStackTrace();
            System.exit(-1);
        }
    }

    /**
     * デストラクタ。
     * サーバーソケットのクローズ、メモリの開放を行う。
     */
    public void finalize() {
        try {
            server.close();
        } catch (IOException e) {
            System.out.println("*** サーバーソケットの終了に失敗しました。 ***");
            e.printStackTrace();
        } finally {
            server = null;
            main = null;
            System.exit(-1);
        }
    }

    /**
     * 起動した、サーバーソケットで待機を行う。
     */
    public void run()  {
        try {
            System.out.println("*** サーバーソケット起動 ***");
            Socket sock = server.accept();
            // リクエスト
            request = new BufferedReader(new InputStreamReader(sock.getInputStream()));
            // レスポンス
            response = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));
            // リクエストの読み込み
            while(true) {
                String inputTxt = readRequest(request);

                if (inputTxt.contains("HTTP/1.1")) {
                    System.out.println("HTTP: " + inputTxt);
                    inputTxt = getHttpResponse(inputTxt);
                } else if ("".equals(inputTxt) ) {
                    System.out.println("***> 空リクエスト: " + inputTxt);
                    inputTxt = "<html><body>Hello World!</body></html>";
                } else {
                    System.out.println("***> else: " + inputTxt);
                    if (isBye(inputTxt)) {
                        break;
                    }
                }
                if (DEBUG) System.out.println("*** サーバーソケット: リクエスト受信 " + inputTxt + "***");

                // レスポンスを返す
                response.write(inputTxt + SEP);
                response.flush();
                System.out.println("*** サーバーソケット: レスポンス送信 " + inputTxt + "***");
                inputTxt = null;
//              request.close();
//              response.close();
//              sock.close();
//              request = null;
//              response = null;
//              break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private boolean isBye(String inputTxt) {
        if (inputTxt != null && inputTxt.startsWith("bye")) {
            System.out.println("*** サーバーを終了します。 ***");
            return true;
        }
        return false;
    }

    private String getHttpResponse(String req) {
        StringBuilder response = new StringBuilder();

        response.append("200 OK" + SEP);
        response.append("Access-Control-Allow-Origin: *" + SEP);
        response.append("Connection: Keep-Alive" + SEP);
        response.append("Content-Encoding: gzip" + SEP);
        response.append("Content-Type: text/html; charset=utf-8" + SEP);
        response.append("Date: Mon, 18 Jul 2016 16:06:00 GMT" + SEP);
        response.append("Etag: \"c561c68d0ba92bbeb8b0f612a9199f722e3a621a\"" + SEP);
        response.append("Keep-Alive: timeout=5, max=997" + SEP);
        response.append("Last-Modified: Mon, 18 Jul 2016 02:36:04 GMT" + SEP);
        response.append("Server: NaturalBorn" + SEP);
        response.append("Set-Cookie: mykey=myvalue; expires=Mon, 17-Jul-2017 16:06:00 GMT; Max-Age=31449600; Path=/; secure" + SEP);
        response.append("Transfer-Encoding: chunked" + SEP);
        response.append("Vary: Cookie, Accept-Encoding" + SEP);
        response.append("X-Backend-Server: developer2.webapp.scl3.mozilla.com" + SEP);
        response.append("X-Cache-Info: not cacheable; meta data too large" + SEP);
        response.append("X-kuma-revision: 1085259" + SEP);
        response.append("x-frame-options: DENY" + SEP);

        return response.toString();
    }

    /**
     * 受信した、メッセージを読み込む。
     *
     * @param in Socketより取得した入力ストリーム
     * @return
     * @throws IOException
     */
    private String readRequest(BufferedReader in) throws IOException {
        if (DEBUG) System.out.println("*** サーバーソケット: readRequest() ***");
        int read = 0;
        StringBuilder inputTxt = new StringBuilder();
//      System.out.println("**** read() : " + in.read());
//      System.out.println("**** ready() : " + in.ready());
//      System.out.println("**** readLine() : " + in.readLine());

        // CRとCRLFの場合で入力が終了している時がある
        while((read = in.read()) > 0) {
            // 空の場合
            if (read == 10 || read == 13) {
                System.out.println("*** read break ***");
                break;
            }
            char ch = (char) read;
            inputTxt.append(ch);
        }
        if (DEBUG) System.out.println("*** サーバーソケット: 完了:readRequest(): " + inputTxt + " ***");
        return inputTxt.toString();
    }
    /**
     * メインメソッド、ここから始まる。
     * @param args
     */
    public static void main(String[] args) {
        main = new NaturalBornServlet();

        try {
            main.start();
        } catch (Exception e) {
            System.out.println("*** 例外が発生しました。 " + e.getMessage() + "***");
            e.printStackTrace();
        }

    }
}

処理の概要と受信処理

上記のコードは大まかに下のような処理を行っています。

  1. メインメソッドでメイン処理を実行します。このクラスはThreadクラスを継承しているので、マルチスレッド処理を行うことができます。

  2. メインメソッドでstart()`が呼び出されているので、`run()メソッドが起動します。

  3. run()`メソッドでは、ServerSocketで`accept()を呼び出し、リクエストの受付を行います。
    つまりは、リクエストを受け付けるまで処理を行わず待っている状態になります。

  4. リクエストをつけ付けたら次のコードに処理が進みます。Socketクラスを受け取り、さらに入力ストリームと出力ストリームを取得します。入力は受け付けたリクエストで、出力は返却するレスポンスになります。具体的には下のようなコードです。

    // リクエスト
    request = new BufferedReader(new InputStreamReader(sock.getInputStream()));
    // レスポンス
    response = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));
  5. リクエストを読み込み、受信した内容に応じてレスポンスを返します。

    // リクエストの読み込み
    while(true) {
    String inputTxt = readRequest(request);
    
    if (inputTxt.contains("HTTP/1.1")) {
        System.out.println("HTTP: " + inputTxt);
        inputTxt = getHttpResponse(inputTxt);
    } else if ("".equals(inputTxt) ) {
        System.out.println("***> 空リクエスト: " + inputTxt);
        inputTxt = "<html><body>Hello World!</body></html>";
    } else {
        System.out.println("***> else: " + inputTxt);
        if (isBye(inputTxt)) {
            break;
        }
    }
    if (DEBUG) System.out.println("*** サーバーソケット: リクエスト受信 " + inputTxt + "***");
    
    // レスポンスを返す
    response.write(inputTxt + SEP);
    response.flush();
    System.out.println("*** サーバーソケット: レスポンス送信 " + inputTxt + "***");
    inputTxt = null;
    }
  6. リクエストの読み込みを行っているのは下のコードです。

    /**
    * 受信した、メッセージを読み込む。
    *
    * @param in Socketより取得した入力ストリーム
    * @return
    * @throws IOException
    */
    private String readRequest(BufferedReader in) throws IOException {
    if (DEBUG) System.out.println("*** サーバーソケット: readRequest() ***");
    int read = 0;
    StringBuilder inputTxt = new StringBuilder();
    System.out.println("**** read() : " + in.read());
    System.out.println("**** ready() : " + in.ready());
    System.out.println("**** readLine() : " + in.readLine());
    
    // CRとCRLFの場合で入力が終了している時がある
    while((read = in.read()) > 0) {
        // 空の場合
        if (read == 10 || read == 13) {
            System.out.println("*** read break ***");
            break;
        }
        char ch = (char) read;
        inputTxt.append(ch);
    }
    if (DEBUG) System.out.println("*** サーバーソケット: 完了:readRequest(): " + inputTxt + " ***");
    return inputTxt.toString();
    }

    ポイントになるのは、文字列を読み込をするときにに読み込む文字がないことを確認するために「改行コード」の数値型の値を使用しているところです。改行コードのchar型の値は整数型(int)で表現すると「13」もしくは「10」になります。CRLFCRの存在があるため2つになります。

通信処理について

通信処理=レスポンスの送信処理部分に関しては出力ストリームを使用して、送信します。

// レスポンスを返す
response.write(inputTxt + SEP);
response.flush();
System.out.println("*** サーバーソケット: レスポンス送信 " + inputTxt + "***");

「inputTxt」はString型の変数で、リクエストの値を取得しています。
つまりはリクエストで受けた文字列をそのまま返却しているというわけです。

感想

この実装は、Socket通信の最も簡単な処理になります。いわゆる「Socket通信のハローワールド」を実装したようなものでなので、通信処理の土台になります、逆に言うとこれを基本にどのような処理も実装することが可能ということです。

それなりに大変なことがありますが。。。

まとめると、通信の基本というところです。これを理解すれば、いろいろな通信処理の実装を行うことも可能になります。
なぜかというと、通信の基本を学んだからです。

でわでわ。。。

関連ページ

Java Basic

  1. Java Basic Level 1 Hello Java
  2. Java Basic Level2 Arithmetic Calculate
  3. Java Basic Level3 About String class
  4. Java Basic Level 4Boolean
  5. Java Basic Level 5If Statement
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 Traning of If statement
  8. Java Basic Level8 How to use for statement
  9. Java Basic Level 8.5 Array
  10. Java Basic Level 9Training of for statement
  11. Java Basic Level 10 While statement 
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1
  17. Java Basic JUnit 〜テストスイートの作り方〜

JavaFX in RPi 〜RPiでビルドをかける〜

JavaFXで作成したアプリケーションをRPi(ラズパイ)にインストールしたいと思います。

今までやってきたのは下にリンクをつけて置きます。

  1. メディアプレーヤ作成開始
  2. ラズパイでJavaFXを使うには
  3. [JavaFXとプロパティファイルを読み込み](Java FX in RPi 〜プロパティファイルの読み込み JavaFX実装〜)
  4. JavaFXで画面サイズ取得
  5. Youtubeにアクセス
  6. JavaFXでHTMLをロードする
  7. IFrame YoutubePlayerを使う

RPiでビルド準備

単純にビルドをかけるためにはMavenを使います。

Mavenとは

世間では「ビルドツール」としてよく目にしますが、「ビルドツールって何?」とか「用途は?」と疑問に思うことがあります。
早い話が、「ビルド!」ってやると、以下のようなことができます。

  1. 実行ファイルを作る
  2. 自動でテスト
  3. デプロイ
  4. 他の人のプロジェクトをダウンロード(git pull)

大雑把に上記のようなことができます。

Mavenのセットアップ in RPi

早速、RPiにアクセスしようと思います。SSH接続の詳細に関してはこちらに記載しています
補足としてメモもあります

とりあえずはSSHで接続します。

上のようにMavenがインストールされているか?
mvn -version
Javaがインストールされているか?を確認します。
java --version

しかし、上記の通りに何もインストールしていないのでここからインストールします。

Javaのインストール

Oracleからダウンロードしてインストールするのが一番良いと思います。(コマンドでインストールするとどこに何が?となる。。。)
調べてみたところ、ラズパイのサイトから見つけた方法が良いかと思いました。
これを実行します。

ラズパイにJDK

ラズパイのへのJDKのインストールに関しては、オラクルのサイトから手順を見ながら行いました。

bellsoft-jdk13-linux-arm32-vfp-hflt.debをインストールして、ラズパイでのJavaFXを起動できるようにします。

詳細に関しては、以下の通りです。

  1. 通常のJDK、Windowsなどの通常のPCで使用しているJDKではなく、ARM32用のJDKをインストール
  2. 「update-alternatives」コマンドで、使用するJDKを変更する
  3. Mavenをインストールする

この部分に関しては、下の記事に詳細を記載しています。
RPi JavaFX execution ~ラズパイでJavaFX起動~

しかし、自分がこの設定を行い実行したときは、リモートデスクトップ接続した状態だったので動きませんでした。
エラー詳細に関してはこちらに記載しています、とりあえずはリモートデスクトップ接続では動かなかったというところです。

あとは、ラズパイでの実行確認を行うだけなのですが、時間がなく。。。

中途半端な状態です。

でわでわ。。。

関連記事

Failed to write to /sys/class/input/mice/uevent

実行した環境

ラズパイでリモートデスクトップの設定を行い、WindowsのPCからリモートデスクトップ接続にてJavaFXを起動したときのエラーメッセージです。

ラズパイでのリモートデスクトップ設定に関してはリンク先の記事に書きました。

Failed to write to /sys/class/input/mice/uevent

ラズパイで作成したコード、JavaFXを起動するアプリケーションのコードをGithubから取得して、コンパイル、JARファイルを生成、実行したときのエラーです。

dev: Failed to write to /sys/class/input/mice/uevent
      Check that you have permission to access input devices
java.io.FileNotFoundException: /sys/class/input/mice/uevent (許可がありません)
    at java.io.FileOutputStream.open0(Native Method)
    at java.io.FileOutputStream.open(FileOutputStream.java:270)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:101)
    at com.sun.glass.ui.monocle.SysFS.write(SysFS.java:121)
    at com.sun.glass.ui.monocle.SysFS.triggerUdevNotification(SysFS.java:108)
    at com.sun.glass.ui.monocle.LinuxInputDeviceRegistry.<init>(LinuxInputDeviceRegistry.java:74)
    at com.sun.glass.ui.monocle.LinuxPlatform.createInputDeviceRegistry(LinuxPlatform.java:37)
    at com.sun.glass.ui.monocle.NativePlatform.getInputDeviceRegistry(NativePlatform.java:67)
    at com.sun.glass.ui.monocle.MonocleApplication.<init>(MonocleApplication.java:71)
    at com.sun.glass.ui.monocle.MonoclePlatformFactory.createApplication(MonoclePlatformFactory.java:42)
    at com.sun.glass.ui.Application.run(Application.java:146)
    at com.sun.javafx.tk.quantum.QuantumToolkit.startup(QuantumToolkit.java:259)
    at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:211)
    at com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:675)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:337)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)

実行手順

ラズパイを起動して、以下のようなコマンドを叩きました。

cd repos # リポジトリのあるディレクトリに移動
git pull # Gitからソースを取得する

そして、Javaコマンドで作成したJARファイルを実行

これは、コマンドの実行時に、「sudo」をつけることで解決しました。

つまりは以下のようなコマンドを実行すればよいわけです。エラーの原因はファイルにアクセスする権限がなかったということです。

なので「sudo」コマンドでスーパーユーザーの権限でjavaコマンドを実行したら解決したというわけです。

sudo java -jar target/RPiMediaPlayer-0.0.1-SNAPSHOT-jar-with-dependencies.jar

次のエラーメッセージ

出力されたメッセージは下のようなものです。

Exception in Application constructor
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Unable to construct Application instance: class application.Main
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:907)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$1(LauncherImpl.java:182)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$7(LauncherImpl.java:819)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
    at com.sun.glass.ui.monocle.RunnableProcessor.runLoop(RunnableProcessor.java:93)
    at com.sun.glass.ui.monocle.RunnableProcessor.run(RunnableProcessor.java:52)
    ... 1 more
Caused by: java.awt.AWTError: Can't connect to X11 window server using ':10.0' as the value of the DISPLAY variable.
    at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
    at sun.awt.X11GraphicsEnvironment.access$200(X11GraphicsEnvironment.java:65)
    at sun.awt.X11GraphicsEnvironment$1.run(X11GraphicsEnvironment.java:115)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.awt.X11GraphicsEnvironment.<clinit>(X11GraphicsEnvironment.java:74)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at java.awt.GraphicsEnvironment.createGE(GraphicsEnvironment.java:103)
    at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:82)
    at application.Main.initWindowInfo(Main.java:154)
    at application.Main.<init>(Main.java:88)
    ... 12 more
Exception running application application.Main

キーポイント

ここで忘れてはいけないのが「リモートデスクトップ」での実行であったというところ

そして、以下の部分がキーポイントになりました。

Can't connect to X11 window server using ':10.0' as the value of the DISPLAY variable.

しかし、この部分の解決に至らず。。。

もう少し調査をすることにしました。

そして、調べていくうちにSSHなどのように外部からアクセスして実行するケースで上のようなエラーメッセージが表示されるという記事を見つけました。

つまりは、リモートデスクトップでのアプリケーションの起動は、エラーが出るということでした。

次は、ラズパイ本体で実行してみることにします。

でわでわ。。。

PHP LMS2 ~Moodleのインストール~

Moodle

MoodleというLMS(ラーニング・マネジメント・システム)で、早い話が、以下のような事ができます。

  • 学生に告知する情報の一覧
  • 授業(科目毎)の授業内容やドキュメントの登録
  • その他いろいろ

詳細に関しては本家のサイトをご覧ください。日本のページもあります。

概要の動画らしいです。

インストール

日本語のドキュメントを参考にしました。

  1. このサイトからMoodle本体をダウンロード
  2. XAMMP, Apacheなどのドキュメントルートにコピー、もしくは展開する
    ※「localhost/」に展開したディレクトリ(index.php)が配置されているようにする
  3. DBを作成する(MySQLの場合は、下のSQLで作成しました。)

    CREATE DATABASE moodle DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

    GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,CREATE TEMPORARY TABLES,DROP,INDEX,ALTER ON DATABASENAME.* TO 'ユーザー名'@'localhost' IDENTIFIED BY 'パスワード';
    4.ウェブサーバーを起動して、ブラウザから「展開フォルダ/install.php」=「localhost」を開く

  4. 管理者ユーザーの設定を行う

これで、うまくいってデータの追加などを行ったのですが、また動かなくなりました。。。

再インストールする

作成されたDBと設定したい下のフォルダにある「cashe」「session」を削除
<config.php>

$CFG->dataroot = 'D:/Apps/moodle-latest-310/moodledata';

MySQLのDBを削除

DROP DATABASE 作成したDB

改めて、localhost/install.phpを実行する

あと、初期表示するHOMEのURLを覚えておいたほうがよいです。

でわでわ。。。

Mavan インストール ~ワンポイントレッスン的な~

Mavenのインストール

このMavenはビルドツールとして世界中で利用されているものです。自分も開発したり、サンプルを作成するときに使用することが多いです。同類のものとしてgradleというものがありますが、今回はビルドツールのMavenをインストールします。

Javaのインストール

こちらのサイト、java.netよりインストーラーをダウンロードできます。これでインストールすると
Mavenのインストール準備ができます。

確認方法

「windows」ボタンを押しながら「R]ボタンを押下します。

すると下のようなダイアログが表示されるので「cmd」と入力してエンターキーを押下してください、
するとコマンドプロンプトが開きます。

ここでjava --versionと入力してバージョン情報が表示されればOKです。(ラズパイでの表示ですが。。。)

Mavenのインストール

  1. Apache MavanのサイトからZIP(apache-maven-X.X.X-bin.zip)ファイルをダウンロードします。※「X」は数字が入ります。
    手順はです。

  2. ZIPのファイルを展開して、展開後にできたフォルダが以下のようになります。

  3. 最後に、上のbinフォルダを環境変数へ登録します。

こんな感じです。

でわでわ。。。

関連ページ一覧

[Eclipse セットアップ](http://zenryokuservice.com/wp/2020/09/01/%e9%96%8b%e7%99%ba%e7%92%b0%e5%a2%83%e6%a7%8b%e7%af%89%ef%bd%9ewindows%e7%89%88eclipse%e3%81%ae%e8%a8%ad%e5%ae%9a%ef%bd%9e/)

  1. Java Install Eclipse〜開発ツールのインストール〜
  2. TensorFlow C++環境〜EclipseCDTをインストール〜
  3. Setup OpenGL with JavaJOGLを使う準備 for Eclipse
  4. Eclipse Meven 開発手順〜プロジェクトの作成〜
  5. Java OpenCV 環境セットアップ(on Mac)
  6. Eclipse SceneBuilderを追加する
  7. JavaFX SceneBuilder EclipseSceneBuilder連携~

Java Basic一覧

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Level 4〜Boolean〜
  5. Java Basic Level 5〜If Statement〜
  6. Java Basic Summary from Level1 to 5
  7. Java Basic Level 6 〜Traning of If statement〜
  8. Java Basic Level8 〜How to use for statement〜
  9. Java Basic Level 8.5 〜Array〜
  10. Java Basic Level 9〜Training of for statement〜
  11. Java Basic Level 10 〜While statement 〜
  12. Java Basic Swing〜オブジェクト指向〜
  13. Java Basic Swing Level 2〜オブジェクト指向2〜
  14. サンプル実装〜コンソールゲーム〜
  15. Java Basic インターフェース・抽象クラスの作り方
  16. Java Basic クラスとは〜Step2_1〜
  17. Java Basic JUnit 〜テストスイートの作り方〜

Git関連

  1. Java Git clone in Eclipse 〜サンプルの取得〜
  2. Eclipse Gitリポジトリの取得 GitからソースをPullしよう〜
  3. IntelliJ IDEA GitGitリポジトリからクローン〜

JavaFX関連ページ

  1. Eclipse SceneBuilderを追加する
  2. JavaFX SceneBuilder 〜EclipseとSceneBuilder連携~
  3. JavaFX SceneBuilder〜ボタンにメソッドを割り当てるワンポイント〜
  4. Java プロコンゲーム 〜見た目の作成(SceneBuilderの使用)〜

ステップアップ関連ページ一覧

  1. Java 初めてでも大丈夫〜ステップアッププログラミングのススメ〜
  2. ステップアッププログラミング〜Java FxでHelloWorld解説〜
  3. Java StepUpPrograming〜JavaFX で四則計算〜
  4. Java StepUpPrograming〜JavaFXで画面切り替えを作る1〜
  5. Java StepUpPrograming〜JavaFXで画面切り替え2ボタン作成〜
  6. Java StepUpPrograming〜JavaFXで画面切り替え3アクション〜
  7. Java StepUpPrograming〜JavaFXで画面切り替え4Pane切り替え〜
  8. Java StepUpPrograming〜JavaFXで画面切り替え5WebEngine

JavaFX + ND4Jで機械学習準備

  1. JavaFX + ND4J〜数学への挑戦1:ND4Jのインストール〜
  2. JavaFX + ND4J〜数学への挑戦2: 行列の計算〜
  3. Java + ND4J 〜数学への挑戦3: ベクトル(配列)の作成方法〜

オブジェクト指向関連ページ

  1. [オブジェクト指向の概念1〜OracleDocのチュートリアル1〜](https://zenryokuservice.com/wp/2019/10/301. /%e3%82%aa%e3%83%96%e3%82%b8%e3%82%a7%e3%82%af%e3%83%88%e6%8c%87%e5%90%91%e3%81%ae%e6%a6%82%e5%bf%b5-%e3%80%9coracledoc%e3%81%ae%e3%83%81%e3%83%a5%e3%83%bc%e3%83%88%e3%83%aa%e3%82%a2%e3%83%ab%ef%bc%91/)
  2. オブジェクト指向の概念2〜クラスとは〜

Java Discord

  1. IntelliJ IDEA Discord Botを作る〜Gradle環境のセットアップ〜
  2. Java Discord セットアップ〜Hello Discord〜
  3. Java Discord ピンポン〜Discordプログラム〜
  4. Java Discord Listener実装〜コマンドを好きなだけ追加しよう〜

java.lang.UnsatisfiedLinkError: Can’t load library

Can't load library

表題のようなエラーが出ました。

java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
        at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
        at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
        at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$1(LauncherImpl.java:182)
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.UnsatisfiedLinkError: Can't load library: jdk1.8.0_265\jre\bin\jfxwebkit.dll
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1820)
        at java.lang.Runtime.load0(Runtime.java:810)
        at java.lang.System.load(System.java:1088)
        at com.sun.glass.utils.NativeLibLoader.loadLibraryFullPath(NativeLibLoader.java:201)
        at com.sun.glass.utils.NativeLibLoader.loadLibraryInternal(NativeLibLoader.java:94)
        at com.sun.glass.utils.NativeLibLoader.loadLibrary(NativeLibLoader.java:39)
        at com.sun.webkit.WebPage.lambda$static$0(WebPage.java:133)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.webkit.WebPage.<clinit>(WebPage.java:132)
        at javafx.scene.web.WebEngine.<init>(WebEngine.java:881)
        at javafx.scene.web.WebEngine.<init>(WebEngine.java:868)
        at javafx.scene.web.WebView.<init>(WebView.java:273)
        at application.Main.start(Main.java:49)
        at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:863)
        at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
        at com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
        at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
        at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at com.sun.glass.ui.win.WinApplication.lambda$null$3(WinApplication.java:177)
        ... 1 more
Exception running application application.Main
Caused by: java.lang.UnsatisfiedLinkError: Can't load library: D:\Apps\jdk1.8.0_265\jre\bin\jfxwebkit.dll
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1820)
        at java.lang.Runtime.load0(Runtime.java:810)
        at java.lang.System.load(System.java:1088)
        at com.sun.glass.utils.NativeLibLoader.loadLibraryFullPath(NativeLibLoader.java:201)
        at com.sun.glass.utils.NativeLibLoader.loadLibraryInternal(NativeLibLoader.java:94)
        at com.sun.glass.utils.NativeLibLoader.loadLibrary(NativeLibLoader.java:39)
        at com.sun.webkit.WebPage.lambda$static$0(WebPage.java:133)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.webkit.WebPage.<clinit>(WebPage.java:132)
        at javafx.scene.web.WebEngine.<init>(WebEngine.java:881)
        at javafx.scene.web.WebEngine.<init>(WebEngine.java:868)
        at javafx.scene.web.WebView.<init>(WebView.java:273)
        at application.Main.start(Main.java:49)
        at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:863)
        at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$7(PlatformImpl.java:326)
        at com.sun.javafx.application.PlatformImpl.lambda$null$5(PlatformImpl.java:295)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.javafx.application.PlatformImpl.lambda$runLater$6(PlatformImpl.java:294)
        at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
        at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at com.sun.glass.ui.win.WinApplication.lambda$null$3(WinApplication.java:177)
        ... 1 more

実行環境

Eclipseで作成したJavaFXアプリケーションをJarファイルに出力して実行したときのエラーです。
ライブラリが参照できていないようです。

参照できていないライブラリは以下のようなものでした。

jdk1.8.0_265\jre\bin\
- jfxwebkit.dll
- fxplugins.dll
- glib-lite.dll
- gstreamer-lite.dll
- jfxmedia.dll
- jfxwebkit.dll

これは、JDKにJavaFXが梱包されているJDK corret(Amazon)なら問題ないようです。

そんなにてこずらずに解決できました。

でわでわ。。。