この前東京湾を通った台風の強風も凄かったが、10月に入ってもこの暑さで、温暖化の効果恐るべし。国連で演説した少女も気持ちも理解できるというもの。

私は新聞をとってないが、ネット上の新聞社のサイトの有料会員登録をしている。

その新聞社を含めて新聞社関連のサイトには多数の写真が掲載されており、私もたまに覗いてざっと見ることがある。たいていは見るだけだが、なかにはどうしても自分のフォルダに保存しておきたいと思う写真に出会うことがある

そんな場合、写真を右クリックしてプルダウンメニューを表示しても"名前を付けて画像を保存"が出てこない。つまり新聞社のサイトでは著作権を考慮して写真の静止画ファイルを取り出せないような設定になっている。

ただ自分のパソコンで写真を表示したということは、その写真の静止画データそのものは既に自分のパソコンのストレージに存在することを意味する。でもブラウザからは取り出せないので、エクスプローラー(File Explorer)を使って取り出せばいい。

勿論、著作権を考慮して、ネットを含めて自分の機器以外には出さないようにするのは必須。

ネットで調べればすぐわかるが、WindowsではC:\Users\(ユーザ名)フォルダの下にAppDataという隠しフォルダがある。

エクスプローラーでローカルディスク(C:)からユーザー、自分の名前と辿ってカレントフォルダをC:\Users\(ユーザ名)としてアドレスバーの右の空白を2回クリックしてブルーバックを解除した後、\appdataとキー入力すると以下のフォルダに移行。

C:\Users\(ユーザ名)\AppData

もしユーザー名がNavafaなら、C:\Users\Navafa\AppData となる。

AppDataフォルダ下には、Local、LocalLow、Roamingという3つのフォルダがある。これらのフォルダを調べてお目当ての静止画ファイルを探せばいい

ブラウザがMicrosoft Edgeの場合、以下のフォルダにキャッシュデータを保存。

C:\Users\(ユーザ名)\AppData\Local\Packages\Microsoft.MicrosoftEdge_8wekyb3d8bbwe

だたこの下にも複数の隠しフォルダがあり目的のフォルダを探すのは困難。だからアドレスバーの右にある検索ボックスで、*.jpgと入力して静止画ファイルを探せばいい。お目当ての静止画ファイルが表示されない場合は、ファイル拡張子が.jpgでない場合もあるので、*.jpeg、*.*jpg、*.gif 等々色々試せばいいだろう。

そしてお目当ての静止画ファイルが見つかれば、自分のフォルダにコピー。

話が前後するが、保存しておきたい写真に出会った場合は、そのネットのアドレスをブックマークしておき、ブラウザのキャッシュデータを削除した後に、保存したブックマークを使って再度写真を呼び出す方が探すデータが少なくて効率的。

ブラウザのキャッシュデータを削除するには以下のフリーソフトがお勧め。

https://forest.watch.impress.co.jp/library/software/ccleaner/

このCCleanerには有料版もあるが無料版で十分だ。私はノートPCをシャットダウンする際は、必ずCCleanerでキャッシュデータを削除してから落とすようにしている。

私はMicrosoftのBingDesktopもインストールしている。BingDesktopは毎日壁紙が更新されるが、壁紙には綺麗な風景写真が多く残しておきたいと思うものも少なくない。その壁紙の静止画ファイルは以下のフォルダに当日を含めて9日間分が残っているので、取っておきたいファイルは自分のフォルダにコピーすればいい。

C:\Users\(ユーザ名)\AppData\Local\Microsoft\BingDesktop\themes

話をブラウザに戻して、私はMicrosoft製のブラウザはe-Taxにしか使わず、通常はGoogle Chromeを使っている。Google Chromeのキャッシュは以下のフォルダ。

C:\Users\(ユーザ名)\AppData\Local\Google\Chrome\User Data\Default\Cache

このフォルダには、index、data_0、data_1、data_2、data_3、f_00000a、f_00000b、f_00000c、…等のファイルがあるが、全て拡張子のないファイルになっている。

だからどれが静止画ファイルなのかわからない。エクスプローラーから手で拡張子の".jpg"を付加するしかない。経験上、index、data_0、data_1、data_2、data_3は静止画ファイルではない。静止画ファイルは比較的サイズが大きいのでエクスプローラーの表示を詳細に切り替えてファイルサイズを表示させ、f_00000a以降のファイルからサイズの大きめのファイルを選び拡張子を付加するしかない。

