ブログのネタ切れ対策として、
以前に、
そのJavaプログラムのソースコードは見やすいように、
それは、以下の関数の中にある。
※昔は、
if (判断) {
…
}
と書いていたが、最近は、
if (判断)
{
…
}
と書く。その方が見やすいと思うので。
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;
}
何処かわかるだろうか?
それは if (path.length() > 3) の行。
次の行が int pos = path.indexOf("\\.\\"); で3文字との比較なので、
if (path.length() >= 3)
と path.length() > 3 を path.length() >= 3 に替えた方が正解だろう。
同様のバグが、関数 arrangePath2(String path) にもあった。
なお"\\.\\"が3文字というのは、'\n'(改行)
ただ2019年9月の記事に掲載した実行ログの関数arrang
*** ArrangingPath1 : C:\Tmp\java\work\work2\work3\.
*** ArrangingPath1 : C:\Tmp\java\work\work2\work3\.
*** ArrangingPath1 : C:\Tmp\java\work\work2\work3\.
*** ArrangingPath1 : C:\Tmp\java\work\work2\work3\.
とあるようにarrangePath1()
ログを見てもわかるように、arrangePath1()は、
再帰呼び出しとは上記のソースコードを見ればわかるように、
その呼び出し方を、上記のログに従って、引数とともに書くと、
arrangePath1(C:\Tmp\java\work\
|
+--arrangePath1(C:\Tmp\java\
|
+--arrangePath1(C:\Tmp\java\
|
+--arrangePath1(C:\Tmp\java\
|
+--arrangePath1(…) C:\Tmp\java\work\work2\work3\.
|
+--arrangePath1(…) C:\Tmp\java\work\work2\work3\.
|
+--arrangePath1(…) C:\Tmp\java\work\work2\work3\.
|
arrangePath1(…) C:\Tmp\java\work\work2\work3\.
となる。呼び出し側の引数から'\.'を1個ずつ減らしていき、
再帰呼び出しが理解出来ただろうか?
1980年代前半、
Z80 8bit CPU+CP/M OSではメモリは64Kbytes。
なおメモリが64Kbytesしかないのでプログラム自体が小規
Windows OSではスタック欠乏はまず発生しないが、
そのループ処理の関数arrangePath1l()は、
private static String arrangePath1l(String path)
{
System.out.println("*** ArrangingPath1l : " + path);
while (path.length() >= 3)
{
int pos = path.indexOf("\\.\\");
if (pos > 0)
{
path = path.substring(0, pos) +
path.substring(pos + 2, path.length());
System.out.println("*** Path1l-1 : " + path);
}
else
{
String temp = path.substring(path.length() - 2, path.length());
if (temp.startsWith("\\."))
{
path = path.substring(0, path.length() - 2);
System.out.println("*** Path1l-2 : " + path);
}
break;
}
}
return path;
}
再帰呼び出しの関数と比べて、ログ出力が2個増えた以外は、
プログラミング初心者はループ処理のソースコードの方が見やすい
while(判断) {…}、例えば while(i>=0) {…} は変数iが0より大きいか0に等しい場合に {…} を処理し繰り返す(ループ)という意味で、for(初期値; 判断; 更新)、例えば for(int i=10; i>=0; i--) {…} は整数変数iの初期値が10で変数iが0より大きいか0に等しい場合に {…} を処理してその後にiを1減らすことを繰り返すという意味。つまりfor文よりwhile文の方が簡単で簡潔。
勿論、for文を使いたくない訳ではなく、
このループ処理の関数では、breakを用いている点にも注目。
同様にループ処理に修正した関数String arrangePath2l()も含めて、ループ処理のログ出力のこれら2つの関数に関連した部分だけを以下に示そう。
C:\Tmp\java\work\work2\work3> java renameFiles5l .\..\.\.\.. > log.txt
*** ArrangingPath1l : C:\Tmp\java\work\work2\work3\.
*** Path1l-1 : C:\Tmp\java\work\work2\work3\.
*** Path1l-1 : C:\Tmp\java\work\work2\work3\.
*** Path1l-1 : C:\Tmp\java\work\work2\work3\.
*** ArrangingPath2l : C:\Tmp\java\work\work2\work3\.
*** Path2l : C:\Tmp\java\work\work2\..
*** Path2l : C:\Tmp\java\work
もう一つ。
C:\Tmp\java\work\work2\work3> java renameFiles5l ..\.\..\.\work5\. > log2.txt
*** ArrangingPath1l : C:\Tmp\java\work\work2\work3\.
*** Path1l-1 : C:\Tmp\java\work\work2\work3\.
*** Path1l-1 : C:\Tmp\java\work\work2\work3\.
*** Path1l-2 : C:\Tmp\java\work\work2\work3\.
*** ArrangingPath2l : C:\Tmp\java\work\work2\work3\.
*** Path2l : C:\Tmp\java\work\work2\..\
*** Path2l : C:\Tmp\java\work\work5
これらのログを見ると、
これらの関数を含むrenameFiles5lクラスのソースコ
勿論、私が書いたオリジナルプログラムなので、
このプログラムの詳しい使用方法は、
なおJava RuntimeとJDKはどのバージョンでも動作するはず。
言うまでもないが、
例えば特権モード(スーパーユーザ)
つまりこのプログラムは、サイバーテロにも使える。
勿論、suパスワードを知っていなければ無意味だが、
なおD:ドライブがUSBメモリの場合とかで、D:
ちなみにソフトウエア関連の仕事には、プログラマーの他にSE(
だから私は、SEになりたいとは最初から思ってないし、
才能のある人には天職があるが、
プログラミング自体は慣れれば誰でも出来る簡単な作業だが、
それにソフトウエア開発の各段階で一番面白いのは、
勿論、単なる趣味で始めたこのファイル名変更プログラムも、
また仕事で既存のプログラムの修正やデバッグを行う場合でも、
つまり、ソフトウエアはソースコードがすべて、
逆に言えば、完璧で見栄えがする設計資料があっても、
-------------------- Java renameFiles5lクラス -----------------------
import java.io.*;
import java.text.*;
class renameFiles5l
{
/**
* 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 = arrangePath1l(path);
path = arrangePath2l(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[
}
else
{
fileno = renameFilesInFolder(filelist[
}
}
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 arrangePath1l(String path)
{
System.out.println("*** ArrangingPath1l : " + path);
while (path.length() >= 3)
{
int pos = path.indexOf("\\.\\");
if (pos > 0)
{
path = path.substring(0, pos) +
path.substring(pos + 2, path.length());
System.out.println("*** Path1l-1 : " + path);
}
else
{
String temp = path.substring(path.length() - 2, path.length());
if (temp.startsWith("\\."))
{
path = path.substring(0, path.length() - 2);
System.out.println("*** Path1l-2 : " + path);
}
break;
}
}
return path;
}
/**
* Arrange Path for "\..".
*
* @param path path name.
* @return String path.
**/
private static String arrangePath2l(String path)
{
System.out.println("*** ArrangingPath2l : " + path);
while (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.
if (pos2 > 0)
{
pathupper = path.substring(0, pos2);
}
path = pathupper + pathlower;
System.out.println("*** Path2l : " + path);
}
else
{
break;
}
}
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);
}
}