ورود

View Full Version : سوال: نحوه گرفتن نام جدید برای تغییر نام یک فایل



Sina.iRoid
شنبه 10 آبان 1393, 20:10 عصر
سلام دوستان. ممنون میشم اگر راهنماییم کنید.

من می خوام ابتدا نام یک فایل و از کاربر دریافت کنم و بعد از اینکه برنامه چک میکنه که اون آدرسی که دریافت شده یه فایل هست، نام جدید و از کاربر می خواد که وارد کنه تا اون فایل و rename کنه.

من در حالت کلی اینکار و می دونم چه طور باید انجام بدم. اما من دارم سعی می کنم که برنامه رو شی گرا بنویسم. یعنی یه کلاس جدا برای انجام عملیات rename کردن و یه کلاس برای دریافت ورودی از کاربرد. (من اصلا نمی خوام که داخل کلاسی که برای rename کردن ایجاد کردم، از کاربرورودی بگیرم). من کدم و به صورت زیر نوشتم اما نمیدونم که اشکال کار کجاست که شرط داخل دستور if اجرا نمیشه و هی نام فایل و از کاربر می خواد. ممنون میشم اگر راهنماییم کنید:

کد کلاس RenameFile:

import java.io.File;


import javax.swing.JOptionPane;




public class RenameFile {

private String firstFileName;
private String secondFileName;

//Constructor
public RenameFile(String firstFileName) {
setFirstFileName(firstFileName);

File mainFileName = new File(firstFileName);

if (mainFileName.isFile()) {

InputClass inputClass = new InputClass();
inputClass.secondFileName();

String mainFileNamePath = mainFileName.getParent();
File newFileName = new File(mainFileNamePath + "\\" + secondFileName);

mainFileName.renameTo(newFileName);
}else {
JOptionPane.showMessageDialog(null, "Sorry, your address does not a file.");
System.exit(0);
}
}

public RenameFile() {

}

//Getter and Setter
public String getMainFileName(){
return firstFileName;
}
public void setFirstFileName(String firstFileName){
this.firstFileName = firstFileName;
}
public String getSecondName(){
return secondFileName;
}
public void setSecondName(String secondName){
this.secondFileName = secondName;
}
}


کد کلاس InputClass:


import javax.swing.JOptionPane;


public class InputClass extends RenameFile{


//Constructor
public InputClass() {
super
(
JOptionPane.showInputDialog("Enter file name")
);
}

//method to get secondFileName
public void secondFileName(){

String newName = JOptionPane.showInputDialog("Enter new name");
setSecondName(newName);
}
}


و کد کلاس اصلی:

public class DriverClass {

public static void main(String[] args) {

new InputClass();
}
}


همانطور که مشاهده می کنید، خواستم که وقتی شرط if اجرا میشه، یه آبجکت از کلاس InputClass ساخته بشه و بعد با استفاده از اون آبجکت متدی که در کلاس InputClass هست اجرا بشه. اما اصلا این متد اجرا نمیشه.(خیلی در این مورد فک کردم اما به نتیجه نرسیدم).
ممنون میشم اگر راهنماییم کنید.

محمد فدوی
شنبه 10 آبان 1393, 23:08 عصر
میدونم این یه تمرینه اما ماهیت شیءگرایی تو این برنامه یه مقدار زیر سؤاله.
علاوه بر این، حتی شما اگه میخوای برای هر قسمت یه کلاس بنویسی خب ایرادی نداره. اما واقعا InputClass فرزند RenameClass هستش؟! بحث شیءگرایی یکم فلسفیه! باید تشخیص بدی رابطه‌ی این دوتا کلاس یه رابطه‌ی عرضیه یا طولی!! ولش کن! ولی یکم در مورد اصول شیءگرایی بخون.

