ورود

View Full Version : خواندن یک شی از file



smokyshadow
دوشنبه 24 خرداد 1395, 10:56 صبح
سلام به دوستان
من نیاز دارم تو یه برنامه ای اطلاعات شی هایی رو ذخیره کنم بعد نوشتن چند شی رو در فایل بلدم ولی نمی دونم چه جوری یک شی خاص رو ازش بخونم(مثلا می خوام بگم اگه اسم یکی از شیا توی فایل برابر یه textfield بود یه کاری کنه و نکته دیگم ایه که نمی دونم این شیی که به صورت باینری ذخیره شده چطور اسمشو استفاده کنم؟)
این جوری فک کنین که یه فایل از شی های کلاس person داریم بعد می خوایم یه اسمی رو با همه ی اسمای اشیای ذخیره شده برابر بودنشو مقایسه کنیم؟جه جوری؟(من ObjectInputStream و ُSerialization و...رو می دونم ولی نمی دونم چطور بگم برو شی بعدی رو چک کن )
کسی که می خوانی لطفا اگه بلدی جواب بده:) (اگه جوابی میدید لطفا کامل توضیح بدید...)
ممنون

vahid-p
سه شنبه 25 خرداد 1395, 14:39 عصر
ابتدا مشخص کنید اندازه فایلتون بزرگه یا نه؟ (تعداد آبجکت ها زیادن یا نه)
اگر تعداد آبجکت ها خیلی زیاد نیست، اونها رو در یک ArrayList بریز و بعدش کل ArrayList رو در یک فایل قرار بده. موقع خوندن هم کل ArrayList رو بخون و تو ArrayList سرچ کن ببین اونی که میخوای هست یا نه.
اما اگر تعداد آبجکت ها زیادن و اینکه کل فایل به صورت یک ArrayList بیاری تو رم مورد نظر شما نیست، باید آبجکت ها رو یکی یکی بنویسی و به همون صورت بخونی که در ادامه برای چنین حالتی توضیح داده شده:

کلاس Person:

public class Person implements Serializable{
private String name;
private int age;
private String city;

public Person(String name, int age, String city){
this.name=name;
this.age=age;
this.city=city;
}


public String getName() {
return name;
}


public int getAge() {
return age;
}


public String getCity() {
return city;
}
}


در برنامه زیر اول چندین مقدار در فایل F.x قرار میدیم و بعد در تابع بعدی مقادیر رو میخونیم. برای خوندن از فایل هم همونطور که میبینید کافیه ois.readObject() رو صدا بزنیم و مقدارش رو Cast کنیم به Person. کلاس ObjectInputStream متدی برای تشخیص انتهای فایل نداشت و راهی جز استفاده از EOFException نبود. که البته خیلی روش خوبی نیست از Exception به این صورت استفاده کنیم.
(یک راه بهتر اینه شما اول فایل یک عدد قرار بدید که تعداد آبجکت های موجود درون فایل رو بهتون برگردونه. موقع خوندن اول readInt می کنید و بعد به اون تعدادی که بدست اومده می تونید readObject انجام بدید.)


public static void main(String[] args) {
write("F.x");
read("F.x");
}


public static void write(String fileName) {
Person person;
ObjectOutputStream writer = null;
try {
writer = new ObjectOutputStream(new FileOutputStream(fileName));
person = new Person("Ali", 20, "Tehran");
writer.writeObject(person);
person = new Person("Arash", 21, "Tabriz");
writer.writeObject(person);
person = new Person("Saeed", 22, "Shiraz");
writer.writeObject(person);
person = new Person("Mohammad", 23, "Mashhad");
writer.writeObject(person);
writer.flush();
} catch (IOException ex) {
System.err.println("Cannot write in file:" + fileName);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException ex) {
System.err.println("Cannot close file:" + fileName);
}
}
}
}