Shiftキーを押して左クリックすることで多数のファイルを指定し、右クリックから名前の変更を試みても、一度に多数のファイルへの拡張子の変更は出来ない仕様になっている。

手で一つずつファイルに拡張子を付ければいいのだが、手間がかかりすぎる。

そこで前回紹介したフォルダ単位でファイルの名称変更するJavaプログラムを修正し、拡張子がないファイルには自動的に拡張子".jpg"を付加することを思いついた。

そのプログラムがrenameFiles5.java。

このプログラムでは引数をさらに一つ追加して、拡張子がない場合につける拡張子を指定できるようにしている。勿論、指定がない場合のデフォルトは".jpg"で指定する場合"."は不要で、内部で付加する。

またファイル名変更する対象となる拡張子の".bmp"、".jpg"、".png"、".gif"以外の拡張子でも名称変更の対象にしたい場合の指定も、新たな引数で可能になる。勿論、ソースコードがあるのでソースコードを修正してコンパイルし直すのが一番手っ取り早いが、コマンドで指定する機能も持たせたということ。

結局、拡張子を指定する引数には二つの意味があるわけで、本来は引数を二つ追加する必要があるが、煩雑なので追加の引数は一つとした。従って状況により使い分ければいい。

プログラム内部では拡張子の比較を小文字ベースで行っているから、その拡張子で再び名称変更する場合を考えると拡張子の引数は小文字で指定する方がいい。

最終的にrenameFiles5の引数は、フォルダ名、ファイル番号、拡張子の順に指定。

そのファイル番号だが、元々指定したフォルダの下層フォルダを含めた通し番号のつもりだったが、フォルダ毎にファイル番号を1にリセットする方が一般的な気がする。そこでファイル番号に0を指定すればフォルダ毎にファイル番号を1にリセットすることにした。デフォルト値は0で、1以上を指定すればその番号からの通し番号とする。拡張子は上記で説明したようにファイル名変更の対象拡張子と拡張子がない場合の追加拡張子。勿論、ファイル番号と拡張子は省略可能。

なお新旧二つの拡張子を指定してファイル名は変更せずに拡張子だけフォルダごと変更するプログラム(class renameExts1)もこのソースコードから作成済み。こちらの内部処理では旧拡張子は小文字に変換せずそのまま比較。新拡張子も同様。

興味がある人には各ソースコードを読んでもらうことにして、最後にrenameFiles5とrenameExts1の使い方を説明しよう。

以下のサイトから、多数の写真家のきれいな写真を見ることができる。
https://www.sony.jp/ichigan/a-universe/special_a7RM3/

それらの写真を右クリックして、プルダウンメニューから名前を付けて画像を保存することは可能だが、写真家の中には十枚以上の写真が掲載されているものもあり、一枚ずつファイルに保存するのは面倒。そこでrenameFiles5やrenameExts1の出番

手順は以下の通り。

1. Google Chromeで上記のサイトをブックマークする。

2. CCleanerを実行してGoogle Chromeのキャッシュデータをクリアする。

3. Chromeで上記のサイトを表示し好みの写真家を選んでその写真が全て表示されていることを確認した後、Chromeを終了する。

4. Windowsコマンドプロンプト(cmd.exe)を起動しカレントフォルダをC:\Tmp\javaに移動する。

5. cmd.exeから以下のコマンドを実行する。

java renameFiles5 "C:\Users\(ユーザ名)\AppData\Local\Google\Chrome\User Data\Default\Cache"