اما در مورد ایراد برنامه‌ت، اولین ایراد اینه که برنامه‌ت رو انداختی توی دور (Loop)! شما وقتی InputClass رو فرزند RenameClass معرفی میکنی، یعنی موقع ساختن یه InputClass، سازنده‌ی RenameClass فراخوانی میشه. حالا شما اومدی توی سازنده‌ی RenameClass یه شیء از InputClass ساختی (خط ۲۲). این یعنی چی؟ یعنی برای ساخت این شیء باید سازنده‌ی RenameClass فراخوانی بشه و دوباره تو اون سازنده یه InputClass ساخته میشه که...! این یعنی برنامه توی دور بی‌نهایت (Infinity Loop) گیر افتاده.

می‌دونی باید چجوری پیاده‌سازیش کنی فقط یکم به شیءگرایی مسلط نیستی. یکم برنامه‌ت رو اصلاح کنی درست کار میکنه. اینو یادت میره که هر کلاس به خودی خود باید یه برنامه‌ی ساخت یافته باشه. شما میخوای همه‌ی کارا با ساختن اشیاء انجام شه! واسه همینه که متد main هم فقط کارش ساختن یک شیء شده! شیءگرایی موقعی کامل میشه که اشیاء از خودشون رفتار داشته باشن نه فقط حضور! برنامه تشکیل شده از یه سری شیء که یه سری افعال رو انجام میدن. نه اینکه حضورشون کاری رو انجام بده. خیلی فلسفی شد!

اگه نتونستی برنامه‌ت رو اصلاح کنی بگو تا کد اصلاح شدش رو بنویسم برات.

* به عنوان کاراکتر جدا کننده (Separator) توی برنامه‌نویسی Java به جای کاراکتر '\\' (Back Slash) از یکی از ثابت‌های File.separator یا File.separatorChar استفاده کن (فرقی باهم ندارن). یا اگه حوصلش رو نداری حداقل از کاراکتر '/' (Slash) استفاده کن.

Sina.iRoid
سه شنبه 13 آبان 1393, 12:52 عصر
سلام دوست عزیز.
ابتدا سپاس از شما که اینقدر عالی توضیح میدین.

در مورد برنامه من یه سری اصلاحاتی و انجام دادم اما این بار برنامه کرش می کنه. لطف کنید کدها رو یه نگاه کنید:

کد کلاس RenameClass:

import java.io.File;


public final class RenameClass {

private String firstName;
private String secondName;

//object from default constructor
InputOutputClass ioClassObj = new InputOutputClass();

//Constructor
public RenameClass() {
setFirstName(firstName);

File mainFileName = new File(firstName);

if (mainFileName.isFile()) {
String getParentMainFileName = mainFileName.getParent();

ioClassObj.secondFileName();

File secondFileName =
new File(getParentMainFileName + File.separator + getSecondName());

//rename file
mainFileName.renameTo(secondFileName);
} else {
ioClassObj.outputMessage();
}
}

//Getter And Setter
public String getFirstName(){
return firstName;
}
public void setFirstName(String firstName){
this.firstName = firstName;
}
public String getSecondName(){
return secondName;
}
public void setSecondName(String secondName){
this.secondName = secondName;
}
}


کد کلاس InputOutputClass:

import javax.swing.JOptionPane;


@SuppressWarnings("serial")
public class InputOutputClass extends JOptionPane{

//object from RenameClass
RenameClass renameClass = new RenameClass();

//Constructor
public InputOutputClass() {
renameClass.setFirstName(showInputDialog("Enter file name", "File Name"));
}

//input
public void secondFileName(){
renameClass.setSecondName(showInputDialog("Enter new file name", "File Name"));
}

//Output
public void outputMessage(){
showMessageDialog(null, "Sorry, your address does not a file.",
"Error", JOptionPane.ERROR_MESSAGE);
}
}

و این هم کد کلاس اصلی:


public class DriverClass {

public static void main(String[] args) {

new InputOutputClass();
}
}



همانطور که خود شما فرمودین این برنامه رو برای تمرین شی گرایی انجام میدم. وگرنه rename کردن و بلدم. در مورد کلاس main دقیقا چی باید توش بنویسیم؟ من اینطور خوندم که کلاس main فقط مسئول اجرای برنامست و بقیه کارها رو باید کلاس های دیگه انجام بدن. (و اینکه اگر امکانش هست فقط راهنماییم کنید چون می خوام خودم سعی کنم برنامه رو بنویسم.)
سپاس از شما.