public static void read(String fileName) {
Person person;
ObjectInputStream reader = null;
try {
reader = new ObjectInputStream(new FileInputStream(fileName));
while (true) {
person = (Person) reader.readObject();
System.out.println("Name:" + person.getName() + ", Age:" + person.getAge() + ", City:" + person.getCity());
}
} catch (EOFException ex){
System.out.println("End of File");
} catch (IOException ex) {
System.err.println("Cannot read from file:" + fileName);
} catch (ClassNotFoundException ex) {
System.err.println(ex.getMessage());
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ex) {
System.err.println("Cannot close file:" + fileName);
}
}
}
}


اگر هم میخواید یک اسم رو جستجو کنید که خب تو حلقه while یک شرط میذاریم و یا پیدا میشه یا به EOF می رسیم که چنین اسمی وجود نداره:

public static boolean find(String fileName, String name) {
Person person;
ObjectInputStream reader = null;
try {
reader = new ObjectInputStream(new FileInputStream(fileName));
while (true) {
person = (Person) reader.readObject();
if (person.getName().equals(name)) {
System.out.println("Name:" + person.getName() + ", Age:" + person.getAge() + ", City:" + person.getCity());
return true;
}
}
} catch (EOFException ex) {
return false;
} catch (IOException ex) {
System.err.println("Cannot read from file:" + fileName);
} catch (ClassNotFoundException ex) {
System.err.println(ex.getMessage());
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ex) {
System.err.println("Cannot close file:" + fileName);
}
}
}
return false;
}

vahid-p
سه شنبه 25 خرداد 1395, 14:50 عصر
یه روش دیگه که میتونی انتهای فایل رو تشخیص بدی تو قسمت write قبل ()oos.flush بنویس writer.writeObject("EOF"); . پس اون قسمت میشه:
...
writer.writeObject(person);writer.writeObject("EOF");
writer.flush();
...
موقع خوندن قبل از Cast کردن کافیه چک کنی آبجکتی که خوندی از نوع Person است یا خیر، اگر نبود به آخر فایل رسیدیم ("EOF") و میتونیم حلقه رو break کنیم:
while (true) { obj = reader.readObject();
if (obj instanceof Person) {
person=(Person) obj;
System.out.println("Name:" + person.getName() + ", Age:" + person.getAge() + ", City:" + person.getCity());
}else{
break;
}
}

البته میتونی writer.writeObject(null) بنویسی و null بودن آبجکتی که میخونی رو چک کنی (نمیدونم این روش امن هست یا نه)

smokyshadow
سه شنبه 25 خرداد 1395, 18:04 عصر
یه روش دیگه که میتونی انتهای فایل رو تشخیص بدی تو قسمت write قبل ()oos.flush بنویس writer.writeObject("EOF"); . پس اون قسمت میشه:
...
writer.writeObject(person);writer.writeObject("EOF");
writer.flush();
...
موقع خوندن قبل از Cast کردن کافیه چک کنی آبجکتی که خوندی از نوع Person است یا خیر، اگر نبود به آخر فایل رسیدیم ("EOF") و میتونیم حلقه رو break کنیم:
while (true) { obj = reader.readObject();
if (obj instanceof Person) {
person=(Person) obj;
System.out.println("Name:" + person.getName() + ", Age:" + person.getAge() + ", City:" + person.getCity());
}else{
break;
}
}

البته میتونی writer.writeObject(null) بنویسی و null بودن آبجکتی که میخونی رو چک کنی (نمیدونم این روش امن هست یا نه)
سلام...
واقعا ممنون از وقتی که گذاشتید واقعا استادید در جاوا:لبخندساده: ولی راستش من به یه مشکل دبگه برخوردم اونم اینه که وقتی یه شی رو در فایل ذخیره می کنم وقتی برنامه رو می بندم دوباره run می کنم وقتی می خوام به اخر فایل شیی اضافه کنم دوباره یه فایل جدید میسازه یه که اطلاعات قبلی رو حفظ نمی کنه و نمی شه روش append کنیم.من البته برای این اطلاعات هر شی رو رو یه
فایل گذاشتم (با توجه به اینکه تعداد شی ها مثلا چیزی حدود 300 و400 تاست این کار خوبه هست...حجم برنامه رو زیاد نمیکنه ؟)
بعد شما راه مناسب تری برای ذخیره اشیا سراغ دارید؟