Chrome Cacheフォルダは"User Data"のように半角空白(0x20)を含む部分があるので、ダブルクォート(")で囲むのは必須。

6. エクスプローラーでChrome Cacheフォルダを表示する。その際に、表示方式を   大アイコンに変更すると写真の場合はアイコンが写真に変わるので、その状態で写真ファイルを確認。Ctrlキーを押しながら左クリックで写真ファイルだけをブルーバック状態にしてもいいが、写真以外の不要なファイルを削除していき写真ファイルだけを残す方が簡単。

7. あとは残った写真ファイルを自分のPicturesフォルダの下に適当なフォルダを作成して移動するだけ。勿論、そのフォルダ内で残したい写真ファイルだけを厳選し、renameFiles5を再度使ってファイル名とファイル番号を付け直してもいい。ファイル名を付け直す場合にファイル名とファイル番号が重なりエラーが発生する場合があるが、その場合はファイル番号を最終のファイル番号よりも大きな数字、例えば、200枚の写真が1つのフォルダにあれば、ファイル番号に1000を指定して一旦すべてのファイル名とファイル番号を付け替えた後に、ファイル番号を指定せずにもう一度起動するとファイル番号が1から始まる状態にもっていける。

renameFiles5の代わりにrenameExts1を使う場合は、以下のコマンドを実行する。

java renameExts1 "" jpg "C:\Users\(ユーザ名)\AppData\Local\Google\Chrome\User Data\Default\Cache"

renameExts1の引数は、renameExts1 旧拡張子 新拡張子 フォルダ名 の順に指定。これは拡張子が何もない("")ファイルに拡張子(".jpg")を付加する指定となる。

以下のその逆の指定は、拡張子".jpg"がついたファイルからその拡張子を削除。

java renameExts1 jpg "" "C:\Users\(ユーザ名)\AppData\Local\Google\Chrome\User Data\Default\Cache"

以下の指定は、拡張子".jpg"を大文字の".JPG"に変更する。

java renameExts1 jpg JPG "C:\Users\(ユーザ名)\AppData\Local\Google\Chrome\User Data\Default\Cache"

なお私はChrome CacheとBingDesktop themesの2つのフォルダはショートカットを作成しているので、ショートカットで起動されるエクスプローラーのアドレスバーからコピペすればコマンドプロンプトにChrome Chacheフォルダを簡単に入力可能。

また各写真にコメントを付加したい場合は、その写真にカーソルを合わせて右クリックして表示されるプルダウンメニューからプロパティを起動しその詳細タブからタイトルの項目に任意の文字列を入力可能。全角でも数十文字分のコメントを付加できるはず。

私は若い頃アセンブラ言語とC言語のプログラミングで給料をもらっていた。言語がJavaに変わってもこの程度の簡単なプログラムなら、62歳になった今でも容易に作成及び修正できて当然だろう。

私の印象では、JavaはBASICとCの長所をあわせたような言語。

------------------- renameFiles5.java ------------------------------------
import java.io.*;
import java.text.*;

class renameFiles5
{
    /**
     * Rename picture files in folder main.
     *
     * @param args[0] folder name.
     * @param args[1] file number.
     * @param args[2] extension name.
     * @return void.
     **/
    public static void main(String[] args)
    {
        try
        {
            File fileobj;
            int fileno = 0;
            String extname =".jpg";

            if (args.length > 0)
            {
                fileobj = new File(args[0]);
                if (args.length > 1)
                {
                    fileno = Integer.parseInt(args[1]);
                    if (args.length > 2)
                    {
                        extname = "." + args[2];
                    }
                }
            }
            else
            {
                fileobj = new File(".");
            }

            String path = fileobj.getAbsolutePath();
            path = arrangePath1(path);
            path = arrangePath2(path);
            fileobj = new File(path);

            renameFilesInFolder(fileobj, fileno, extname);
        }
        catch (Exception e)
        {
            printError(e);
            System.out.println("Usage: java renameFiles5 [FolderName, [FileNo, [ExtName]]]");
        }
    }

    /**
     * Rename picture files in folder function.
     * picture file types are bmp, jpg, png and gif.
     *
     * @param fileobj File class instance.
     * @param fileno  file number.
     * @param extname extension name.
     * @return fileno file number.
     **/
    private static int renameFilesInFolder(File fileobj, int fileno, String extname)
    {
        try
        {
            boolean reset = false;
            if (fileno <=0)
            {
                reset = true;
                fileno = 1;
            }

            String path = fileobj.getAbsolutePath();
            System.out.println("*** AbsolutePath : " + path);

            int pos = searchBackSlash(path);
            if (fileobj.isDirectory())
            {
                String folder = path.substring(pos + 1, path.length());

                File[] filelist = fileobj.listFiles();
                for (int i = 0; i < filelist.length; i++)
                {
                    if (filelist[i].isDirectory())
                    {
                        if(reset)
                        {
                            renameFilesInFolder(filelist[i], 0, extname);
                        }
                        else
                        {
                            fileno = renameFilesInFolder(filelist[i], fileno, extname);
                        }
                    }
                    else
                    {
                        if (renameFile(filelist[i], path, folder, fileno, extname))
                        {
                            fileno++;
                        }
                    }
                }
            }
            else
            {
                path = path.substring(0, pos);
                pos = searchBackSlash(path);
                String folder = path.substring(pos + 1, path.length());

                if (renameFile(fileobj, path, folder, fileno, extname))
                {
                    fileno++;
                }
            }
        }
        catch (Exception e)
        {
            printError(e);
        }

        return fileno;
    }

    /**
     * Rename picture file.
     * picture file types are bmp, jpg, png and gif.
     *
     * @param fileobj  File class instance.
     * @param path     path name.
     * @param folder   folder name.
     * @param fileno   file number.
     * @param extname  extension name.
     * @return boolean true(success) or false(failure).
     **/
    private static boolean renameFile(File fileobj, String path, String folder, int fileno, String extname)
    {
        try
        {
            String name = fileobj.getName();
            for (int i = name.length() - 1; i >= 0 ; i--)
            {
                String temp = name.substring(i, i + 1);
                if (temp.startsWith("."))
                {
                    String ext = name.substring(i, name.length());
                    ext = ext.toLowerCase();
                    if (ext.startsWith(".bmp") || ext.startsWith(".jpg") || ext.startsWith(".png") ||
                        ext.startsWith(".gif") || ext.startsWith(extname))
                    {
                        return renameFileOnly(fileobj, path, folder, fileno, ext);
                    }
                    return false;
                }
            }
            return renameFileOnly(fileobj, path, folder, fileno, extname);
        }
        catch (Exception e)
        {
            printError(e);
        }

        return false;
    }


    /**
     * Rename picture file only.
     *
     * @param fileobj  File class instance.
     * @param path     path name.
     * @param folder   folder name.
     * @param fileno   file number.
     * @param extname  extension name.
     * @return boolean true(success) or false(failure).
     **/
    private static boolean renameFileOnly(File fileobj, String path, String folder, int fileno, String extname)
   {
        try
        {
            String name = fileobj.getName();

            DecimalFormat noformat = new DecimalFormat("0000");
            String newname = new String(path + "\\" + folder + "-" + noformat.format(fileno) + extname);
            File newfile = new File(newname);
            if (fileobj.renameTo(newfile))
            {
                System.out.println("Rename Success.: " + name + " -> " + newname);
                return true;
            }
            else
            {
                System.out.println("Rename Failure!: " + name + " -> " + newname);
            }
        }
        catch (Exception e)
        {
            printError(e);
        }

        return false;
    }

    /**
     * Arrange Path for "\.".
     *
     * @param path path name.
     * @return String path.
     **/
    private static String arrangePath1(String path)
    {
        System.out.println("*** ArrangingPath1 : " + path);

        if (path.length() > 3)
        {
            int pos = path.indexOf("\\.\\");
            if (pos > 0)
            {
                return arrangePath1(path.substring(0, pos) +
                                    path.substring(pos + 2, path.length()));
            }
            else
            {
                String temp = path.substring(path.length() - 2, path.length());
                if (temp.startsWith("\\."))
                {
                    return path.substring(0, path.length() - 2);
                }
            }
         }

         return path;
    }

    /**
     * Arrange Path for "\..".
     *
     * @param path path name.
     * @return String path.
     **/
    private static String arrangePath2(String path)
    {
        System.out.println("*** ArrangingPath2 : " + path);

        if (path.length() > 3)
        {
            int pos = path.indexOf("\\..");
            if (pos > 0)
            {
                String pathlower = "";
                if (path.length() > pos + 3)
                {
                    pathlower = path.substring(pos + 3, path.length());
                }

                String pathupper = "";
                int pos2 = searchBackSlash(path.substring(0, pos));
                if (pos2 > 0)
                {
                    pathupper = path.substring(0, pos2);
                }

                return arrangePath2(pathupper + pathlower);
            }
         }

         return path;
    }

    /**
     * Search '\' character in path form path tail.
     *
     * @param path path name.
     * @return int position of '\'.
     **/
    private static int searchBackSlash(String path)
    {
        for (int i = path.length() - 1; i >= 0 ; i--)
        {
            String temp = path.substring(i, i + 1);
            if (temp.startsWith("\\"))
            {
                return i;
            }
        }
        return -1;
    }

    /**
     * Print Error.
     *
     * @param e exception.
     * @return void.
     **/
    private static void printError(Exception e)
    {
        System.out.println("Error!: " + e);
    }
}