[Java] 25 リストとfor文

前回の続きです。

競走馬名に対して登録が複数ある場合に競走馬IDをリスト化するコードを書きました。

Listを使うために一々ライブラリをimportするのには少し驚きました。

for文の書き方はPythonよりこちらの方が好みかも。

package mysql_test3;

import java.util.ArrayList;
import java.util.List;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class AppTest {
    public static void main(String args[]) {
        String url = "jdbc:mysql://localhost:3306";
        String user = "ユーザ名";
        String password = "パスワード";

        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);

        System.out.println("競走馬名を入力してください");

        String name = null;
        try {
            name = br.readLine();}

        catch (IOException e) {
            e.printStackTrace();}

        System.out.println("競走馬名は「" + name + "」です");

        List<String> ID_list = new ArrayList<String>();
        for (int i = 1986; i < 2019; i++){
            try (Connection conn = DriverManager.getConnection(url, user, password)){
                String sql = String.format("SELECT horseID FROM \
                horse_list.horse%d WHERE 検索馬名 = '%S'",i,name);
                PreparedStatement ps = conn.prepareStatement(sql);
                ResultSet rs = ps.executeQuery();

                String ID = null;
                while (rs.next()) {
                    ID = rs.getString("horseID");
                    System.out.println(ID);
                    ID_list.add(ID);
                    System.out.println(ID_list);}}

            catch (Exception e) {
                    e.printStackTrace();}}}}
--------------------------------------------------

出力
--------------------------------------------------
競走馬名を入力してください
ヒシマサル
競走馬名は「ヒシマサル」です
198908574
[198908574]
201405934
[198908574, 201405934]

[Java] 24 標準入力取得とformatメソッド

前回の続きです。

ターミナルに競走馬名を入力しそれを元にSQL文を作成、そして競走馬IDを検索するコードを書きました。

特に引っかかるところはなかったです。

package mysql_test2;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class AppTest {
    public static void main(String args[]) {
        String url = "jdbc:mysql://localhost:3306";
        String user = "ユーザ名";
        String password = "パスワード";

        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);

        System.out.println("競走馬名を入力してください");

        String name = null;
        try {
            name = br.readLine();}

        catch (IOException e) {
            e.printStackTrace();}

        System.out.println("競走馬名は「" + name + "」です");

        try (Connection conn = DriverManager.getConnection(url, user, password)){
            String sql = String.format("SELECT horseID FROM horse_list.horse2018 \
            WHERE 検索馬名 = '%S'",name);
            PreparedStatement ps = conn.prepareStatement(sql);
            ResultSet rs = ps.executeQuery();

            while (rs.next()) {
                System.out.println(rs.getString("horseID"));}}

        catch (Exception e) {
                e.printStackTrace();}}}

[Java] 23 mySQLへの接続

以前Pythonで書いたmySQL検索コードをJavaに取り込めないか調べたところ、Jython(ジャイソンと読むらしい)ならできることが判明。しかしPython2のみ対応とのことで断念し、素直にJavaで書き直します。

昨年の4月に相当苦労してVScodeでのJava開発環境を構築しMavenプロジェクトを作成できるようにしましたが、そのおかげでデータベースAPIであるJDBCを簡単に導入できました。

mySQLの自製競馬データベースに接続し、ダービー馬”シャフリヤール”の競走馬IDを検索するコードを以下に記します。

しかしこのシンプルなコードを書くだけで、Javaの取っつきにくさを知るハメになりました。

Pythonのようにfinallyを安易には使えないようです。[Java]21の記事でCSVファイルを閉じられなかった理由がわかりました。

今回はtry-with-resources文でそれなりのコードにしました。この内容でもPreparedStatementとResultSetを閉じておらず不完全ですが、とりあえずよしとします。