vahid-p
سه شنبه 25 خرداد 1395, 19:37 عصر
سلام...
واقعا ممنون از وقتی که گذاشتید واقعا استادید در جاوا
:لبخندساده:ولی راستش من به یه مشکل دبگه برخوردم اونم اینه که وقتی یه شی رو در فایل ذخیره می کنم وقتی برنامه رو می بندم دوباره run می کنم وقتی می خوام به اخر فایل شیی اضافه کنم دوباره یه فایل جدید میسازه یه که اطلاعات قبلی رو حفظ نمی کنه و نمی شه روش append کنیم.
نه بابا، اساتید کم پیدا شدن ما جولان میدیم
///
سعی کنید JavaDoc هر چیزی استفاده می کنید رو بخونید.
کلاس FileOutputStream چندین کانستراکتور داره که یکیش دو پارامتر میگیره که پارامتر دوم برای append کردنه.
برای این کانستراکتور در کلاس FileInputStream جاواداک میگه:

public FileOutputStream(String (http://barnamenevis.org/*1) name, boolean append) throws FileNotFoundException (http://barnamenevis.org/*2)



Creates a file output stream to write to the file with the specified name. If the second argument is true, then bytes will be written to the end of the file rather than the beginning. A new FileDescriptor object is created to represent this file connection.

First, if there is a security manager, its checkWrite method is called with name as its argument.

If the file exists but is a directory rather than a regular file, does not exist but cannot be created, or cannot be opened for any other reason then a FileNotFoundException is thrown.

Parameters:

name - the system-dependent file name
append - if true, then bytes will be written to the end of the file rather than the beginning


Throws:

FileNotFoundException (http://barnamenevis.org/*3) - if the file exists but is a directory rather than a regular file, does not exist but cannot be created, or cannot be opened for any other reason.
SecurityException (http://barnamenevis.org/*4) - if a security manager exists and its checkWrite method denies write access to the file.


Since:

JDK1.1
که به وضوح گفته:
append - if true, then bytes will be written to the end of the file rather than the beginning

پس شما کافیه پارامتر دوم رو true بذارید.


من البته برای این اطلاعات هر شی رو رو یه
فایل گذاشتم (با توجه به اینکه تعداد شی ها مثلا چیزی حدود 300 و400 تاست این کار خوبه هست...حجم برنامه رو زیاد نمیکنه ؟)
بعد شما راه مناسب تری برای ذخیره اشیا سراغ دارید؟
برای این تعداد اگر آبجکت هاتون حجیم نباشه، زیاد مهم نیست و سرعت کار حفظ میشه و محسوس نیست. حتی میتونی از همین ArrayList که گفتم استفاده کنید و کلش رو یه بار بخونی بیاری تو رم، تغییر خواستی بدی و دوباره همشو بنویسی تو فایل. لااقل ArrayList کار باهاش ساده تره. یا هم از همین روش پست دوم که باز چندان پیچیده نیست استفاده کن.

راه بهتر؟
دیتابیس. دیتابیس های مختلفی هستند که انتخابشون با خودتونه. که یک دیتابیس همراهی مثل H2 میتونه خیلی از نیازها رو به راحتی جوابگو باشه (تایپ OTHER رو ببینید=> ارجاع (http://www.h2database.com/html/datatypes.html)). بعضی دیتابیس ها مثل Mysql بهترن ولی ایرادی که داره باید به صورت جداگونه MySql راه اندازی بشه تا برنامه جاوات بتونه باهاش ارتباط برقرار کنه. ولی H2 خودش یه لایبرری جاواست که نیازی به این کار نداره (خب زیاد وارد بحث دیتابیس نشم، فقط میخواستم اشاره کنم و اگر میخواید کار کنید باید برید مباحثش رو با یک سرچ ساده پیدا کنید)