0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Javaのアプリ

Last updated at Posted at 2024-07-01

コンソールではなくGUIで対話式のインターフェースを提供するために、JavaのSwingを使用します。以下に、Swingを用いて対話式のファイル比較ツールを実装したコードを示します。

Swingを用いた対話式ファイル比較ツール

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.*;

public class FileComparator extends JFrame {
    private static final int THREAD_POOL_SIZE = 4;  // Intel i5の4コアに合わせて設定
    private static final int BUFFER_SIZE = 8192;

    private JTextField sourceFolderPathField;
    private JTextField targetFolderPathField;
    private JTextArea outputArea;
    private JButton compareButton;

    public FileComparator() {
        setTitle("ファイル比較ツール");
        setSize(600, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLayout(new BorderLayout());

        JPanel inputPanel = new JPanel();
        inputPanel.setLayout(new GridLayout(3, 2));

        inputPanel.add(new JLabel("ソースフォルダのパス:"));
        sourceFolderPathField = new JTextField();
        inputPanel.add(sourceFolderPathField);

        inputPanel.add(new JLabel("ターゲットフォルダのパス:"));
        targetFolderPathField = new JTextField();
        inputPanel.add(targetFolderPathField);

        compareButton = new JButton("比較開始");
        inputPanel.add(compareButton);

        add(inputPanel, BorderLayout.NORTH);

        outputArea = new JTextArea();
        outputArea.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(outputArea);
        add(scrollPane, BorderLayout.CENTER);

        compareButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String sourceFolderPath = sourceFolderPathField.getText();
                String targetFolderPath = targetFolderPathField.getText();

                if (!isValidFolder(sourceFolderPath) || !isValidFolder(targetFolderPath)) {
                    outputArea.append("提供されたフォルダパスが無効です。\n");
                    return;
                }

                outputArea.append("比較を開始します...\n");
                long startTime = System.currentTimeMillis();
                compareFolders(sourceFolderPath, targetFolderPath);
                long endTime = System.currentTimeMillis();
                outputArea.append("処理時間: " + (endTime - startTime) + " ミリ秒\n");
            }
        });
    }

    private boolean isValidFolder(String folderPath) {
        File folder = new File(folderPath);
        return folder.isDirectory();
    }

    private void compareFolders(String sourceFolderPath, String targetFolderPath) {
        File sourceFolder = new File(sourceFolderPath);
        File targetFolder = new File(targetFolderPath);

        File[] sourceFiles = sourceFolder.listFiles();
        File[] targetFiles = targetFolder.listFiles();

        Map<String, File> sourceFileMap = new HashMap<>();
        Map<String, File> targetFileMap = new HashMap<>();

        if (sourceFiles != null) {
            for (File file : sourceFiles) {
                sourceFileMap.put(file.getName(), file);
            }
        }

        if (targetFiles != null) {
            for (File file : targetFiles) {
                targetFileMap.put(file.getName(), file);
            }
        }

        Set<String> allFileNames = new HashSet<>();
        allFileNames.addAll(sourceFileMap.keySet());
        allFileNames.addAll(targetFileMap.keySet());

        ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
        List<Future<?>> futures = new ArrayList<>();

        for (String fileName : allFileNames) {
            Future<?> future = executorService.submit(() -> {
                File sourceFile = sourceFileMap.get(fileName);
                File targetFile = targetFileMap.get(fileName);

                try {
                    if (sourceFile == null) {
                        // 追加データ
                        writeToFile(targetFile, "updatedData.txt", "追加データ: " + fileName);
                        outputArea.append("追加データ: " + fileName + "\n");
                    } else if (targetFile == null) {
                        // 削除データ
                        writeToFile(sourceFile, "deletedData.txt", "削除データ: " + fileName);
                        outputArea.append("削除データ: " + fileName + "\n");
                    } else {
                        // 差分比較
                        compareFiles(sourceFile, targetFile, "updatedData.txt");
                    }
                } catch (IOException e) {
                    outputArea.append("ファイル処理中のエラー: " + fileName + "\n");
                    e.printStackTrace();
                }
            });
            futures.add(future);
        }

        for (Future<?> future : futures) {
            try {
                future.get();
            } catch (InterruptedException | ExecutionException e) {
                outputArea.append("並行実行中のエラー\n");
                e.printStackTrace();
            }
        }

        executorService.shutdown();
    }

    private void compareFiles(File sourceFile, File targetFile, String outputFileName) throws IOException {
        try (BufferedReader sourceReader = new BufferedReader(new FileReader(sourceFile), BUFFER_SIZE);
             BufferedReader targetReader = new BufferedReader(new FileReader(targetFile), BUFFER_SIZE)) {

            String sourceLine;
            String targetLine;
            boolean differencesFound = false;

            while ((sourceLine = sourceReader.readLine()) != null && (targetLine = targetReader.readLine()) != null) {
                if (!sourceLine.equals(targetLine)) {
                    writeToFile(sourceFile, outputFileName, "更新あり: " + sourceFile.getName());
                    outputArea.append("更新あり: " + sourceFile.getName() + "\n");
                    differencesFound = true;
                    break;
                }
            }

            if (!differencesFound && (sourceReader.readLine() != null || targetReader.readLine() != null)) {
                writeToFile(sourceFile, outputFileName, "更新あり: " + sourceFile.getName());
                outputArea.append("更新あり: " + sourceFile.getName() + "\n");
            }
        }
    }

    private void writeToFile(File file, String outputFileName, String header) throws IOException {
        synchronized (FileComparator.class) {
            try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputFileName, true), BUFFER_SIZE);
                 BufferedReader reader = new BufferedReader(new FileReader(file), BUFFER_SIZE)) {
                writer.write(header);
                writer.newLine();

                String line;
                while ((line = reader.readLine()) != null) {
                    writer.write(line);
                    writer.newLine();
                }
            }
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            FileComparator fileComparator = new FileComparator();
            fileComparator.setVisible(true);
        });
    }
}

説明

  1. GUIの構築

    • JFrameを拡張して、ファイル比較ツールのウィンドウを作成します。
    • テキストフィールド(JTextField)を使用して、ユーザーがソースフォルダとターゲットフォルダのパスを入力できるようにします。
    • 結果を表示するためのテキストエリア(JTextArea)を配置し、スクロール可能にします。
  2. イベントハンドリング

    • 比較ボタン(JButton)にアクションリスナーを追加し、ボタンがクリックされたときにファイル比較処理を開始します。
    • ユーザーが入力したフォルダパスの有効性をチェックし、無効な場合はエラーメッセージを表示します。
  3. ファイル比較処理

    • 前述のコンソール版と同様に、フォルダ内のファイルをマップに格納し、並行処理で比較を行います。
    • 比較結果は、テキストエリアにリアルタイムで表示されます。

このGUI版ツールにより、ユーザーは対話的にフォルダパスを入力し、ファイル比較の結果を直感的に確認することができます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?