package mysql_test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class AppTest {
    public static void main(String args[]) {
        String url = "jdbc:mysql://localhost:3306";
        String user = "ユーザ名";
        String password = "パスワード";

        try (Connection conn = DriverManager.getConnection(url, user, password)){
            String sql = "SELECT horseID FROM horse_list.horse2018 WHERE \
            検索馬名 = 'シャフリヤール'";
            PreparedStatement ps = conn.prepareStatement(sql);
            ResultSet rs = ps.executeQuery();

            while (rs.next()) {
                System.out.println(rs.getString("horseID"));}}

        catch (Exception e) {
                e.printStackTrace();}}}

[Java] 22 スクレイピング によるテキスト取得

スクレイピングでWebサイトのテキストを取得してみました。

開発サイトから入手したjsoupライブラリは外部ライブラリとして設定しました。VScodeの拡張機能”Java Extension Pack”を使います。

プロジェクトを作るまでもない単独ファイルの場合はVScodeが手軽で便利です。

行の先頭にある波カッコが気になるため、全て行末に置いてみました。これだと一見Pythonっぽくなります。

import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class Scraping {
	public static void main(String[] args) {
		try {
			Document doc = Jsoup.connect("対象サイトのURL").get();
			Elements elements = doc.select("タブ名");

			for (Element element : elements) {
				System.out.println(element.text());}}

		catch (IOException e) {
			e.printStackTrace();}}}

[Java] 21 CSVファイルの読み込み

Javaに関する記事は昨年10月以来です。

CSVファイルを読み込んでみました。

BufferedReader等をどうしても閉じることができず放置しています。

波カッコが相変わらず目障りですが、位置は適当でも数さえ合っていればいいので見ないようにしています。

文法がやや複雑なのでPythonでは浮き彫りになるコーダーのセンスが分かりにくいのも特徴の一つでしょうか。

Pythonと比較しながら学習を進めるのも楽しそうです。

import java.io.*;

public class ReadCSV {

    public static void main(String[] args) {
        String file_name = "test.csv";
        try {
            // File file = new File(file_name);
            // FileInputStream input = new FileInputStream(file);
            // InputStreamReader stream = new InputStreamReader(input,"shift_jis");
            // BufferedReader br = new BufferedReader(stream);
            
       // 一つにまとめました
            BufferedReader br = new BufferedReader(
                new InputStreamReader(
                new FileInputStream(
                new File(file_name)),"shift_jis"));

            String line;
            String[] data;

            while ((line = br.readLine()) != null) {
                byte[] b = line.getBytes();
                line = new String(b, "utf-8");
                data = line.split(",");
            
                for (int i = 0; i < data.length; i++) {
                    System.out.print(data[i] + " ");
            }
                System.out.println();
        }
        }
        catch (Exception e) {
            System.out.println(e.getMessage());
        }
     
        // 閉じようとしてもエラーになるため省略
        // finally {
        //     try {
        //         br.close();
        // }

        //     catch (Exception e) {
        //         System.out.println(e.getMessage());
        // }
        // }
        }
        }

[Python] 265 日付・時刻の文字列化関数

前回記事の続きです。

日付・時刻の文字列化コードは使用頻度がかなり高いため関数にしました。

import datetime

datetime_now = datetime.datetime.now()

def now():
    datetime_now_str = datetime_now.strftime('%y%m%d%H%M')
    return datetime_now_str

def today():
    datetime_today_str = datetime_now.strftime('%y%m%d')
    return datetime_today_str
from my_library import date

print(date.now())
print(date.today())
--------------------------------------------------

出力
--------------------------------------------------
2106081330
210608

[Python] 264 日付・時刻の文字列化

ファイル名に今日の日付や現在時刻を付ける場合の文字列作成コードです。

import datetime

datetime_now = datetime.datetime.now()
datetime_now_str = datetime_now.strftime('%y%m%d%H%M')
datetime_today_str = datetime_now.strftime('%y%m%d')

filename_now = f"/{datetime_now_str}.csv"
filename_today = f"/{datetime_today_str}.csv"

print(filename_now)
print(filename_today)
--------------------------------------------------

出力
--------------------------------------------------
/2106080730.csv
/210608.csv

[Python] 263 C言語でモジュールを作成

[macOS Catalina 10.15.7]

