Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

ElectronでFileのOpenとSave

More than 1 year has passed since last update.

Electronでファイル操作する必要があったのでOpenとSaveの方法をメモ。

dialogの制御方法が知りたいのが主目的なので、ロジックはなし。
csvを読み込み表示。そのままsaveする。

仕様

下記のような感じ。

  • openボタンを押すとファイオープンし、textareaに表示。
  • saveでtextarea内の内容をfileにSave。

スクリーンショット 2019-01-27 7.14.03.png

textarea内を変更しても内容はファイルには反映されない。それをやるにはVueとかReact使う。

実装

package.json

エンドポイントはmain.jsとしました。

package.json
{
  "name": "openclose",
  "version": "1.0.0",
  "description": "sample",
  "main": "main.js",
  "scripts": {
    "start": "electron ."
  },
  "devDependencies": {
    "electron": "^4.0.2"
  }
}

main.js

ElectronのQuick Startのmain.jsとほぼ一緒。
起動時の表示としてindex.htmlを呼び出している。

main.js
const { app, BrowserWindow } = require('electron')

let win

function createWindow() {

    //ウインドウの作成
    win = new BrowserWindow({ width: 800, height: 400 })

    //ウインドウに表示する内容
    win.loadFile('index.html')

    //デバッグ画面表示
    // win.webContents.openDevTools()

    //このウインドウが閉じられたときの処理
    win.on('closed', () => {
        win = null
    })
}

//アプリが初期化されたとき(起動されたとき)
app.on('ready', () => {
    createWindow()
})

//全ウインドウが閉じられたとき
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        app.quit()
    }
})

//アクティブになったとき(MacだとDockがクリックされたとき)
app.on('activate', () => {
    if (win === null) {
        createWindow()
    }
})

index.html

画面要素を配置。ロジックを実装するindex.jsとstyles.cssを呼び出している。

index.html
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>sample</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <h3>File Open/Save</h3>
    <button id="openFile">Open</button>
    <button id="saveFile">Save</button>
    <br>
    <textarea id="preview"></textarea>
    <script src="index.js"></script>
</body>
</html>

index.js

ここにいろいろ書く。やってることは、

  • OpenDialogで開くファイル名(Path)を取得し、その情報を利用してファイルをオープン。
  • SaveDialogで保存するファイル名(Path)を取得して、その情報を利用してファイルをSave。
index.js
const fs = require('fs');
const { BrowserWindow, dialog } = require('electron').remote;

//html内の要素取得とリスナーの設定
document.querySelector("#openFile").addEventListener('click', () => {
    openFile();
})

document.querySelector("#saveFile").addEventListener('click', () => {
    saveFile();
})

const preview = document.getElementById('preview');

//openFileボタンが押されたとき(ファイル名取得まで)
function openFile() {
    const win = BrowserWindow.getFocusedWindow();
    dialog.showOpenDialog(
        win,
        {
            properties: ['openFile'],
            filters: [
                {
                    name: 'Document',
                    extensions: ['csv', 'txt']
                }
            ]
        },
        (fileNames) => {
            if (fileNames) {
                // alert(fileNames[0]);
                readFile(fileNames[0]); //複数選択の可能性もあるので配列となる。
            }
        }
    )
}

//指定したファイルを読み込む
function readFile(path) {
    fs.readFile(path, (error, data) => {
        if (error != null) {
            alert("file open error.");
            return;
        }
        preview.textContent = data.toString();
    })
}

//saveFileボタンが押されたとき
function saveFile() {
    const win = BrowserWindow.getFocusedWindow();
    dialog.showSaveDialog(
        win,
        {
            properties: ['openFile'],
            filters: [
                {
                    name: 'Documents',
                    extensions: ['csv', 'txt']
                }
            ]
        },
        (fileName) => {
            if (fileName) {
                const data = preview.textContent;
                console.log(data);
                writeFile(fileName, data);
            }
        }
    )
}

//fileを保存(Pathと内容を指定)
function writeFile(path, data) {
    fs.writeFile(path, data, (error) => {
        if (error != null) {
            alert("save error.");
            return;
        }
    })
}

styles.css

まあ、おまけ程度ですが、いちおう。

styles.css
#preview{
    margin-top: 20px;
    width: 300px;
    height: 100px;
}
zaburo
こんにちは。自分用のメモをだらだら公開しています。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away