محمد فدوی
سه شنبه 13 آبان 1393, 14:37 عصر
خواهش میکنم وظیفه‌ست. باشه فقط راهنمایی میکنم.
اول در مورد متن متد main حرف بزنم. خیلی در عمل تفاوتی نمیکنه اینجوری که الان نوشتید بنویسید یا اینجوری:


public static void main(String[] args) {
InputOutputClass inout = new InputOutputClass();


String filePath = inout.askForFilePath();
String newName = inout.askForNewName();


RenameClass renamer = new RenameClass(filePath, newName);
boolean success = rename.renameFile();


if(success) {
inout.outputSucceed();
} else {
inout.outputFailed();
}
}

اما فردی که کد بالا رو میخونه یه چیزایی دستش میاد و بعد میتونه مراحل رو ریز تر دنبال کنه. اما کد شما چی؟ وقتی متد main رو میخونیم هیچی نمیفهمیم! تازه بعد که بریم InputOutputClass رو بخونیم میبینیم توش حرف از یه کلاس دیگه ام زده شده به اسم RenameClass! بعد... یه اصطلاحی داریم تو برنامه‌نویسی به اسم کد اسپاگتی که کد مثل اسپاگتی در هم میپیچه و فهمش سخت میشه. معمولا این کد بر اثر استفاده از دستور goto بوجود میاد اما اگه حواسمون نباشه توی برنامه‌نویسی ساخت‌یافته/شیءگرا/ماژولار هم ممکنه به نقطه‌ای برسیم که توی کد گم شیم!
برنامه‌ی شما ساده‌ست و میشه فهمیدش اما از طرز کدنویسی بر میاد که اگه پیچیده‌تر بود با یه اسپاگتی خیلی خوب طرف بودیم!!
توی کدنویسی همیشه خودتو اول بذار جای کامپایلر و خط به خط کدت رو اجرا کن. بعد از اشکال یابی خودت رو بذار جای کسی که قراره کدت رو بخونه و سعی کن کارش رو راحت کنی. اینکار رو توی پروژه های بزرگ بصورت دوره‌ای و مقطعی باید انجام بدی تا توی کدت گم نشی.

الان من میخوام کدت رو اجرا کنم! هیچ نیازی هم به کامپایلر نیست.
کد متد main رو میخونم. خب میگه یه InputOutputClass بساز. میرم یدونه بسازم، توی خط هشتم این کلاس بم گفتی یدونه RenameClass بساز! خب ایرادی نداره میرم یدونه از این بسازم، که توی خط دهمش گفتی یدونه InputOutputClass بساز... الان من افتادم توی Infinity Loop. این یعنی هنوز ایراد قبلی که گرفتم از برنامه‌ت رفع نشده.

سعی کن اونطوری که متد main رو برات نوشتم ازش ایده بگیری و کلاس‌هات رو اونطوری تغییر بدی.
بطوری که کلاس RenameClass فقط کارش اینه که دو تا رشته بگیره و کاراش رو انجام بده... و بتونه بگه اینکار با موفقیت انجام شد یا نه.
همینطور کلاس InputOutputClass. این کلاسم فقط کارش اینه که میتونه یه سری چیزا از کاربر بگیره و بده تحویل یا یه چیزایی به کاربر بگه.
کلاس RenameClass هیچ اطلاعی از وجود کلاسی به اسم InputOutputClass نداره و همینطور بالعکس. کسی که بین این دوتا ارتباط و همکاری برقرار میکنه متد main هستش و اگه بعدا خواست میتونه خیلی ساده بین RenameClass و یه کلاس دیگه همکاری ایجاد کنه! این یعنی ساخت یافتگی. برنامه‌ی شما باید به چند زیر مسئله که کاملا از هم مستقلن تقسیم بشه (توی ریاضی میگن افراز بشه!)