これまで自作モジュールはPythonで書いてきましたが、高速化が必要な場合にC/C++モジュールで対応するためテストしてみました。

1.C言語モジュールの作成

#include <Python.h>

static PyObject* 
hello_world (PyObject *self, PyObject *args) {
  printf("Hello_world\n");
  Py_RETURN_NONE;
}

// メソッドの定義
static PyMethodDef TestMethods[] = {
  {"hello_world", (PyCFunction)hello_world, METH_NOARGS, "test1: hello_world"},
  {NULL, NULL, 0, NULL}
};

// モジュールの定義
static struct PyModuleDef testmodule = {
  PyModuleDef_HEAD_INIT,
  "test",
  NULL,
  -1,
  TestMethods
};

// メソッドの初期化
PyMODINIT_FUNC PyInit_test (void) {
  return PyModule_Create(&testmodule);
}

2.setup.pyの作成

from distutils.core import setup, Extension
setup(name='test',
        version='1.0',
        ext_modules=[Extension('test', ['test.c'])]
)

3.C言語モジュールのビルド

python setup.py build_ext -i

4.C言語モジュールの動作チェック

作成されたtest.cpython-39-darwin.soファイルをあらかじめ用意しておいたc_moduleフォルダへコピーし、以下のコードを実行。

c_moduleフォルダをライブラリとして認識させるため、フォルダ内に空の__init__.pyを置くようにする。

そしてc_moduleフォルダまたはシンボリックリンクをこのコードと同じところに置く。

なお今後のためにc_moduleフォルダを作成しましたが、soファイルをソースコードと同じところに置くだけでも1行目”import test”にて実行可能です。

from c_module import test

test.hello_world()
--------------------------------------------------

出力
--------------------------------------------------
Hello_world

参考サイト

[Python] 262 subprocessモジュール2 日付を出力 続編

[macOS Catalina 10.15.7]

前記事でBashにて3日後の日付を出力させるのに苦労しましたが、仕切り直しで再調査したところあっさり解決しました。

info dateコマンドで出力されるドキュメントが参考になりました。やはり分からなければ開発元のドキュメントを読むのが基本ですね。

UNIXのタイプによってルールが全く異なるというのがよく分かりました。ちなみにmacOSはBSDベースです。

import subprocess
from subprocess import PIPE

# 3日後の場合 Bash
com_date_3 = subprocess.run("date -v+3d +%y%m%d", shell=True, stdout=PIPE, stderr=PIPE, text=True)
date_3 = com_date_3.stdout

print(f'date_3 {date_3}')
--------------------------------------------------

出力
--------------------------------------------------
date_3 210531

[Python] 261 subprocessモジュール1 日付を出力

[macOS Catalina 10.15.7]

Bashのコマンドで日付を出力させてみました。

今日の日付は特に問題ないですが、3日後の書き方でドハマりしました。

とりあえず出力できましたが、他にスマートな書き方がないのであればこの使い方ではBash&macOSは却下です。

Zshにすれば普通になるのでしょうか。

import subprocess
from subprocess import PIPE
import datetime

# 今日の日付 Bash
com_date = subprocess.run("date +%y%m%d", shell=True, stdout=PIPE, stderr=PIPE, text=True)
date = com_date.stdout

print(date)

# 今日の日付 Python
date_today = datetime.date.today()
date_today_str = date_today.strftime('%y%m%d')

print(date_today_str)

# 3日後の日付 Bash 時差+9-72=-63 このスクリプトは可読性低い
com_date_3 = subprocess.run("env TZ=JST-63 date +%y%m%d", shell=True, stdout=PIPE, stderr=PIPE, text=True)
date_3 = com_date_3.stdout

print(f'date_3 {date_3}')

# 3日後の日付 Python
days3 = datetime.timedelta(days = 3)
date_days3 = date_today + days3
date_days3_str = date_days3.strftime('%y%m%d')

print(f'date_days3_str {date_days3_str}')
--------------------------------------------------

出力
--------------------------------------------------
210527
210527
date_3 210530
date_days3_str 210530