【Java】QRコードジェネレータ

<h2>１．背景</h2>

身近なテーマで何か作りたかったため。
Javaにしたのは何となくです。


<h2>２．環境</h2>

Windows 11 22H2
Eclipse 2022-06 (4.24.0)
openjdk 17.0.3

<h2>３．Maven ／ Gradleの記述例</h2>

<h3>Maven</h3>

```markdown:pom.xml
	<dependencies>
		<dependency>
			<groupId>com.google.zxing</groupId>
			<artifactId>core</artifactId>
			<version>3.5.2</version>
		</dependency>
		<dependency>
			<groupId>com.google.zxing</groupId>
			<artifactId>javase</artifactId>
			<version>3.5.2</version>
		</dependency>
    </dependencies>
```

<h3>Gradle</h3>


```markdown:build.gradle

dependencies {
    implementation 'com.google.zxing:core:3.5.2'
    implementation 'com.google.zxing:javase:3.5.2'
}


```

<h2>４．ソース</h2>

```markdown:CreateQrcode.java
import java.awt.FileDialog;
import java.awt.Frame;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.Scanner;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

public class CreateQrcode {

    // Loggerを設定
    private static final Logger logger = Logger.getLogger(CreateQrcode.class.getName());

    static {
        try {
            // ログの出力先ファイルを設定
            FileHandler fileHandler = new FileHandler("error.log", true); // 追記モードでログを記録
            fileHandler.setFormatter(new SimpleFormatter());
            logger.addHandler(fileHandler);
            logger.setLevel(Level.ALL);
        } catch (IOException e) {
            System.err.println("ログファイルの初期化に失敗しました: " + e.getMessage());
        }
    }

    public static void main(String[] args) {
        // フレームを作成 (FileDialogはFrameが必要)
        Frame frame = new Frame();

        // 出力先フォルダを選択する
        FileDialog fileDialog = new FileDialog(frame, "出力フォルダを選択", FileDialog.LOAD);
        fileDialog.setVisible(true);

        // 選択されたディレクトリのみ取得
        String directory = fileDialog.getDirectory();
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        
        if (directory != null) {
            // 出力ファイルのパスを設定（フォルダ+ファイル名）
            File outputFile = new File(directory, sdf.format(date) + "_output_qrcode.png");

            // QRコード生成
            CreateQrCode(outputFile);
        } else {
            System.out.println("出力フォルダ選択がキャンセルされました。");
        }

        // フレームを閉じる
        frame.dispose();
    }

    public static void CreateQrCode(File outputFile) {
        try (Scanner sc = new Scanner(System.in)) {
            System.out.print("QRコード化したいURLを入力してください > ");
            
            String contents = sc.nextLine();
            BarcodeFormat format = BarcodeFormat.QR_CODE;
            int width = 160;
            int height = 160;

            Hashtable<EncodeHintType, ErrorCorrectionLevel> hints = new Hashtable<>();
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);

            QRCodeWriter writer = new QRCodeWriter();
            BitMatrix bitMatrix = writer.encode(contents, format, width, height, hints);
            BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix);
            
            // QRコード画像を指定したファイルに書き込む
            ImageIO.write(image, "png", outputFile);

            System.out.println("QRコードが正常に生成されました: " + outputFile.getAbsolutePath());
        } catch (Exception e) {
            System.out.println("エラーが発生しました。ログを確認してください。");
            logger.log(Level.SEVERE, "QRコードの生成に失敗しました", e); // ログファイルにエラー内容を記録
        }
    }
}
```

<h2>５．ソース解説</h2>

エラーログ出力の設定を行う。

    // Loggerを設定
    private static final Logger logger = Logger.getLogger(CreateQrcode.class.getName());

    static {
        try {
            // ログの出力先ファイルを設定
            FileHandler fileHandler = new FileHandler("error.log", true); // 追記モードでログを記録
            fileHandler.setFormatter(new SimpleFormatter());
            logger.addHandler(fileHandler);
            logger.setLevel(Level.ALL);
        } catch (IOException e) {
            System.err.println("ログファイルの初期化に失敗しました: " + e.getMessage());
        }
    }

OS標準のファイルダイアログを表示する。

Frameは、JavaのFileDialogクラスで、指定したタイトルと親フレーム（Frame parent）を使用してファイルロード用のダイアログウィンドウを生成する。

```
    // フレームを作成 (FileDialogはFrameが必要)
    Frame frame = new Frame();
    
    // 出力先フォルダを選択する
    FileDialog fileDialog = new FileDialog(frame, "出力フォルダを選択", FileDialog.LOAD);
    fileDialog.setVisible(true);

```

Scannerクラスを用いて、コマンドラインからQRコード化したいURLの入力受付を行う。
```
    Scanner sc = new Scanner(System.in)) {
        System.out.print("QRコード化したいURLを入力してください > ");
```

QRコードのフォーマットおよびサイズ指定。
```
        BarcodeFormat format = BarcodeFormat.QR_CODE;
        int width = 160;
        int height = 160;
```

ヒント情報とエラー訂正レベルをHashtableで定義する。
```
        Hashtable<EncodeHintType, ErrorCorrectionLevel> hints = new Hashtable<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
```

QRコードを生成する。
```
        QRCodeWriter writer = new QRCodeWriter();
        BitMatrix bitMatrix = writer.encode(contents, format, width, height, hints);
        BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix);
```

QRコード画像をファイルに書き込む。
```
        // QRコード画像を指定したファイルに書き込む
        ImageIO.write(image, "png", outputFile);

```


<h2>６．動作イメージ</h2>

ここではURL短縮サービスをQRコード化してみる。
出力先はCドライブ直下を想定。


https://x.gd/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615710/6905ba6c-db23-ac97-5ab0-af1ec1574e16.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615710/5b218e12-458e-bb60-36e2-b741f395ffef.png)

実際に生成したコード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3615710/7a0ee7cb-4bf2-1e1a-b11d-64c32a18802a.png)


<h2>６．改善点</h2>

ネイティブアプリ化することだがこの程度の機能の需要はない、はず。。