Skip to content

4. کلاس‌های پرکاربرد

در این فصل، تعدادی از کلاس‌های پرکاربرد جاوا را معرفی می‌کنیم. این کلاس‌ها دارای ویژگی‌ها، متدها و سازنده‌های متعددی هستند. در هر مورد، تنها نمونه‌ای کوچک از این کلاس‌ها را ارائه می‌دهیم. جزئیات بیشتر در بخش راهنمای جاوا موجود است که اکنون آن را معرفی خواهیم کرد.

4.1. مستندات

اگر JDK شرکت Sun را در پوشه <jdk> نصب کرده باشید، مستندات در پوشه <jdk>\docs موجود است:

Image

گاهی ممکن است یک فایل jdk داشته باشید اما هیچ مستنداتی وجود نداشته باشد. این مستندات را می‌توانید در وب‌سایت Sun به آدرس http://www.sun.com پیدا کنید. در پوشه docs، فایلی به نام index.html وجود دارد که نقطه شروع راهنمای JDK است:

Image

Image

لینک «API & Language» در بالا دسترسی به کلاس‌های جاوا را فراهم می‌کند. لینک «Demos/Tutorials» به‌ویژه برای یافتن نمونه‌هایی از برنامه‌های جاوا مفید است. بیایید لینک «API & Language» را دنبال کنیم:

Image

بیایید لینک Java 2 Platform API را دنبال کنیم:

Image

این صفحه نقطهٔ شروع واقعی مستندات کلاس است. می‌توانید برای دسترسی سریع یک میانبر به آن ایجاد کنید. URL در <jdk>\docs\api\index.html قرار دارد. این صفحه نقطه شروع واقعی مستندات کلاس است. می‌توانید برای دسترسی سریع یک میانبر به آن ایجاد کنید. URL در <jdk>\docs\api\index.html قرار دارد. بیایید یک مثال بزنیم و به دنبال اطلاعات در مورد کلاس Vector بگردیم که یک آرایه پویا را پیاده‌سازی می‌کند. به سادگی در لیست کلاس‌ها در پنل سمت چپ به دنبال آن بگردید.

بیایید یک مثال بزنیم و به دنبال اطلاعات درباره کلاس Vector بگردیم که یک آرایه پویا را پیاده‌سازی می‌کند. به سادگی در لیست کلاس‌ها در پنل سمت چپ به دنبال لینک کلاس Vector بگردید:

Image

و روی لینک کلیک کنید تا تعریف کلاس را مشاهده کنید:

Image

در اینجا خواهید یافت

  • سلسله‌مراتبی که کلاس در آن قرار دارد، در این مورد java.util.Vector
  • فهرست فیلدها (ویژگی‌ها) برای کلاس
  • فهرست سازنده‌ها
  • فهرست متدها

اکنون کلاس‌های مختلفی را ارائه خواهیم داد. از خواننده دعوت می‌کنیم تا به‌طور سیستماتیک تعریف کامل کلاس‌های مورد استفاده را بررسی کند.

4.2. کلاس‌های آزمایشی

مثال‌های زیر گاهی از کلاس‌های personne و enseignant استفاده می‌کنند. ما تعاریف آن‌ها را در اینجا ارائه می‌دهیم.

public class personne{
    // نام خانوادگی، نام، سن
  private String prenom;
  private String nom;
  private int age;

  // سازنده ۱
  public personne(String P, String N, int age){
    this.prenom=P;
    this.nom=N;
    this.age=age;
  }

   // سازنده ۲
  public personne(personne P){
    this.prenom=P.prenom;
    this.nom=P.nom;
    this.age=P.age;
  }

  // toString
  public String toString(){
    return "personne("+prenom+","+nom+","+age+")";
  }

  // دسترسی‌یافتگان
  public String getPrenom(){
    return prenom;
  }
  public String getNom(){
    return nom;
  }
  public int getAge(){
    return age;
  }

  //تعدیل‌کننده‌ها
  public void setPrenom(String P){
    this.prenom=P;
  }
  public void setNom(String N){
    this.nom=N;
  }
  public void setAge(int age){
    this.age=age;
  }
}

کلاس enseignant از کلاس personne مشتق شده و به شرح زیر تعریف می‌شود:

class enseignant extends personne{
// ویژگی‌ها
  private int section;

    // سازنده
  public enseignant(String P, String N, int age,int section){
    super(P,N,age);
    this.section=section;
  }
    // toString
  public String toString(){
    return "etudiant("+super.toString()+","+section+")";    
  }
}

ما همچنین از کلاسی به نام etudiant که از کلاس personne مشتق شده و به صورت زیر تعریف شده است، استفاده خواهیم کرد:


class etudiant extends personne{
  String numero;

  public etudiant(String P, String N, int age,String numero){
    super(P,N,age);
    this.numero=numero;
  }

  public String toString(){
    return "etudiant("+super.toString()+","+numero+")";    
  }    
}

4.3. کلاس String

کلاس String نمایانگر رشته‌های کاراکتری است. فرض کنید nom یک متغیر رشتهٔ کاراکتری باشد:

String name;

nom یک مرجع به شی‌ای است که هنوز مقداردهی نشده است. این مرجع را می‌توان به دو روش مقداردهی کرد:

name = "horse" یا name = new String("horse")

هر دو روش معادل هستند. اگر بعداً name=&quot;fish&quot; را بنویسیم، nom به یک شیء جدید اشاره خواهد کرد. شیء قدیمی String(&quot;cheval&quot;) از بین می‌رود و حافظه‌ای که اشغال کرده بود بازیابی خواهد شد.

کلاس String دارای طیف گسترده‌ای از ویژگی‌ها و متدها است. در اینجا به چند مورد از آن‌ها اشاره می‌شود:

public char charAt(int i)
حرف i را از رشته بازمی‌گرداند، جایی که اولین حرف شاخص 0 دارد. بنابراین، String("horse").charAt(3) برابر با 'v' است
public int compareTo(string2)
chaine1.compareTo(string2) رشته1 را با رشته2 مقایسه می‌کند و در صورتی که رشته1 = رشته2 باشد 0، در صورتی که رشته1 > رشته2 باشد 1، و در صورتی که رشته1 < رشته2 باشد -1 را برمی‌گرداند.
public boolean equals(Object anObject)
chaine1.equals(string2) در صورتی که string1 = string2 مقدار true و در غیر این صورت مقدار false را برمی‌گرداند
public String toLowerCase()
chaine1.toLowerCase() رشتهٔ string1 را به حروف کوچک تبدیل می‌کند
public String toUpperCase()
chaine1.toUpperCase() رشتهٔ string1 را به حروف بزرگ تبدیل می‌کند
public String trim()
chaine1.trim() فاصله‌های ابتدایی و انتهایی را از string1 حذف می‌کند
public String substring(int beginIndex, int endIndex)
String("chapeau").subString(2,4) رشته "ape" را برمی‌گرداند
public char[] toCharArray()
امکان قرار دادن کاراکترهای رشته در یک آرایهٔ کاراکتری را فراهم می‌کند
تعداد کاراکترهای رشته
تعداد کاراکترهای رشته
int indexOf(String string2)
اولین رخداد chaine2 را در رشتهٔ جاری بازمی‌گرداند، یا در صورتی که chaine2 وجود نداشته باشد، مقدار -1 را برمی‌گرداند
int indexOf(String string2, int startIndex)
اولین وقوع chaine2 را در رشتهٔ جاری بازمی‌گرداند، یا در صورت عدم وجود chaine2 مقدار -1 را برمی‌گرداند. جستجو از کاراکتر با شماره startIndex آغاز می‌شود.
int lastIndexOf(String string2)
آخرین موقعیت chaine2 را در رشتهٔ جاری بازمی‌گرداند، یا در صورتی که chaine2 وجود نداشته باشد، مقدار -1 را برمی‌گرداند
boolean startsWith(String string2)
اگر رشتهٔ جاری با chaine2 شروع شود، مقدار true را برمی‌گرداند
boolean endsWith(String string2)
اگر رشتهٔ فعلی با chaine2 پایان یابد، مقدار true را برمی‌گرداند.
boolean matches(String regex)
در صورتی که رشتهٔ جاری با عبارت منظم regex مطابقت داشته باشد، مقدار true را برمی‌گرداند.
String[] split(String regex)
رشتهٔ فعلی از فیلدهایی تشکیل شده است که با رشته‌ای از کاراکترها که توسط عبارت منظم regex مطابقت داده شده‌اند، از هم جدا شده‌اند. متد split فیلدها را در یک آرایه بازیابی می‌کند.
String replace(char oldChar, char newChar)
کاراکتر oldChar را در رشتهٔ جاری با کاراکتر newChar جایگزین می‌کند.

در اینجا یک برنامهٔ نمونه آورده شده است:

// واردات‌ها
import java.io.*;

public class string1{
    // یک کلاس نمایشی
    public static void main(String[] args){
        String uneChaine="l'oiseau vole au-dessus des nuages";
        affiche("uneChaine="+uneChaine);
        affiche("uneChaine.Length="+uneChaine.length());
        affiche("chaine[10]="+uneChaine.charAt(10));
        affiche("uneChaine.IndexOf(\"vole\")="+uneChaine.indexOf("vole"));
        affiche("uneChaine.IndexOf(\"x\")="+uneChaine.indexOf("x"));
        affiche("uneChaine.LastIndexOf('a')="+uneChaine.lastIndexOf('a'));
        affiche("uneChaine.LastIndexOf('x')="+uneChaine.lastIndexOf('x'));
        affiche("uneChaine.substring(4,7)="+uneChaine.substring(4,7));
        affiche("uneChaine.ToUpper()="+uneChaine.toUpperCase());
        affiche("uneChaine.ToLower()="+uneChaine.toLowerCase());
        affiche("uneChaine.Replace('a','A')="+uneChaine.replace('a','A'));
        String[] champs=uneChaine.split("\\s+");
        for (int i=0;i<champs.length;i++){
            affiche("champs["+i+"]=["+champs[i]+"]");
        }//برای
        affiche("(\"  abc  \").trim()=["+"  abc  ".trim()+"]");
    }//اصلی

  //نمایش می‌دهد
    public static void affiche(String msg){
        // پیام را نمایش می‌دهد
        System.out.println(msg);
    }//نمایش می‌دهد
}//کلاس

و نتایج حاصل:

uneChaine=l'oiseau vole au-dessus des nuages
uneChaine.Length=34
chaine[10]=o
uneChaine.IndexOf("vole")=9
uneChaine.IndexOf("x")=-1
uneChaine.LastIndexOf('a')=30
uneChaine.LastIndexOf('x')=-1
uneChaine.substring(4,7)=sea
uneChaine.ToUpper()=L'OISEAU VOLE AU-DESSUS DES NUAGES
uneChaine.ToLower()=l'oiseau vole au-dessus des nuages
uneChaine.Replace('a','A')=l'oiseAu vole Au-dessus des nuAges
champs[0]=[l'oiseau]
champs[1]=[vole]
champs[2]=[au-dessus]
champs[3]=[des]
champs[4]=[nuages]
("  abc  ").trim()=[abc]

4.4. کلاس Vector

یک بردار یک آرایه پویا است که عناصر آن ارجاع به اشیاء هستند. بنابراین این یک آرایه از اشیاء است که اندازه آن می‌تواند در طول زمان تغییر کند، امری که با آرایه‌های ایستا که تاکنون با آن‌ها مواجه شده‌ایم امکان‌پذیر نیست. در اینجا برخی از فیلدها، سازندها و متدهای این کلاس آورده شده است:

public Vector()
یک بردار خالی ایجاد می‌کند
public final int size()
تعداد عناصر در بردار
public final void addElement(Object obj)
شیء مرجع obj را به وکتور اضافه می‌کند
public final Object elementAt(int index)
اشاره به عنصر شماره index در آرایه – شاخص‌ها از 0 شروع می‌شوند
public final Enumeration elements()
مجموعه عناصر در بردار را به صورت یک شمارش‌گر
public final Object firstElement()
اشاره به عنصر اول آرایه
public final Object lastElement()
اشاره به آخرین عنصر آرایه
public final boolean isEmpty()
در صورتی که آرایه خالی باشد، مقدار true را برمی‌گرداند
public final void removeElementAt(int index)
عنصر با ایندکس را حذف می‌کند
public final void removeAllElements()
آرایه را از تمام عناصرش پاک می‌کند
public final String toString()
یک رشته را بازمی‌گرداند که آرایه را شناسایی می‌کند

در اینجا یک برنامه آزمایشی آمده است:


//کلاس‌های واردشده
import java.util.*;

public class test1{

// برنامهٔ اصلی: main – static – متد کلاس

  public static void main(String arg[]){

//ایجاد اشیاء نمونه کلاس
    personne p=new personne("Jean","Dupont",30);
    enseignant en=new enseignant("Paula","Hanson",56,27);
    etudiant et=new etudiant("Chris","Garot",22,"19980405");
    System.out.println("p="+p.toString());
    System.out.println("en="+en.toString());
    System.out.println("et="+et.toString());

// چندریختی
    personne p2=(personne)en;
    System.out.println("p2="+p2.toString());
    personne p3=(personne)et;
    System.out.println("p3="+p3.toString());

//یک بردار
    Vector V=new Vector();
    V.addElement(p);V.addElement(en);V.addElement(et);
    System.out.println("Taille du vecteur V = "+V.size());
    for(int i=0;i<V.size();i++){
      p2=(personne) V.elementAt(i);
      System.out.println("V["+i+"]="+p2.toString());
    }
} // پایان برنامه اصلی
}// پایان کلاس

بیایید این برنامه را کامپایل کنیم:

E:\data\serge\JAVA\poly juin 2002\Chapitre 3\vector>dir
10/06/2002  10:41                1 134 personne.class
10/06/2002  10:41                  619 enseignant.class
10/06/2002  10:41                  610 etudiant.class
10/06/2002  10:42                1 035 test1.java
E:\data\serge\JAVA\poly juin 2002\Chapitre 3\vector>javac test1.java

E:\data\serge\JAVA\poly juin 2002\Chapitre 3\vector>dir
10/06/2002  10:41                1 134 personne.class
10/06/2002  10:41                  619 enseignant.class
10/06/2002  10:41                  610 etudiant.class
10/06/2002  10:42                1 035 test1.java
10/06/2002  10:43                1 506 test1.class

بیایید فایل test1.class را اجرا کنیم:

E:\data\serge\JAVA\poly juin 2002\Chapitre 3\vector>java test1
p=personne(Jean,Dupont,30)
en=etudiant(personne(Paula,Hanson,56),27)
et=etudiant(personne(Chris,Garot,22),19980405)
p2=etudiant(personne(Paula,Hanson,56),27)
p3=etudiant(personne(Chris,Garot,22),19980405)
Taille du vecteur V = 3
V[0]=personne(Jean,Dupont,30)
V[1]=etudiant(personne(Paula,Hanson,56),27)
V[2]=etudiant(personne(Chris,Garot,22),19980405)

از این پس، ما فرآیند کامپایل و اجرای برنامه‌های تست را تکرار نخواهیم کرد. کافی است مراحل ذکر شده در بالا را دنبال کنید.

4.5. کلاس ArrayList

کلاس ArrayList مشابه کلاس Vector است. این کلاس اساساً تنها زمانی با آن تفاوت دارد که همزمان توسط چندین نخ اجرایی استفاده شود. روش‌های همگام‌سازی نخ برای دسترسی به Vector یا ArrayList متفاوت است. به جز این مورد، می‌توان از هر یک به طور متناوب استفاده کرد. در اینجا برخی از فیلدها، سازنده‌ها و متدهای این کلاس آورده شده است:

ArrayList()
یک آرایه خالی ایجاد می‌کند
int size()
تعداد عناصر در آرایه
void add(Object obj)
شیء مرجع obj را به آرایه اضافه می‌کند
void add(int index, Object obj)
شیء مرجع obj را به آرایه در موقعیت index اضافه می‌کند
شیء get(int index)
ارجاع به شی شماره index در آرایه – شاخص‌ها از 0 شروع می‌شوند
boolean isEmpty()
در صورتی که آرایه خالی باشد، مقدار true را برمی‌گرداند
void remove(int index)
عنصر با شاخص index را حذف می‌کند
void clear()
آرایه را از تمام عناصرش پاک می‌کند
آرایهٔ شیء toArray()
مجموعه پویا را به یک آرایه استاندارد تبدیل می‌کند
String toString()
یک رشته حاوی شناسهٔ آرایه را بازمی‌گرداند

در اینجا یک برنامه آزمایشی آمده است:

//کلاس‌های واردشده
import java.util.*;

public class test1{

// برنامهٔ اصلی – main – استاتیک – متد کلاس

  public static void main(String arg[]){

// ایجاد اشیاء نمونه کلاس
    personne p=new personne("Jean","Dupont",30);
    enseignant en=new enseignant("Paula","Hanson",56,27);
    etudiant et=new etudiant("Chris","Garot",22,"19980405");
    System.out.println("p="+p);
    System.out.println("en="+en);
    System.out.println("et="+et);

// چندریختی
    personne p2=(personne)en;
    System.out.println("p2="+p2);
    personne p3=(personne)et;
    System.out.println("p3="+p3);

//یک بردار
    ArrayList personnes=new ArrayList();
    personnes.add(p);personnes.add(en);personnes.add(et);
    System.out.println("Nombre de personnes = "+personnes.size());
    for(int i=0;i<personnes.size();i++){
      p2=(personne) personnes.get(i);
      System.out.println("personnes["+i+"]="+p2);
    }
} // پایان برنامه اصلی
}// پایان کلاس

نتایج به‌دست‌آمده همانند قبل هستند.

4.6. کلاس Arrays

کلاس java.util.Arrays دسترسی به متدهای استاتیک را فراهم می‌کند که امکان انجام عملیات مختلف روی آرایه‌ها، به‌ویژه مرتب‌سازی و جستجو برای عناصر را فراهم می‌آورد. در اینجا چند نمونه از این متدها آورده شده است:

static void sort(array)
tableau را با استفاده از ترتیب ضمنی نوع داده آرایه، چه اعداد و چه رشته‌ها، مرتب می‌کند.
static void sort(Object[] array, Comparator C)
آرایه tableau را با استفاده از تابع مقایسه C برای مقایسه عناصر مرتب می‌کند
static int binarySearch(array, element)
موقعیت élément در tableau را بازمی‌گرداند، در غیر این صورت مقداری کمتر از 0 را برمی‌گرداند. آرایه باید از قبل مرتب شده باشد.
static int binarySearch(Object[] array, Object element, Comparator C)
همانند مورد بالا، اما از تابع مقایسه C برای مقایسه دو عنصر آرایه استفاده می‌کند.

در اینجا یک مثال اولیه آورده شده است:

import java.util.*;

public class sort2 implements Comparator{

   //یک کلاس خصوصی داخلی
  private class personne{
    private String nom;
    private int age;
    public personne(String nom, int age){
      this.nom=nom; // نام شخص
      this.age=age; // سن آنها
    }
     // بازیابی سن
    public int getAge(){
      return age;
    }
     // هویت شخص
    public String toString(){
      return ("["+nom+","+age+"]");
    }
  }; // کلاس شخص

   // تولیدکننده
  public sort2() {
     // یک آرایه از افراد
    personne[] amis=new personne[]{new personne("tintin",100),new personne("milou",80),
        new personne("tournesol",40)};
     // ترتیب‌دهی آرایه افراد
    Arrays.sort(amis,this);
     // تأیید
    for(int i=0;i<3;i++)
      System.out.println(amis[i]);
  }//سازنده

   // تابعی که افراد را مقایسه می‌کند
  public int compare(Object o1, Object o2){
    // باید بازگرداند
     // -1 اگر o1 «کمتر از» o2 باشد
     // 0 اگر o1 برابر با o2 باشد
     //+1 اگر o1 «بزرگ‌تر از» o2 باشد
    personne p1=(personne)o1;
    personne p2=(personne)o2;
    int age1=p1.getAge();
    int age2=p2.getAge();
    if(age1<age2) return (-1);
      else if (age1==age2) return (0);
        else return +1;
  }//مقایسه می‌کند

    // تابع آزمون
  public static void main(String[] arg){
    new sort2();
  }//اصلی

}//کلاس

بیایید این برنامه را بررسی کنیم. تابع main یک شیء sort2 ایجاد می‌کند. سازنده کلاس sort2 به شرح زیر است:

   // سازنده
  public sort2() {
     // فهرستی از افراد
    personne[] amis=new personne[]{new personne("tintin",100),new personne("milou",80),
        new personne("tournesol",40)};
     // ترتیب‌دهی فهرست افراد
    Arrays.sort(amis,this);
     //تأیید
    for(int i=0;i<3;i++)
      System.out.println(amis[i]);
  }//سازنده

آرایه‌ای که باید مرتب شود، یک آرایه از اشیاء personne است. کلاس personne به صورت خصوصی (private) در داخل کلاس sort2 تعریف شده است. متد استاتیک sort از کلاس Arrays نمی‌داند چگونه یک آرایه از اشیاء personne را مرتب کند، بنابراین در اینجا مجبوریم از شکل void sort(Object[] obj, Comparator C) استفاده کنیم. Comparator یک رابط است که تنها یک متد را تعریف می‌کند:

    int compare(Object o1, Object o2)

که باید در صورت برابر بودن o1 و o2، عدد 0 را بازگرداند، -۱: اگر o1 < o2، +۱: اگر o1 > o2. در پروتوتایپ void sort(Object[] obj, Comparator C), آرگومان دوم C باید یک شیء پیاده‌ساز رابط Comparator باشد. در سازنده sort2، ما شیء فعلی this را انتخاب کرده‌ایم:

     //مرتب‌سازی فهرست افراد
    Arrays.sort(amis,this);

این امر ما را ملزم به انجام دو کار می‌کند:

  1. مشخص کنیم که کلاس sort2 رابط Comparator را پیاده‌سازی می‌کند
public class sort2 implements Comparator{
  1. تابع compare را در کلاس sort2 بنویسید.

این به شرح زیر است:

   // تابعی که افراد را مقایسه می‌کند
  public int compare(Object o1, Object o2){
    // باید بازگرداند
     // -1 اگر o1 «کمتر از» o2 باشد
     // 0 اگر o1 برابر با o2 باشد
     //+1 اگر o1 «بزرگ‌تر از» o2 باشد
    personne p1=(personne)o1;
    personne p2=(personne)o2;
    int age1=p1.getAge();
    int age2=p2.getAge();
    if(age1<age2) return (-1);
      else if (age1==age2) return (0);
        else return +1;
  }//مقایسه می‌کند

برای مقایسه دو شیء personne، در اینجا از age استفاده می‌کنیم (می‌توانستیم از name استفاده کنیم).

نتایج اجرای کد به شرح زیر است:

[tournesol,40]
[milou,80]
[tintin,100]

ما می‌توانستیم رویکرد متفاوتی برای پیاده‌سازی رابط Comparator اتخاذ کنیم:

import java.util.*;

public class sort2 {

  //یک کلاس خصوصی داخلی
  private class personne{
…….
  }; // کلاس شخص

   // سازنده
  public sort2() {
     // یک آرایه از افراد
    personne[] amis=new personne[]{new personne("tintin",100),new personne("milou",80),
        new personne("tournesol",40)};
     // ترتیب‌دهی آرایه افراد
    Arrays.sort(amis,
        new java.util.Comparator(){
          public int compare(Object o1, Object o2){
            return compare1(o1,o2);
        }//مقایسه
      }//کلاس
    );
     // اعتبارسنجی
    for(int i=0;i<3;i++)
      System.out.println(amis[i]);
  }//سازنده

   // تابعی که افراد را مقایسه می‌کند
  public int compare1(Object o1, Object o2){
    // باید بازگرداند
     // -1 اگر o1 «کمتر از» o2 باشد
     // 0 اگر o1 برابر با o2 باشد
     //+1 اگر o1 «بزرگ‌تر از» o2 باشد
    personne p1=(personne)o1;
    personne p2=(personne)o2;
    int age1=p1.getAge();
    int age2=p2.getAge();
    if(age1<age2) return (-1);
      else if (age1==age2) return (0);
        else return +1;
  }//compare1

  // اصلی
  public static void main(String[] arg){
    new sort2();
  }//main
}//مرتب‌سازی

دستور مرتب‌سازی به شرح زیر است:

     //مرتب‌سازی فهرست افراد
    Arrays.sort(amis,
        new java.util.Comparator(){
          public int compare(Object o1, Object o2){
            return compare1(o1,o2);
        }//مقایسه
      }//کلاس
    );

پارامتر دوم متد sort باید یک شیء باشد که رابط Comparator را پیاده‌سازی کند. در اینجا ما با استفاده از new java.util.Comparator() چنین شیئی را ایجاد می‌کنیم، و متن داخل {…} کلاسی را که از آن شیئی ایجاد می‌کنیم تعریف می‌کند. این یک کلاس گمنام نامیده می‌شود زیرا نامی ندارد. در داخل این کلاس گمنام، که باید رابط Comparator را پیاده‌سازی کند، ما متد compare آن رابط را تعریف می‌کنیم. این متد صرفاً متد compare1 از کلاس sort2 را فراخوانی می‌کند. در این صورت، ما به حالت قبلی بازمی‌گردیم.

کلاس sort2 دیگر رابط Comparator را پیاده‌سازی نمی‌کند. در نتیجه، اعلان آن به این صورت درمی‌آید:

public class sort2 {

اکنون متد binarySearch از کلاس Arrays را با استفاده از مثال زیر آزمایش خواهیم کرد:

import java.util.*;

public class sort4 {

  //یک کلاس خصوصی داخلی
  private class personne{
      // ویژگی‌ها
    private String nom;
    private int age;

        // سازنده
    public personne(String nom, int age){
      this.nom=nom; // نام شخص
      this.age=age; // سن
    }

     // استخراج نام
    public String getNom(){
      return nom;
    }

     //بازیابی سن
    public int getAge(){
      return age;
    }
     // هویت شخص
    public String toString(){
      return ("["+nom+","+age+"]");
    }
  }; // کلاس شخص

   // سازنده
  public sort4() {
     // یک آرایه از افراد
    personne[] amis=new personne[]{new personne("tintin",100),new personne("milou",80),
        new personne("tournesol",40)};

     // مقایسه‌گرها
    java.util.Comparator comparateur1=
        new java.util.Comparator(){
          public int compare(Object o1, Object o2){
            return compare1(o1,o2);
        }//مقایسه می‌کند
      }//کلاس
      ;
    java.util.Comparator comparateur2=
        new java.util.Comparator(){
          public int compare(Object o1, Object o2){
            return compare2(o1,o2);
        }//مقایسه می‌کند
      }//مرتب‌سازی‌ها
      ;          

     //مرتب‌سازی فهرست افراد
    Arrays.sort(amis,comparateur1);
    // تأیید
    for(int i=0;i<3;i++)
      System.out.println(amis[i]);
    //جستجوها
    cherche("milou",amis,comparateur2);
    cherche("xx",amis,comparateur2);
  }//سازنده

   // تابعی که افراد را مقایسه می‌کند
  public int compare1(Object o1, Object o2){
    //باید بازگرداند
     // -1 اگر o1 «کمتر از» o2 باشد
     // 0 اگر o1 برابر با o2 باشد
     //+1 اگر o1 «بزرگ‌تر از» o2 باشد
    personne p1=(personne)o1;
    personne p2=(personne)o2;
    int age1=p1.getAge();
    int age2=p2.getAge();
    if(age1<age2) return (-1);
      else if (age1==age2) return (0);
        else return +1;
  }//compare1

   // تابعی که یک شخص را با یک نام مقایسه می‌کند
  public int compare2(Object o1, Object o2){
    //o1 یک شخص است
     // o2 یک رشته است، نام «name2» یک شخص
     // باید بازگرداند
     // -1 اگر o1.nom «کمتر از» nom2 باشد
     // 0 اگر o1.nom برابر با name2 باشد
     //+1 اگر o1.nom «بزرگ‌تر از» name2 باشد
    personne p1=(personne)o1;
    String nom1=p1.getNom();
    String nom2=(String)o2;
    return nom1.compareTo(nom2);
  }//مقایسه2

    public void cherche(String ami,personne[] amis, Comparator comparateur){
       //جستجو برای دوست در آرایه دوستان
    int position=Arrays.binarySearch(amis,ami,comparateur);
     //پیدا شد؟
    if(position>=0)
        System.out.println(ami + " a " + amis[position].getAge() + " ans");
    else System.out.println(ami + " n'existe pas dans le tableau");
  }//در حال جستجو

  // دست
  public static void main(String[] arg){
    new sort4();
  }//دست
}//کلاس

در اینجا، ما کمی متفاوت از مثال‌های قبلی عمل کرده‌ایم. دو شیء Comparator که توسط متدهای sort و binarySearch مورد نیاز بودند، ایجاد شده و به متغیرهای comparateur1 و comparateur2 اختصاص یافتند.

     //مقایسه‌گرها
    java.util.Comparator comparateur1=
        new java.util.Comparator(){
          public int compare(Object o1, Object o2){
            return compare1(o1,o2);
        }//مقایسه می‌کند
      }//class
      ;
    java.util.Comparator comparateur2=
        new java.util.Comparator(){
          public int compare(Object o1, Object o2){
            return compare2(o1,o2);
        }//compare
      }//class
      ;          

یک جستجوی دوگانه روی جدول amis دو بار در سازنده برای sort4 انجام می‌شود:

     //جستجوها
    cherche("milou",amis,comparateur2);
    cherche("xx",amis,comparateur2);

متد cherche تمام پارامترهای لازم برای فراخوانی متد binarySearch را دریافت می‌کند:

    public void cherche(String ami,personne[] amis, Comparator comparateur){
       //جستجوی دوست در فهرست دوستان
    int position=Arrays.binarySearch(amis,ami,comparateur);
     // یافت شد؟
    if(position>=0)
        System.out.println(ami + " a " + amis[position].getAge() + " ans");
    else System.out.println(ami + " n'existe pas dans le tableau");
  }//جستجو

متد binarySearch با مقایسه‌گر comparateur2 کار می‌کند که به نوبه خود متد compare2 از کلاس sort4 را فراخوانی می‌کند. متد rend موقعیت نام جست‌وجو شده را در آرایه بازمی‌گرداند، اگر وجود داشته باشد، و در غیر این صورت عددی کمتر از 0. متد compare2 برای مقایسه یک شیء personne با نامی از نوع String استفاده می‌شود.

   // تابعی که یک شخص را با یک نام مقایسه می‌کند
  public int compare2(Object o1, Object o2){
    // o1 یک شخص است
     // o2 یک رشته است، نام «name2» یک شخص
     //باید بازگرداند
     // -1 اگر o1.nom "کمتر از" name2 باشد
     //0 اگر o1.nom برابر با name2 باشد
     //+1 اگر o1.nom «بزرگ‌تر از» name2 باشد
    personne p1=(personne)o1;
    String nom1=p1.getNom();
    String nom2=(String)o2;
    return nom1.compareTo(nom2);
  }//compare2

برخلاف متد sort، متد binarySearch دو شیء personne را نمی‌پذیرد، بلکه یک شیء personne و یک شیء String را به همین ترتیب می‌پذیرد. پارامتر اول یک عنصر از آرایه amis است و پارامتر دوم نام فردی است که در حال جستجو است.

4.7. کلاس Enumeration

Enumeration یک رابط است، نه یک کلاس. این رابط متدهای زیر را دارد:

public abstract boolean hasMoreElements()
در صورتی که شمارش هنوز عنصر داشته باشد، مقدار true را برمی‌گرداند
public abstract Object nextElement()
یک مرجع به عنصر بعدی در شمارش‌پذیر را بازمی‌گرداند

چگونه از یک شمارش‌شده استفاده می‌کنید؟ به طور کلی، به این صورت:

    Enumeration e=…                //یک شیء شمارشگر را بازیابی می‌کند
    while(e.hasMoreElements()){
        // پردازش عنصر e.nextElement()
    }

در اینجا یک مثال آورده شده است:


// کلاس‌های واردشده
import java.util.*;

public class test1{

// برنامهٔ اصلی: `main`، `static` و متدهای کلاس

  public static void main(String arg[]){

//ایجاد نمونه‌های کلاس
    personne p=new personne("Jean","Dupont",30);
    enseignant en=new enseignant("Paula","Hanson",56,27);
    etudiant et=new etudiant("Chris","Garot",22,"19980405");
    System.out.println("p="+p.toString());
    System.out.println("en="+en.toString());
    System.out.println("et="+et.toString());

// چندریختی
    personne p2=(personne)en;
    System.out.println("p2="+p2.toString());
    personne p3=(personne)et;
    System.out.println("p3="+p3.toString());

// یک بردار
    Vector V=new Vector();
    V.addElement(p);V.addElement(en);V.addElement(et);
    System.out.println("Taille du vecteur V = "+V.size());
    int i;
    for(i=0;i<V.size();i++){
      p2=(personne) V.elementAt(i);
      System.out.println("V["+i+"]="+p2.toString());
    }

//یک شمارش‌شده
    Enumeration E=V.elements();
    i=0;
    while(E.hasMoreElements()){
      p2=(personne) E.nextElement();
      System.out.println("V["+i+"]="+p2.toString());
      i++;
    }
   }// پایان برنامه اصلی
}//پایان کلاس

نتایج زیر به دست آمده است:

p=personne(Jean,Dupont,30)
en=enseignant(personne(Paula,Hanson,56),27)
et=etudiant(personne(Chris,Garot,22),19980405)
p2=enseignant(personne(Paula,Hanson,56),27)
p3=etudiant(personne(Chris,Garot,22),19980405)
Taille du vecteur V = 3
V[0]=personne(Jean,Dupont,30)
V[1]=enseignant(personne(Paula,Hanson,56),27)
V[2]=etudiant(personne(Chris,Garot,22),19980405)
V[0]=personne(Jean,Dupont,30)
V[1]=enseignant(personne(Paula,Hanson,56),27)
V[2]=etudiant(personne(Chris,Garot,22),19980405)

4.8. کلاس Hashtable

کلاس Hashtable برای پیاده‌سازی یک دیکشنری استفاده می‌شود. یک دیکشنری را می‌توان به صورت یک آرایهٔ دو ستونی در نظر گرفت:

کلید
value
key1
value1
key2
value2
..
...

کلیدها منحصربه‌فرد هستند، c.a.d، به این معنی که هیچ دو کلیدی نمی‌توانند یکسان باشند. روش‌ها و ویژگی‌های اصلی کلاس Hashtable به شرح زیر هستند:

public Hashtable()
سازنده – یک جدول هش خالی ایجاد می‌کند
public int size()
تعداد عناصر در دیکشنری – هر عنصر یک جفت (کلید، مقدار) است
public Object put(Object key, Object value)
جفت (کلید، مقدار) را به دیکشنری اضافه می‌کند
public Object get(Object key)
شیء مرتبط با کلید key را بازیابی می‌کند یا در صورتی که کلید key وجود نداشته باشد، null را
public boolean containsKey(Object key)
true اگر کلید key در دیکشنری وجود داشته باشد
public boolean contains(Object value)
true اگر مقدار value در دیکشنری وجود داشته باشد
public Enumeration keys()
کلیدهای دیکشنری را به صورت یک شمارش‌گر برمی‌گرداند
public Object remove(Object key)
جفت (کلید، مقدار) را که کلید آن key است، حذف می‌کند
public String toString()
واژه‌نامه را شناسایی می‌کند

در اینجا یک مثال آورده شده است:


//کلاس‌های واردشده
import java.util.*;

public class test1{

// برنامهٔ اصلی – main – استاتیک – متد کلاس

  public static void main(String arg[]){

// ایجاد اشیاء نمونه کلاس
    personne p=new personne("Jean","Dupont",30);
    enseignant en=new enseignant("Paula","Hanson",56,27);
    etudiant et=new etudiant("Chris","Garot",22,"19980405");
    System.out.println("p="+p.toString());
    System.out.println("en="+en.toString());
    System.out.println("et="+et.toString());

// چندریختی
    personne p2=(personne)en;
    System.out.println("p2="+p2.toString());
    personne p3=(personne)et;
    System.out.println("p3="+p3.toString());

// یک فرهنگ لغت
    Hashtable H=new Hashtable();
    H.put("personne1",p);
    H.put("personne2",en);
    H.put("personne3",et);
    Enumeration E=H.keys();
    int i=0;
    String cle;
    while(E.hasMoreElements()){
      cle=(String) E.nextElement();
      p2=(personne) H.get(cle);
      System.out.println("clé "+i+"="+cle+" valeur="+p2.toString());
      i++;
    }
  }//پایان برنامه اصلی
}//پایان کلاس

نتایج به‌دست‌آمده به شرح زیر است:

p=personne(Jean,Dupont,30)
en=enseignant(personne(Paula,Hanson,56),27)
et=etudiant(personne(Chris,Garot,22),19980405)
p2=enseignant(personne(Paula,Hanson,56),27)
p3=etudiant(personne(Chris,Garot,22),19980405)
clé 0=personne3 valeur=etudiant(personne(Chris,Garot,22),19980405)
clé 1=personne2 valeur=enseignant(personne(Paula,Hanson,56),27)
clé 2=personne1 valeur=personne(Jean,Dupont,30)

4.9. فایل‌های متنی

4.9.1. نوشتن

برای نوشتن در یک فایل، به یک جریان نوشتن نیاز دارید. می‌توانید از کلاس FileWriter برای این منظور استفاده کنید. پرکاربردترین سازندها به شرح زیر هستند:

FileWriter(String fileName)
یک فایل با نام fileName ایجاد می‌کند – سپس می‌توانید در آن بنویسید – هر فایل موجود با همین نام بازنویسی خواهد شد
FileWriter(String fileName,
boolean append)
همانند مورد بالا – هر فایل موجود با نام یکسان را می‌توان با باز کردن آن در حالت الحاق (append mode) (append=true) استفاده کرد.

کلاس FileWriter تعدادی متد برای نوشتن در فایل فراهم می‌کند که از کلاس Writer به ارث رسیده است. برای نوشتن در یک فایل متنی، ترجیحاً از کلاس PrintWriter استفاده کنید که سازنده‌های رایج آن به شرح زیر هستند:

PrintWriter(Writer out)
آرگومان از نوع Writer یا c.a.d است: یک جریان خروجی (به یک فایل، از طریق شبکه و غیره)
PrintWriter(Writer out, boolean autoflush)
همانند مورد بالا. آرگومان دوم، بافرینگ خطوط را کنترل می‌کند. وقتی روی false (که پیش‌فرض است) تنظیم شود، خطوطی که به فایل نوشته می‌شوند از یک بافر حافظه‌ای عبور می‌کنند. وقتی بافر پر شود، محتویات آن به فایل نوشته می‌شوند. این کار عملکرد دسترسی به دیسک را بهبود می‌بخشد. با این حال، این رفتار گاهی اوقات نامطلوب است، به‌ویژه هنگام نوشتن از طریق شبکه.

متدهای مفید کلاس PrintWriter به شرح زیر است:

void print(Type T)
داده‌های T (String, int, …) را می‌نویسد
void println(Type T)
همان کار را انجام می‌دهد، اما با یک خط‌شکن پایان می‌یابد
void flush()
بافر را تخلیه می‌کند اگر در حالت autoflush نباشد
void close()
جریان خروجی را می‌بندد

در اینجا برنامه‌ای است که چند خط به یک فایل متنی می‌نویسد:

// واردات
import java.io.*;

public class ecrire{
  public static void main(String[] arg){
    // باز کردن فایل
    PrintWriter fic=null;
    try{
      fic=new PrintWriter(new FileWriter("out"));
    } catch (Exception e){
      Erreur(e,1);
    }
     //نوشتن در فایل
    try{
      fic.println("Jean,Dupont,27");
      fic.println("Pauline,Garcia,24");
      fic.println("Gilles,Dumond,56");
    } catch (Exception e){
      Erreur(e,3);
    }
     // بستن فایل
    try{
      fic.close();
    } catch (Exception e){
      Erreur(e,2);
    }
  }//پایان تابع main

  private static void Erreur(Exception e, int code){
    System.err.println("Erreur : "+e);
    System.exit(code);
  }//خطا
}//کلاس

فایل out تولید شده توسط اجرا به شرح زیر است:

Jean,Dupont,27
Pauline,Garcia,24
Gilles,Dumond,56

4.9.2. خواندن

برای خواندن محتویات یک فایل، به یک جریان خواندن مرتبط با آن فایل نیاز دارید. می‌توانید از کلاس FileReader و سازنده زیر برای این کار استفاده کنید:

FileReader(String filename)
یک جریان خواندن از فایل مشخص را باز می‌کند. در صورت ناموفق بودن عملیات، یک استثنا پرتاب می‌کند.

کلاس FileReader دارای تعدادی متد برای خواندن از یک فایل است که از کلاس Reader به ارث رسیده است. برای خواندن خطوط متن از یک فایل متنی، بهتر است از کلاس BufferedReader با سازنده زیر استفاده کنید:

BufferedReader(Reader in)
یک جریان خوانش بافر شده را از یک جریان ورودی in باز می‌کند. این جریان Reader ممکن است از صفحه‌کلید، یک فایل، شبکه و غیره منشأ بگیرد.

متدهای مفید کلاس BufferedReader به شرح زیر است:

int read()
یک کاراکتر را می‌خواند
String readLine()
یک خط متن را می‌خواند
int read(char[] buffer, int offset, int size)
taille کاراکتر را از فایل می‌خواند و آن‌ها را در آرایه buffer از موقعیت offset قرار می‌دهد.
void close()
جریان خواندن را می‌بندد

در اینجا برنامه‌ای است که محتویات فایل ایجادشده در بالا را می‌خواند:

//کلاس‌های واردشده
import java.util.*;
import java.io.*;

public class lire{
  public static void main(String[] arg){
    personne p=null;
     // فایل باز شد
    BufferedReader IN=null;
    try{
      IN=new BufferedReader(new FileReader("out"));
    } catch (Exception e){
      Erreur(e,1);
    }
     // داده‌ها
    String ligne=null;
    String[] champs=null;
    String prenom=null;
    String nom=null;
    int age=0;

    // پردازش هرگونه خطا
    try{
      while((ligne=IN.readLine())!=null){
        champs=ligne.split(",");
        prenom=champs[0];
        nom=champs[1];
        age=Integer.parseInt(champs[2]);
        System.out.println(""+new personne(prenom,nom,age));
      }// پایان حلقه while
    } catch (Exception e){
      Erreur(e,2);
    }

     //بستن فایل
    try{
      IN.close();
    } catch (Exception e){
      Erreur(e,3);
    }
  }// پایان تابع اصلی

   // خطا
  public static void Erreur(Exception e, int code){
    System.err.println("Erreur : "+e);
    System.exit(code);
  }

}// پایان کلاس

اجرای برنامه نتایج زیر را تولید می‌کند:

personne(Jean,Dupont,27)
personne(Pauline,Garcia,24)
personne(Gilles,Dumond,56)

4.9.3. ذخیره یک شیء شخص

آنچه را که به تازگی دیدیم به کار می‌بریم تا به کلاس personne متدی برای ذخیرهٔ ویژگی‌های یک شخص در یک فایل ارائه دهیم. ما متد sauveAttributs را به تعریف کلاس personne اضافه می‌کنیم:


    // ------------------------------
  //ذخیره در فایل متنی
    // ------------------------------
  public void sauveAttributs(PrintWriter P){
    P.println(""+this);
  }

قبل از تعریف کلاس personne، فراموش نکنید که بسته java.io را وارد کنید:

import java.io.*;

متد sauveAttributs یک پارامتر واحد می‌گیرد: استریم PrintWriter که باید در آن بنویسد. یک برنامهٔ آزمایشی ممکن است به این شکل باشد:

// واردات‌ها
import java.io.*;
// import person;

public class sauver{
  public static void main(String[] arg){
    // باز کردن فایل
    PrintWriter fic=null;
    try{
      fic=new PrintWriter(new FileWriter("out"));
    } catch (Exception e){
      Erreur(e,1);
    }
     //نوشتن در فایل
    try{
      new personne("Jean","Dupont",27).sauveAttributs(fic);
      new personne("Pauline","Garcia",24).sauveAttributs(fic);
      new personne("Gilles","Dumond",56).sauveAttributs(fic);
    } catch (Exception e){
      Erreur(e,3);
    }
     // بستن فایل
    try{
      fic.close();
    } catch (Exception e){
      Erreur(e,2);
    }
  }// پایان برنامه اصلی

   //خطا
  private static void Erreur(Exception e, int code){
    System.err.println("Erreur : "+e);
    System.exit(code);
  }//خطا
}//کلاس

بیایید این برنامه را کامپایل و اجرا کنیم:

E:\data\serge\JAVA\poly juin 2002\Chapitre 3\sauveAttributs>javac sauver.java

E:\data\serge\JAVA\poly juin 2002\Chapitre 3\sauveAttributs>dir
10/06/2002  10:52                1 352 personne.class
10/06/2002  10:53                  842 sauver.java
10/06/2002  10:53                1 258 sauver.class

E:\data\serge\JAVA\poly juin 2002\Chapitre 3\sauveAttributs>java sauver

E:\data\serge\JAVA\poly juin 2002\Chapitre 3\sauveAttributs>dir
10/06/2002  10:52                1 352 personne.class
10/06/2002  10:53                  842 sauver.java
10/06/2002  10:53                1 258 sauver.class
10/06/2002  10:53                   83 out

E:\data\serge\JAVA\poly juin 2002\Chapitre 3\sauveAttributs>more out
personne(Jean,Dupont,27)
personne(Pauline,Garcia,24)
personne(Gilles,Dumond,56)

4.10. فایل‌های باینری

4.10.1. کلاس RandomAccessFile

کلاس RandomAccessFile به شما امکان می‌دهد فایل‌های باینری، به‌ویژه آن‌هایی که ساختار ثابتی دارند مانند فایل‌های موجود در C/C++، را مدیریت کنید. در اینجا برخی از متدها و سازنده‌های مفید آورده شده است:

RandomAccessFile(String filename, String mode)
سازنده – فایل مشخص‌شده را در حالت تعیین‌شده باز می‌کند. حالت می‌تواند مقادیر زیر را داشته باشد:
r: باز کردن برای خواندن
rw: باز برای خواندن و نوشتن
void writeTTT(TTT value)
مقدار را به فایل می‌نویسد. TTT نوع مقدار را نشان می‌دهد. نمایش حافظه مقدار به همان صورت به فایل نوشته می‌شود. بنابراین، ما writeBoolean، writeByte، writeInt، را می‌یابیم، writeDouble, writeLong, writeFloat, ... برای نوشتن یک رشته، از writeBytes(String string) استفاده کنید.
TTT readTTT()
یک مقدار از نوع TTT را می‌خواند و برمی‌گرداند. بنابراین، ما readBoolean، readByte، readInt، readDouble، readLong، readFloat، ... متد read() یک بایت را می‌خواند.
long length()
اندازه فایل به بایت
long getFilePointer()
موقعیت فعلی نشانگر فایل
void seek(long pos)
موقعیت نشانگر فایل را روی بایت pos تنظیم می‌کند

4.10.2. کلاس مقاله

تمام مثال‌های زیر از کلاس article زیر استفاده خواهند کرد:

     //ساختار مقاله
    private static class article{
         // تعریف ساختار
        public String code;
        public String nom;
        public double prix;
        public int stockActuel;
        public int stockMinimum;
  }//کلاس مقاله

کلاس جاوا article که در بالا نشان داده شده است، معادل ساختار C زیر article خواهد بود.

struct article{
    char code[4];
    char nom[20];
    double prix;
    int stockActuel;
    int stockMinimum;
}//ساختار

بنابراین کد را به ۴ کاراکتر و نام را به ۲۰ کاراکتر محدود خواهیم کرد.

4.10.3. نوشتن یک رکورد

برنامه زیر یک رکورد را در فایلی به نام "data" می‌نویسد:

//کلاس‌های واردشده
import java.io.*;

public class test1{

// آزمون‌ها نوشتن یک ساختار (در معنای C) را به یک فایل دودویی بررسی می‌کنند

     //ساختار مقاله
    private static class article{
         // تعریف ساختار
        public String code;
        public String nom;
        public double prix;
        public int stockActuel;
        public int stockMinimum;
  }//کلاس 'article'

    public static void main(String arg[]){

         // ما فایل دودویی را که مقالات در آن ذخیره خواهند شد تعریف می‌کنیم
        RandomAccessFile fic=null;

         //یک آیتم تعریف می‌شود
        article art=new article();
        art.code="a100";
        art.nom="velo";
        art.prix=1000.80;
        art.stockActuel=100;
        art.stockMinimum=10;

         // فایل تعریف می‌شود
        try{
                fic=new RandomAccessFile("data","rw");
        } catch (Exception E){
                erreur("Impossible d'ouvrir le fichier data",1);
        }//try-catch

        // ما می‌نویسیم
        try{
            ecrire(fic,art);
        } catch (IOException E){
                erreur("Erreur lors de l'écriture de l'enregistrement",2);
        }//try-catch

        // تمام شد
        try{
            fic.close();
        } catch (Exception E){
            erreur("Impossible de fermer le fichier data",2);
        }//try-catch
  }//main

   // نوشتن متد
  public static void ecrire(RandomAccessFile fic, article art) throws IOException{
        // کد
      fic.writeBytes(art.code);
       // نام محدود به ۲۰ کاراکتر
      art.nom=art.nom.trim();
      int l=art.nom.length();
      int nbBlancs=20-l;
      if(nbBlancs>0){
          String blancs="";
          for(int i=0;i<nbBlancs;i++) blancs+=" ";
          art.nom+=blancs;
      } else art.nom=art.nom.substring(0,20);
      fic.writeBytes(art.nom);
       // قیمت
      fic.writeDouble(art.prix);
       // سطوح موجودی
      fic.writeInt(art.stockActuel);
      fic.writeInt(art.stockMinimum);
  }// پایان نوشتن

   // ------------------------ خطا
  public static void erreur(String msg, int exitCode){
          System.err.println(msg);
          System.exit(exitCode);
  }// پایان خطا
}// پایان کلاس

برنامه زیر به ما امکان می‌دهد بررسی کنیم که اجرای برنامه به درستی انجام شده است.

4.10.4. خواندن یک رکورد

// کلاس‌های واردشده
import java.io.*;

public class test2{

// آزمایش‌های نوشتن یک ساختار (در معنای C) به یک فایل دودویی

     //ساختار «article»
    private static class article{
         // تعریف ساختار
        public String code;
        public String nom;
        public double prix;
        public int stockActuel;
        public int stockMinimum;
  }//کلاس 'article'

    public static void main(String arg[]){

         // ما فایل باینری را که مقالات در آن ذخیره خواهند شد تعریف می‌کنیم
        RandomAccessFile fic=null;

       //فایل برای خواندن باز می‌شود
      try{
          fic=new RandomAccessFile("data","r");
      } catch (Exception E){
          erreur("Impossible d'ouvrir le fichier data",1);
      }//try-catch

       // یک آیتم را از فایل می‌خواند
    article art=new article();
      try{
          lire(fic,art);
      } catch (IOException E){
          erreur("Erreur lors de la lecture de l'enregistrement",2);
      }//try-catch

       // نمایش رکوردی که خوانده شده است
      affiche(art);

       // همین
      try{
          fic.close();
      } catch (Exception E){
          erreur("Impossible de fermer le fichier data",2);
      }//try-catch
  }//پایان راهنما

    //روش خواندن
    public static void lire(RandomAccessFile fic, article art) throws IOException{
       // خواندن کد
        art.code="";
        for(int i=0;i<4;i++) art.code+=(char)fic.readByte();
    // نام
        art.nom="";
        for(int i=0;i<20;i++) art.nom+=(char)fic.readByte();
        art.nom=art.nom.trim();
    // قیمت
        art.prix=fic.readDouble();
    // سطوح موجودی
        art.stockActuel=fic.readInt();
        art.stockMinimum=fic.readInt();
    }// پایان نوشتن

     // ---------------------نمایش
    public static void affiche(article art){
        System.out.println("code : "+art.code);
        System.out.println("nom : "+art.nom);
        System.out.println("prix : "+art.prix);
        System.out.println("Stock actuel : "+art.stockActuel);
        System.out.println("Stock minimum : "+art.stockMinimum);
    }// پایان نمایش

     // ------------------------خطا
    public static void erreur(String msg, int exitCode){
                System.err.println(msg);
                System.exit(exitCode);
    }// پایان خطا
}// پایان کلاس

نتایج اجرا به شرح زیر است:

E:\data\serge\JAVA\random>java test2
code : a100
nom : velo
prix : 1000.8
Stock actuel : 100
Stock minimum : 10    

رکوردی که توسط برنامه نویسنده نوشته شده بود با موفقیت بازیابی شد.

4.10.5. تبدیل متن به باینری

برنامه زیر توسعه‌ای از برنامه نوشتن یک رکورد است. اکنون چندین رکورد را در یک فایل باینری به نام data.bin می‌نویسیم. داده‌ها از فایل زیر، data.txt، گرفته می‌شوند:

E:\data\serge\JAVA\random>more data.txt
a100:velo:1000:100:10
b100:pompe:65:6:2
c100:arc:867:10:5
d100:fleches - lot de 6:450:12:8
e100:jouet:10:2:3
//کلاس‌های واردشده
import java.io.*;
import java.util.*;

public class test3{

// فایل متنی --> فایل باینری

     //ساختار مقاله
    private static class article{
         // تعریف ساختار
        public String code;
        public String nom;
        public double prix;
        public int stockActuel;
        public int stockMinimum;
  }//کلاس مقاله

    public static void main(String arg[]){

         // تعریف فایل باینری که مقالات در آن ذخیره خواهند شد
        RandomAccessFile dataBin=null;
        try{
                dataBin=new RandomAccessFile("data.bin","rw");
        } catch (Exception E){
                erreur("Impossible d'ouvrir le fichier data.bin",1);
        }

         // داده‌ها از یک فایل متنی گرفته می‌شوند
    BufferedReader dataTxt=null;
        try{
            dataTxt=new BufferedReader(new FileReader("data.txt"));
        } catch (IOException E){
            erreur("Impossible d'ouvrir le fichier data.txt",2);
        }

       // فایل .txt --> فایل .bin
      String ligne=null;
      String[] champs=null;
      int numLigne=0;
      String champ=null;
    article art=new article();    // آیتمی که باید ایجاد شود
      try{
          while((ligne=dataTxt.readLine())!=null){
          //یک خط حاوی +
              numLigne++;
         // تفکیک به فیلدها
        champs=ligne.split(":");
         //پنج فیلد الزامی است
              if(champs.length!=5)
                  erreur("Ligne "+numLigne+" erronée dans data.txt",3);
         //کد
              art.code=champs[0];
              if(art.code.length()!=4) 
            erreur("Code erroné en ligne "+numLigne+" du fichier data.txt",12);
         // نام خانوادگی، نام
              art.nom=champs[1];
         // قیمت
              try{
                  art.prix=Double.parseDouble(champs[2]);
              } catch (Exception E){
                  erreur("Prix erroné en ligne "+numLigne+" du fichier data.txt",4);
              }
        //موجودی فعلی
              try{
                  art.stockActuel=Integer.parseInt(champs[3]);
              } catch (Exception E){
                  erreur("Stock actuel erroné en ligne "+ numLigne + " du fichier data.txt",5);
              }
        // موجودی فعلی
              try{
                  art.stockActuel=Integer.parseInt(champs[3]);
              } catch (Exception E){
                  erreur("Stock actuel erroné en ligne "+ numLigne + " du fichier data.txt",5);
              }             
               // ثبت را بنویسید
              try{
                  ecrire(dataBin,art);
              } catch (IOException E){
                  erreur("Erreur lors de l'écriture de l'enregistrement "+numLigne,7);
              }
               // حرکت به خط بعدی
          }// پایان حلقه while
      } catch (IOException E){
          erreur("Erreur lors de la lecture du fichier data.txt après la ligne "+numLigne,8);
      }        
        // انجام شد
      try{
                  dataBin.close();
      } catch (Exception E){
                  erreur("Impossible de fermer le fichier data.bin",10);
      }
      try{
                  dataTxt.close();
      } catch (Exception E){
                  erreur("Impossible de fermer le fichier data.txt",11);
      }
  }// پایان برنامه اصلی

   // روش نوشتن
  public static void ecrire(RandomAccessFile fic, article art) throws IOException{
        // کد
      fic.writeBytes(art.code);
       // نام محدود به ۲۰ کاراکتر
      art.nom=art.nom.trim();
      int l=art.nom.length();
      int nbBlancs=20-l;
      if(nbBlancs>0){
          String blancs="";
          for(int i=0;i<nbBlancs;i++) blancs+=" ";
          art.nom+=blancs;
      } else art.nom=art.nom.substring(0,20);
      fic.writeBytes(art.nom);
       // قیمت
      fic.writeDouble(art.prix);
       // سطوح موجودی
      fic.writeInt(art.stockActuel);
      fic.writeInt(art.stockMinimum);
  }// پایان نوشتن

     // ------------------------ خطا
    public static void erreur(String msg, int exitCode){
                System.err.println(msg);
                System.exit(exitCode);
    }// پایان خطا

}// پایان کلاس

برنامه زیر به شما امکان می‌دهد بررسی کنید که به درستی کار کرده است.

4.10.6. تبدیل باینری به متن

برنامهٔ زیر محتویات فایل باینری data.bin را که قبلاً ایجاد شده است، می‌خواند و آن را در فایل متنی data.text می‌نویسد. اگر همه چیز به‌خوبی پیش برود، فایل data.text باید دقیقاً مشابه فایل اصلی data.txt باشد.

//کلاس‌های واردشده
import java.io.*;
import java.util.*;

public class test5{

// فایل متنی --> فایل باینری

     //ساختار مقاله
    private static class article{
         // تعریف ساختار
        public String code;
        public String nom;
        public double prix;
        public int stockActuel;
        public int stockMinimum;
  }//کلاس مقاله

     // اصلی
    public static void main(String arg[]){

         // تعریف فایل باینری که مقالات در آن ذخیره خواهند شد
        RandomAccessFile dataBin=null;
        try{
                dataBin=new RandomAccessFile("data.bin","r");
        } catch (Exception E){
                erreur("Impossible d'ouvrir le fichier data.bin en lecture",1);
        }

         // داده‌ها در یک فایل متنی نوشته می‌شوند
    PrintWriter dataTxt=null;
        try{
            dataTxt=new PrintWriter(new FileWriter("data.text"));
        } catch (IOException E){
            erreur("Impossible d'ouvrir le fichier data.text en écriture",2);
        }

      // فایل .bin --> فایل .text
    article art=new article();    // موردی که باید ایجاد شود

       // فایل باینری پردازش می‌شود
      int numRecord=0;
      long l=0;    // اندازه فایل
      try{
          l=dataBin.length();
      } catch (IOException e){
          erreur("Erreur lors du calcul de la longueur du fichier data.bin",2);
      }
      long pos=0;    // موقعیت فعلی در فایل
      try{
          pos=dataBin.getFilePointer();
      } catch (IOException e){
          erreur("Erreur lors de la lecture de la position courante dans data.bin",2);
      }

     //تا زمانی که به انتهای فایل نرسیده باشد
        while(pos<l){
            // رکورد فعلی را بخوانید و آن را پردازش کنید
            numRecord++;
            try{
                lire(dataBin,art);
            } catch (Exception e){
                erreur("Erreur lors de la lecture de l'enregistrement "+numRecord,2);
            }
            affiche(art);

             // خط متنی مربوطه را به dataTxt بنویسید
         dataTxt.println(art.code.trim()+":"+art.nom.trim()+":"+art.prix+":"+art.stockActuel+":"+art.stockMinimum);

             // آیا ادامه دهیم؟
            try{
                pos=dataBin.getFilePointer();
            } catch (IOException e){
                erreur("Erreur lors de la lecture de la position courante dans data.bin",2);
            }
        }// پایان حلقه while

       // تمام شد
      try{
                  dataBin.close();
      } catch (Exception E){
                  erreur("Impossible de fermer le fichier data.bin",2);
      }

      try{
          dataTxt.close();
      } catch (Exception E){
                  erreur("Impossible de fermer le fichier data.text",2);
      }

  }//پایان برنامه اصلی

     // خواندن روش
    public static void lire(RandomAccessFile fic, article art) throws IOException{
      // خواندن کد
        art.code="";
        for(int i=0;i<4;i++) art.code+=(char)fic.readByte();
    // نام
        art.nom="";
        for(int i=0;i<20;i++) art.nom+=(char)fic.readByte();
        art.nom=art.nom.trim();
    // قیمت
        art.prix=fic.readDouble();
    // سطوح موجودی
        art.stockActuel=fic.readInt();
        art.stockMinimum=fic.readInt();
    }// پایان نوشتن

     // ---------------------نمایش
    public static void affiche(article art){
        System.out.println("code : "+art.code);
        System.out.println("nom : "+art.nom);
        System.out.println("prix : "+art.prix);
        System.out.println("Stock actuel : "+art.stockActuel);
        System.out.println("Stock minimum : "+art.stockMinimum);
    }// پایان نمایش

     // ------------------------خطا
    public static void erreur(String msg, int exitCode){
                System.err.println(msg);
                System.exit(exitCode);
    }// پایان خطا
}// پایان کلاس

در اینجا نمونه‌ای از خروجی آورده شده است:

E:\data\serge\JAVA\random>java test5
code : a100
nom : velo
prix : 1000.0
Stock actuel : 100
Stock minimum : 0
code : b100
nom : pompe
prix : 65.0
Stock actuel : 6
Stock minimum : 0
code : c100
nom : arc
prix : 867.0
Stock actuel : 10
Stock minimum : 0
code : d100
nom : fleches - lot de 6
prix : 450.0
Stock actuel : 12
Stock minimum : 0
code : e100
nom : jouet
prix : 10.0
Stock actuel : 2
Stock minimum : 0

E:\data\serge\JAVA\random>more data.text
a100:velo:1000.0:100:0
b100:pompe:65.0:6:0
c100:arc:867.0:10:0
d100:fleches - lot de 6:450.0:12:0
e100:jouet:10.0:2:0

4.10.7. دسترسی مستقیم به سوابق

این برنامهٔ نهایی نشان می‌دهد چگونه به‌طور مستقیم به سوابق یک فایل دودویی دسترسی پیدا کنید. این برنامه رکورد را از فایلی به نام data.bin نمایش می‌دهد که شماره‌اش به‌عنوان پارامتر ارسال می‌شود؛ رکورد اول شمارهٔ ۱ دارد.

//کلاس‌های واردشده
import java.io.*;
import java.util.*;

public class test6{

// فایل متنی --> فایل باینری

     //ساختار مقاله
    private static class article{
         // تعریف ساختار
        public String code;
        public String nom;
        public double prix;
        public int stockActuel;
        public int stockMinimum;
  }//کلاس مقاله

     // اصلی
    public static void main(String[] args){

       //بررسی آرگومان‌ها
      int nbArguments=args.length;
      String syntaxe="syntaxe : pg numéro_de_fiche";
      if(nbArguments!=1)
          erreur(syntaxe,20);
     //بررسی شماره رکورد اصلی
      int numRecord=0;
      try{
          numRecord=Integer.parseInt(args[0]);
      } catch(Exception e){
          erreur(syntaxe+"\nNuméro de fiche incorrect",21);
      }

       // باز کردن فایل باینری برای خواندن
    RandomAccessFile dataBin=null;
      try{
          dataBin=new RandomAccessFile("data.bin","r");
      } catch (Exception E){
          erreur("Impossible d'ouvrir le fichier data.bin en lecture",1);
      }

       // حرکت به رکورد مورد نظر
      try{
          dataBin.seek((numRecord-1)*40);
      } catch (Exception e){
          erreur("La fiche "+numRecord+" n'existe pas",23);
      }

       // خواندن آن
    article art=new article();
      try{
          lire(dataBin,art);
      } catch (Exception e){
          erreur("Erreur lors de la lecture de l'enregistrement "+numRecord,2);
      }

       // آن را نمایش دهید
      affiche(art);

       // تمام
      try{
          dataBin.close();
      } catch (Exception E){
          erreur("Impossible de fermer le fichier data.bin",2);
      }//try-catch

  }//پایان تابع main

    // خواندن متد
    public static void lire(RandomAccessFile fic, article art) throws IOException{
       // کد را بخوانید
        art.code="";
        for(int i=0;i<4;i++) art.code+=(char)fic.readByte();
    // نام
        art.nom="";
        for(int i=0;i<20;i++) art.nom+=(char)fic.readByte();
        art.nom=art.nom.trim();
    // قیمت
        art.prix=fic.readDouble();
    // سطوح موجودی
        art.stockActuel=fic.readInt();
        art.stockMinimum=fic.readInt();
    }// پایان نوشتن

     // ---------------------نمایش
    public static void affiche(article art){
        System.out.println("code : "+art.code);
        System.out.println("nom : "+art.nom);
        System.out.println("prix : "+art.prix);
        System.out.println("Stock actuel : "+art.stockActuel);
        System.out.println("Stock minimum : "+art.stockMinimum);
    }// پایان نمایش

     // ------------------------خطا
    public static void erreur(String msg, int exitCode){
                System.err.println(msg);
                System.exit(exitCode);
    }// پایان خطا
}// پایان کلاس

در اینجا چند نمونه از خروجی آورده شده است:

E:\data\serge\JAVA\random>java test6 2
code : b100
nom : pompe
prix : 65.0
Stock actuel : 6
Stock minimum : 0

E:\data\serge\JAVA\random>java.bat test6 20
Erreur lors de la lecture de l'enregistrement 20

4.11. استفاده از عبارت‌های منظم

4.11.1. پکیج java.util.regex

پکیج java.util.regex امکان استفاده از عبارت‌های منظم را فراهم می‌کند. این عبارت‌ها به شما اجازه می‌دهند تا قالب یک رشته کاراکتری را اعتبارسنجی کنید. به عنوان مثال، می‌توانید بررسی کنید که آیا رشته‌ای که نشان‌دهنده یک تاریخ است، واقعاً در قالب dd/mm/yy قرار دارد. برای این کار، شما از یک الگو استفاده کرده و رشته را با آن الگو مقایسه می‌کنید. در این مثال، d، m و y باید اعداد باشند. الگوی یک فرمت تاریخ معتبر بنابراین «\d\d/\d\d/\d\d» است، که در آن نماد \d نشان‌دهنده یک رقم است. نمادهایی که می‌توان در یک الگو استفاده کرد به شرح زیر است (مستندات مایکروسافت):

Character
توضیحات
\
کاراکتر زیر را به‌عنوان یک کاراکتر ویژه یا تحت‌اللفظی علامت‌گذاری کنید. برای مثال، «n» معادل کاراکتر «n» است. «\n» معادل کاراکتر خط جدید است. توالی «\\» معادل «\» است، در حالی که «\()» معادل «(» است.
^
با شروع ورودی مطابقت دارد.
$
با انتهای ورودی مطابقت دارد.
*
با کاراکتر قبلی صفر یا چند بار مطابقت دارد. بنابراین، 'zo*' با 'z' یا 'zoo' مطابقت دارد.
+
با کاراکتر قبلی یک یا چند بار مطابقت دارد. برای مثال، «zo+» با «zoo» مطابقت دارد، اما با «z» مطابقت ندارد.
؟
با کاراکتر قبلی صفر یا یک بار مطابقت دارد. برای مثال، «a?ve?» با «ve» در «lever» مطابقت دارد.
.
هر کاراکتر منفردی را مطابقت می‌دهد، به جز کاراکتر خط جدید.
(الگو)
به دنبال modèle می‌گردد و تطبیق را ذخیره می‌کند. زیر رشته‌ی تطبیق‌شده را می‌توان از مجموعه Matches حاصل، با استفاده از آیتم [0]...[n] استخراج کرد. برای یافتن تطابق‌هایی که شامل کاراکترها در داخل پرانتز ( ) هستند، از "\(" یا "\)" استفاده کنید.
x|y
مطابقت می‌کند با x یا y. برای مثال، "z|foot" با "z" یا "foot" مطابقت دارد. "(z|f)oo" با "zoo" یا "foo" مطابقت دارد.
{n}
n یک عدد صحیح غیرمنفی است. دقیقاً به همان تعداد n بار با کاراکتر مطابقت دارد. برای مثال، «o{2}» با «o» در «Bob» مطابقت ندارد، اما با دو «o» اول در «fooooot» مطابقت دارد.
{n,}
n یک عدد صحیح غیرمنفی است. حداقل n بار با این کاراکتر مطابقت دارد. برای مثال، «o{2,}» با «o» در «Bob» مطابقت ندارد، اما با تمام «o»ها در «fooooot» مطابقت دارد. «o{1,}» معادل «o+» و «o{0,}» معادل «o*» است.
{n,m}
m و n اعداد صحیح غیرمنفی هستند. حداقل n و حداکثر m بار با کاراکتر مطابقت دارد. برای مثال، «o{1,3}» با سه «o» اول در «foooooot» مطابقت دارد و «o{0,1}» معادل «o؟» است.
[xyz]
مجموعه کاراکترها. یکی از کاراکترهای مشخص‌شده را مطابقت می‌دهد. برای مثال، «[abc]» با «a» در «plat» مطابقت دارد.
[^xyz]
مجموعه کاراکتر منفی. با هر کاراکتری که در لیست ذکر نشده مطابقت دارد. برای مثال، «[^abc]» با «p» در «plat» مطابقت دارد.
[a-z]
محدوده کاراکتری. با هر کاراکتری که در محدوده مشخص‌شده قرار داشته باشد مطابقت دارد. برای مثال، "[a-z]" با هر حرف کوچک الفبایی بین "a" و "z" مطابقت دارد.
[^m-z]
محدوده کاراکتری منفی. با هر کاراکتری مطابقت دارد که در محدوده مشخص‌شده یافت نشود. برای مثال، "[^m-z]" با هر کاراکتری مطابقت دارد که بین "m" و "z" یافت نشود.
\b
مطابقت می‌دهد با مرز کلمه، یعنی موقعیت بین یک کلمه و یک فاصله. برای مثال، "er\b" با "er" در "lever" مطابقت دارد، اما با "er" در "verbe" مطابقت ندارد.
\B
یک مرز را مطابقت می‌دهد که نمایانگر یک کلمه نیست. «en*t\B» با «ent» در «bien entendu» مطابقت دارد.
\d
با یک کاراکتر نمایانگر رقم مطابقت دارد. معادل [0-9].
\D
مطابقت می‌دهد با یک کاراکتر که عدد نیست. معادل [^0-9] است.
\f
نماینده کاراکتر فرستنده فرم است.
\n
نشان‌دهنده کاراکتر خط جدید است.
\r
معادل کاراکتر بازگشت به خانه.
\s
هرگونه فضای خالی، از جمله فاصله، تب، شکست صفحه و غیره را مطابقت می‌دهد. معادل "[ \f\n\r\t\v]".
\S
هر کاراکتر غیرفاصله‌ای را مطابقت می‌دهد. معادل "[^ \f\n\r\t\v]".
\t
با کاراکتر تب مطابقت دارد.
\v
با کاراکتر تب عمودی مطابقت دارد.
\w
هر کاراکتری را که نمایانگر یک کلمه باشد، از جمله زیرخطی (_)، مطابقت می‌دهد. معادل "[A-Za-z0-9_]".
\W
هر کاراکتری را که نمایانگر یک کلمه نیست مطابقت می‌دهد. معادل "[^A-Za-z0-9_]".
\num
مطابق با num است، که در آن num یک عدد صحیح مثبت است. به تطابق‌های ذخیره‌شده اشاره دارد. برای مثال، «(.)\1» معادل دو کاراکتر یکسان متوالی است.
\n
معادل n است، که در آن n یک مقدار فرار اکتال است. مقادیر فرار اکتال باید شامل ۱، ۲ یا ۳ رقم باشند. به عنوان مثال، «\11» و «\011» هر دو به یک کاراکتر تب (tab) مربوط می‌شوند. "\0011" معادل "\001" و "1" است. مقادیر فرار اکتال نباید از ۲۵۶ تجاوز کنند. در صورت تجاوز، تنها دو رقم اول در عبارت در نظر گرفته می‌شوند. امکان استفاده از کدهای ASCII در عبارات باقاعده را فراهم می‌کند.
\xn
مطابق با n است، که در آن n یک مقدار فرار هگزادسیمال است. مقادیر فرار هگزادسیمال باید از دو رقم تشکیل شوند. برای مثال، "\x41" معادل "A" است. "\x041" معادل "\x04" و "1" است. امکان استفاده از کدهای ASCII در عبارت‌های منظم را فراهم می‌کند.

یک عنصر در یک الگو ممکن است یک یا چند بار ظاهر شود. بیایید به چند مثال مربوط به نماد \d که نماینده یک رقم است، نگاهی بیندازیم:

الگو
به معنای
\d
یک رقم
\d؟
۰ یا ۱ رقم
*اعداد*
صفر یا بیشتر رقم
اعداد مثبت
۱ یا چند رقم
\d{2}
۲ رقم
\d{3,}
حداقل ۳ رقم
\d{5,7}
بین ۵ تا ۷ رقم

اکنون بیایید الگویی را در نظر بگیریم که قادر به توصیف قالب مورد انتظار برای یک رشته باشد:

رشته مقصد
الگو
یک تاریخ به فرمت dd/mm/yy
\d{2}/\d{2}/\d{2}
یک زمان در قالب ساعت:دقیقه:ثانیه
\d{2}:\d{2}:\d{2}
یک عدد صحیح بدون علامت
\d+
یک دنباله از فاصله، که ممکن است خالی باشد
\s*
یک عدد صحیح بدون علامت که ممکن است قبل یا بعد از آن فضاها قرار داشته باشد
\s*\d+\s*
یک عدد صحیح که ممکن است علامت‌دار باشد و قبل یا بعد از آن فاصله‌ها قرار گیرند
\s*[+|-]?\s*\d+\s*
یک عدد حقیقی بدون علامت که ممکن است قبل یا بعد از آن فضا باشد
\s*\d+(.\d*)?\s*
یک عدد حقیقی که ممکن است علامت‌دار باشد و قبل یا بعد از آن فاصله‌ها قرار گیرند
\s*[+|]?\s*\d+(.\d*)?\s*
یک رشته حاوی کلمه «just»
\bجوست\b
  

می‌توانید مشخص کنید که الگو را در کجای رشته جستجو کنید:

الگو
به معنی
^pattern
الگو در ابتدای رشته آغاز می‌شود
pattern$
الگو رشته را پایان می‌دهد
^الگو$
الگو رشته را شروع و پایان می‌دهد
الگو
الگو در هر جای رشته، از ابتدا جستجو می‌شود.
رشته جستجو
الگو
یک رشته که با علامت تعجب به پایان می‌رسد
!$
یک رشته که با نقطه پایان می‌یابد
\.$
یک رشته که با توالی // آغاز می‌شود
^//
یک رشته متشکل از یک کلمه واحد، که اختیاریاً قبل یا بعد از آن فاصله‌ها قرار می‌گیرند
^[ \t*]+[ \t*]$
یک رشته متشکل از دو کلمه، که اختیاریاً می‌تواند قبل یا بعد از آن فضا باشد
^\s*\w+\s*\w+\s*$
یک رشته حاوی کلمه 'secret'
\bsecret\b

زیرالگوها در یک الگو را می‌توان «استخراج» کرد. بنابراین، نه تنها می‌توانیم بررسی کنیم که آیا یک رشته با الگوی خاصی مطابقت دارد، بلکه می‌توانیم عناصر مربوط به زیرالگوهای الگو که در کروشه‌ها قرار گرفته‌اند را از آن رشته استخراج کنیم. برای مثال، اگر در حال تحلیل رشته‌ای هستیم که تاریخ را به فرمت dd/mm/yy در خود دارد و همچنین می‌خواهیم عناصر dd، mm و yy را از آن تاریخ استخراج کنیم، از الگوی (\d\d)/(\d\d)/(\d\d) استفاده خواهیم کرد.

4.11.2. بررسی اینکه آیا یک رشته با یک الگوی مشخص مطابقت دارد

کلاس Pattern به شما امکان می‌دهد بررسی کنید که آیا یک رشته با یک الگوی داده‌شده مطابقت دارد یا خیر. برای این کار، از متد استاتیک

boolean Matches(String modèle, String chaine)

در اینجا: modèle: قالب مورد بررسی، chaine: رشته‌ای که باید با قالب مقایسه شود. نتیجه مقدار بولی true است اگر رشته با قالب مطابقت داشته باشد، وگرنه false.

در اینجا یک مثال آمده است:

import java.io.*;
import java.util.regex.*;

// پردازش عبارت منظم
public class regex1 {
  public static void main(String[] args){
    // یک عبارت منظم الگویی
    String modèle1="^\\s*\\d+\\s*$";
    // مقایسهٔ یک نمونه با الگو
    String exemplaire1="  123  ";
    if (Pattern.matches(modèle1,exemplaire1)){
      affiche("["+exemplaire1 + "] correspond au modèle ["+modèle1+"]");
    }else{
      affiche("["+exemplaire1 + "] ne correspond pas au modèle ["+modèle1+"]");
    }//اگر
    String exemplaire2="  123a  ";
    if (Pattern.matches(modèle1,exemplaire2)){
      affiche("["+exemplaire2 + "] correspond au modèle ["+modèle1+"]");
    }else{
      affiche("["+exemplaire2 + "] ne correspond pas au modèle ["+modèle1+"]");
    }//اگر
  }//اصلی

  public static void affiche(String msg){
    System.out.println(msg);
  }//نمایش
}//کلاس

و نتایج اجرا:

[  123  ] correspond au modèle [^\s*\d+\s*$]
[  123a  ] ne correspond pas au modèle [^\s*\d+\s*$]

توجه داشته باشید که در الگوی "^\s*\d+\s*$"، کاراکتر \ باید به دلیل تفسیر خاص جاوا از این کاراکتر، دو برابر نوشته شود. بنابراین ما می‌نویسیم: String pattern1 = "^\\s*\\d+\\s*$";

4.11.3. یافتن تمام عناصری در یک رشته که با یک الگو مطابقت دارند

الگوی "\d+" و رشته " 123 456 789 " را در نظر بگیرید. این الگو در سه مکان مختلف در داخل رشته یافت می‌شود. کلاس‌های Pattern و Matcher به شما امکان می‌دهند تا موارد مختلف یک الگو را در داخل یک رشته بازیابی کنید. کلاس Pattern کلاسی است که با عبارت‌های منظم کار می‌کند. یک عبارت منظم که بیش از یک بار استفاده شود، باید «کامپایل» شود. این کار جستجو برای الگو در رشته‌ها را سرعت می‌بخشد. متد استاتیک compile این وظیفه را انجام می‌دهد:

public static Pattern compile(String regex)

این متد رشته الگو را به عنوان پارامتر می‌پذیرد و یک شیء Pattern را برمی‌گرداند. برای مقایسه الگوی یک شیء Pattern با یک رشته کاراکتری، از کلاس Matcher استفاده می‌شود. این کلاس امکان مقایسه یک الگو با یک رشته کاراکتری را فراهم می‌کند. از یک شیء Pattern می‌توان با استفاده از متد matcher یک شیء Matcher به دست آورد:

public Matcher matcher(CharSequence input)

input رشته‌ای است که باید با الگو مقایسه شود.

بنابراین، برای مقایسه الگوی "\d+" با رشته " 123 456 789 "، می‌توانید یک شیء Matcher را به صورت زیر ایجاد کنید:

Pattern regex=Pattern.compile("\\d+");
Matcher résultats=regex.matcher("  123  456  789  ");

با استفاده از شی résultats قبلی، می‌توانیم رخدادهای مختلف الگو را در رشته بازیابی کنیم. برای این کار، از متدهای suivantes کلاس Matcher استفاده می‌کنیم:

public boolean find()
public String group()
public int start()
public Matcher reset()

روش find در رشته‌ای که در حال تجزیه است، اولین وقوع الگو را جستجو می‌کند. یک فراخوانی دوم از find وقوع بعدی را جستجو خواهد کرد. و به همین ترتیب. این متد در صورت یافتن الگو مقدار true را برمی‌گرداند و در غیر این صورت مقدار false را. بخش مربوط به آخرین مورد یافت‌شده توسط find با استفاده از متد group و موقعیت آن با استفاده از متد start به دست می‌آید. بنابراین، با ادامه مثال قبلی، اگر بخواهیم تمام رخدادهای الگوی "\d+" را در رشته " 123 456 789 " نمایش دهیم، خواهیم نوشت:

while(résultats.find()){
    System.out.println("séquence " + résultats.group() + " trouvée en position " + résultats.start());
    }//در حالی که

متد reset شیء Matcher را به ابتدای رشته‌ای که با الگو مقایسه می‌شود، بازنشانی می‌کند. این بدان معناست که متد find سپس اولین وقوع الگو را دوباره پیدا خواهد کرد.

در اینجا یک مثال کامل آورده شده است:

import java.io.*;
import java.util.regex.*;

// پردازش عبارت‌های منظم
public class regex2 {
  public static void main(String[] args){
    // چندین وقوع الگو در نمونه
    String modèle2="\\d+";
    Pattern regex2=Pattern.compile(modèle2);
    String exemplaire3="  123  456 789";
    //جستجو برای رخدادهای الگو در نمونه
    Matcher matcher2=regex2.matcher(exemplaire3);
    while(matcher2.find()){
      affiche("séquence " + matcher2.group() + " trouvée en position " + matcher2.start());
    }//در حالی که
  }//اصلی

  public static void affiche(String msg){
    System.out.println(msg);
  }//نمایش می‌دهد
}//مرتب‌سازی

نتایج اجرای حکم:

Modèle=[\d+],exemplaire=[  123  456  789 ]
Il y a 3 occurrences du modèle dans l'exemplaire
123 en position 2
456 en position 7
789 en position 12

4.11.4. استخراج بخش‌هایی از یک الگو

زیربخش‌های یک الگو را می‌توان «استخراج» کرد. این بدان معناست که نه تنها می‌توانیم بررسی کنیم که آیا یک رشته با الگوی خاصی مطابقت دارد، بلکه می‌توانیم عناصر مربوط به زیربخش‌های الگو که در داخل پرانتز قرار گرفته‌اند را از آن رشته استخراج کنیم. برای مثال، اگر در حال تحلیل رشته‌ای هستیم که تاریخ را به فرمت dd/mm/yy دارد و همچنین می‌خواهیم عناصر dd، mm و yy را از آن تاریخ استخراج کنیم، از الگوی (\d\d)/(\d\d)/(\d\d) استفاده خواهیم کرد.

بیایید به مثال زیر نگاه کنیم:

import java.io.*;
import java.util.regex.*;

// پردازش عبارت‌های منظم
public class regex3 {
  public static void main(String[] args){
    // عناصر ضبط‌شده در قالب
    String modèle3="(\\d\\d):(\\d\\d):(\\d\\d)";
    Pattern regex3=Pattern.compile(modèle3);
    String exemplaire4="Il est 18:05:49";
    //اعتبارسنجی قالب
    Matcher résultat=regex3.matcher(exemplaire4);
    if (résultat.find()){
      // مثال با قالب مطابقت دارد
      affiche("L'exemplaire ["+exemplaire4+"] correspond au modèle ["+modèle3+"]");
      //نمایش گروه‌ها
      for (int i=0;i<=résultat.groupCount();i++){
        affiche("groupes["+i+"]=["+résultat.group(i)+"] en position "+résultat.start(i));
      }//برای
      }else{
        // مثال با قالب مطابقت ندارد
        affiche("L'exemplaire["+exemplaire4+" ne correspond pas au modèle ["+modèle3+"]");
      }
    }//اصلی

    public static void affiche(String msg){
      System.out.println(msg);
    }//نمایش می‌دهد
}//دسته‌بندی می‌کند

اجرای این برنامه نتایج زیر را تولید می‌کند:

L'exemplaire [Il est 18:05:49] correspond au modèle [(\d\d):(\d\d):(\d\d)]
groupes[0]=[18:05:49] en position 7
groupes[1]=[18] en position 7
groupes[2]=[05] en position 10
groupes[3]=[49] en position 13

تغییر در بخش زیرین کد است:

    // تأیید قالب
    Matcher résultat=regex3.matcher(exemplaire4);
    if (résultat.find()){
      // مثال با قالب مطابقت دارد
      affiche("L'exemplaire ["+exemplaire4+"] correspond au modèle ["+modèle3+"]");
      //گروه‌ها نمایش داده می‌شوند
      for (int i=0;i<=résultat.groupCount();i++){
        affiche("groupes["+i+"]=["+résultat.group(i)+"] en position "+résultat.start(i));
      }//برای
      }else{
        // مثال با قالب مطابقت ندارد
        affiche("L'exemplaire["+exemplaire4+" ne correspond pas au modèle ["+modèle3+"]");
      }

رشته exemplaire4 با استفاده از روش find با الگوی regex3 مقایسه می‌شود. یک نمونه از الگوی regex3 سپس در رشته exemplaire4 یافت می‌شود. اگر الگو شامل زیرمجموعه‌هایی باشد که در کروشه‌ها محصور شده‌اند، این زیرمجموعه‌ها از طریق روش‌های مختلف کلاس Matcher قابل دسترسی هستند:


public int groupCount()
public String group(int group)
public int start(int group)

متد groupCount تعداد زیرمجموعه‌های یافت‌شده در مدل را برمی‌گرداند، و group(i) زیرمجموعه شماره i را برمی‌گرداند. این در رشته‌ای در موقعیتی که توسط start(i) مشخص شده است، یافت می‌شود. بنابراین، در مثال:

L'exemplaire [Il est 18:05:49] correspond au modèle [(\d\d):(\d\d):(\d\d)]
groupes[0]=[18:05:49] en position 7
groupes[1]=[18] en position 7
groupes[2]=[05] en position 10
groupes[3]=[49] en position 13

اولین فراخوانی متد find رشته 18:05:49 را پیدا کرده و به‌طور خودکار سه زیرمجموعه تعریف‌شده توسط پرانتزها در قالب، یعنی 18، 05 و 49 را ایجاد می‌کند.

4.11.5. یک برنامه آموزشی

یافتن عبارت منظم (regular expression) که به ما امکان می‌دهد بررسی کنیم آیا یک رشته با یک الگوی خاص مطابقت دارد یا خیر، گاهی اوقات می‌تواند یک چالش واقعی باشد. برنامه زیر به شما امکان می‌دهد تمرین کنید. این برنامه از شما یک الگو و یک رشته می‌خواهد و سپس نشان می‌دهد که آیا آن رشته با الگو مطابقت دارد یا خیر.

import java.io.*;
import java.util.regex.*;

// پردازش عبارت‌های منظم
public class regex4 {
  public static void main(String[] args){

    // داده‌ها
    String modèle=null,chaine=null;
    Pattern regex=null;
    BufferedReader IN=null;
    Matcher résultats=null;
    int nbOccurrences=0;

    // پردازش خطا
    try{
      // از کاربر خواسته می‌شود قالب‌ها و نمونه‌هایی را که باید با این مورد مقایسه شوند، مشخص کند
      while(true){
        //جریان ورودی
        IN=new BufferedReader(new InputStreamReader(System.in));
        // قالب درخواست می‌شود
        System.out.print("Tapez le modèle à tester ou fin pour arrêter :");
        modèle=IN.readLine();
        // تمام شد؟
        if(modèle.trim().toLowerCase().equals("fin")) break;
        // بیان منظم ایجاد می‌شود
        regex=Pattern.compile(modèle);
        //از کاربر خواسته می‌شود نمونه‌هایی را که باید با الگو مقایسه شوند، انتخاب کند
        while(true){
          System.out.print("Tapez la chaîne à comparer au modèle ["+modèle+"] ou fin pour arrêter :");
          chaine=IN.readLine();
          // تمام؟
          if(chaine.trim().toLowerCase().equals("fin")) break;
          // شیء تطبیق‌دهنده را ایجاد کنید
          résultats=regex.matcher(chaine);
          //جستجوی موارد الگو
          nbOccurrences=0;
          while(résultats.find()){
            //یک نمونه یافت شد
            nbOccurrences++;
            // نمایش آن
            System.out.println("J'ai trouvé la correspondance ["+résultats.group()
            +"] en position "+résultats.start());
            //نمایش زیرعناصر
            if(résultats.groupCount()!=1){
              for(int j=1;j<=résultats.groupCount();j++){
                System.out.println("\tsous-élément ["+résultats.group(j)+"] en position "+
                  résultats.start(j));
              }//برای j
            }//اگر
            // سلسله بعدی
          }//while(QZXW2HTMLCcsOpc3VsdGF0cy.maW5kZQX())
          //آیا حداقل یک مورد یافت شده است؟
          if(nbOccurrences==0){
            System.out.println("Je n'ai pas trouvé de correspondance au modèle ["+modèle+"]");
          }//if
          //الگوی بعدی
        }//while(true)
      }//while(true)
    }catch(Exception ex){
      //خطا
      System.err.println("Erreur : "+ex.getMessage());
      //پایان با خطا
      System.exit(1);
    }//try-catch
    // پایان
    System.exit(0);
  }//کلاس اصلی
}//کلاس

در اینجا نمونه‌ای از خروجی آورده شده است:

Tapez le modèle à tester ou fin pour arrêter :\d+
Tapez la chaîne à comparer au modèle [\d+] ou fin pour arrêter :123 456 789
J'ai trouvé la correspondance [123] en position 0
J'ai trouvé la correspondance [456] en position 4
J'ai trouvé la correspondance [789] en position 8
Tapez la chaîne à comparer au modèle [\d+] ou fin pour arrêter :fin

Tapez le modèle à tester ou fin pour arrêter :(\d\d):(\d\d)
Tapez la chaîne à comparer au modèle [(\d\d):(\d\d)] ou fin pour arrêter :14:15
abcd 17:18 xyzt
J'ai trouvé la correspondance [14:15] en position 0
        sous-élément [14] en position 0
        sous-élément [15] en position 3
J'ai trouvé la correspondance [17:18] en position 11
        sous-élément [17] en position 11
        sous-élément [18] en position 14
Tapez la chaîne à comparer au modèle [(\d\d):(\d\d)] ou fin pour arrêter :fin

Tapez le modèle à tester ou fin pour arrêter :^\s*\d+\s*$
Tapez la chaîne à comparer au modèle [^\s*\d+\s*$] ou fin pour arrêter :  1456
J'ai trouvé la correspondance [  1456] en position 0
Tapez la chaîne à comparer au modèle [^\s*\d+\s*$] ou fin pour arrêter :fin

Tapez le modèle à tester ou fin pour arrêter :^\s*(\d+)\s*$
Tapez la chaîne à comparer au modèle [^\s*(\d+)\s*$] ou fin pour arrêter :1456
J'ai trouvé la correspondance [1456] en position 0
        sous-élément [1456] en position 0
Tapez la chaîne à comparer au modèle [^\s*(\d+)\s*$] ou fin pour arrêter :abcd 1
456
Je n'ai pas trouvé de correspondances
Tapez la chaîne à comparer au modèle [^\s*(\d+)\s*$] ou fin pour arrêter :fin

Tapez le modèle à tester ou fin pour arrêter :fin

4.11.6. متد split کلاس Pattern

یک رشته را در نظر بگیرید که از فیلدهایی تشکیل شده و با یک جداکننده تعریف‌شده توسط یک عبارت منظم از هم جدا شده‌اند. برای مثال، اگر فیلدها با کاراکتر , از هم جدا شده و قبل یا بعد از آن هر تعداد فاصله قرار داشته باشد، عبارت منظم مدل‌سازی جداکننده فیلد به شکل "\s*,\s*" خواهد بود. متد split کلاس Pattern به ما امکان می‌دهد فیلدها را در یک آرایه بازیابی کنیم:


public String[] split(CharSequence input)

رشته input به فیلدها تقسیم می‌شود که توسط جداکننده‌ای مطابق با الگوی شیء فعلی Pattern از هم جدا شده‌اند. برای بازیابی فیلدها از یک سطر که جداکننده فیلدها یک ویرگول است که قبل یا بعد از آن هر تعداد فضای خالی قرار دارد، می‌نویسیم:

    // یک خط
    String ligne="abc  ,, def  , ghi";
    // یک قالب
    Pattern modèle=Pattern.compile("\\s*,\\s*");
    // تفکیک خط به فیلدها
    String[] champs=modèle.split(ligne);

همان نتیجه را می‌توان با استفاده از روش split از کلاس String به دست آورد:


public String[] split(String regex)

در اینجا یک برنامه آزمایشی آورده شده است:

import java.io.*;
import java.util.regex.*;

// پردازش عبارت‌های منظم
public class split1 {
  public static void main(String[] args){
    //یک خط
    String ligne="abc  ,, def  , ghi";
    //یک قالب
    Pattern modèle=Pattern.compile("\\s*,\\s*");
    // تفکیک خط به فیلدها
    String[] champs=modèle.split(ligne);
    //نمایش
    for(int i=0;i<champs.length;i++){
      System.out.println("champs["+i+"]=["+champs[i]+"]");
    }//برای
    // راه دیگری برای انجام آن
    champs=ligne.split("\\s*,\\s*");
    //نمایش
    for(int i=0;i<champs.length;i++){
      System.out.println("champs["+i+"]=["+champs[i]+"]");
    }//برای
  }//اصلی
}//کلاس

نتایج اجرا:

champs[0]=[abc]
champs[1]=[]
champs[2]=[def]
champs[3]=[ghi]
champs[0]=[abc]
champs[1]=[]
champs[2]=[def]
champs[3]=[ghi]

4.12. تمرین‌ها

4.12.1. تمرین ۱

در یونیکس، برنامه‌ها اغلب به صورت زیر فراخوانی می‌شوند:

$ pg -o1 v1 v2 ... -o2 v3 v4

که در آن -oi نمایانگر یک گزینه و vi نمایانگر مقداری است که با آن گزینه مرتبط است. ما می‌خواهیم یک کلاس options بسازیم که رشته آرگومان -o1 v1 v2 ... -o2 v3 v4 … را تحلیل کند تا ساختارهای زیر را ایجاد نماید:

optionsValides
یک دیکشنری (Hashtable) که کلیدهای آن گزینه‌های معتبر oi هستند. مقدار مرتبط با کلید oi یک بردار (Vector) است که عناصر آن مقادیر v1 v2 … مرتبط با گزینه -oi می‌باشند.
optionsInvalides
یک دیکشنری (Hashtable) که کلیدهای آن گزینه‌های oi نامعتبر هستند. مقدار مرتبط با کلید oi یک بردار (Vector) است که عناصر آن مقادیر v1، v2 … مرتبط با گزینه -oi هستند.
optionsSans
رشته (String) که شامل مقادیر vi است که با هیچ گزینه‌ای مرتبط نیستند
erreur
یک عدد صحیح برابر با 0 اگر در خط آرگومان خطایی وجود نداشته باشد، در غیر این صورت چیز دیگری:
1: پارامترهای فراخوانی نامعتبر وجود دارد
۲: گزینه‌های نامعتبر وجود دارد
4: مقادیری وجود دارند که با هیچ گزینه‌ای مرتبط نیستند
اگر چندین نوع خطا وجود داشته باشد، این مقادیر تجمعی هستند.

یک شیء options را می‌توان به چهار روش مختلف ساخت:

public options (String arguments, String optionsAcceptables)

arguments
آرگومان‌های خط فرمان -o1 v1 v2 ... -o2 v3 v4 … برای تجزیه و تحلیل
optionsAcceptables
فهرست گزینه‌های oi قابل قبول

نمونه فراخوانی: options opt=new options("-u u1 u2 u3 -g g1 g2 -x","-u -g");

در اینجا، هر دو آرگومان رشته‌ای هستند. مواردی که این رشته‌ها به کلمات تقسیم شده و در آرایه‌ای از رشته‌ها قرار گرفته‌اند نیز پذیرفته می‌شوند. این امر به سه سازندهٔ دیگر نیاز دارد:

public options (String[] arguments, String optionsAcceptables)
public options (String arguments, String[] optionsAcceptables)
public options (String[] arguments, String[] optionsAcceptables)

کلاس options دارای رابط زیر خواهد بود (getters):

public Hashtable getOptionsValides()

ارجاع به آرایه optionsValides را که هنگام ایجاد شیء گزینه‌ها ایجاد شده است، برمی‌گرداند

public Hashtable getOptionsInvalides()

ارجاع به آرایه optionsInvalides را که هنگام ایجاد شیء گزینه‌ها ایجاد شده است، بازمی‌گرداند

public String getOptionsSans()

ارجاع به رشته optionsSans را بازمی‌گرداند که هنگام ایجاد شیء گزینه‌ها ساخته شده است

public int getErreur()

مقدار ویژگی error را که هنگام ایجاد شیء گزینه‌ها ایجاد شده است، برمی‌گرداند

public String toString()

اگر خطایی وجود نداشته باشد، مقادیر ویژگی‌های optionsValides، optionsInvalides، optionsSans را نمایش می‌دهد؛ در غیر این صورت، شماره خطا را نمایش می‌دهد.

در اینجا یک برنامهٔ نمونه آورده شده است:


import java.io.*;
//گزینه‌های وارداتی؛

public class test1{
  
  
  public static void main (String[] arg){
    
    // باز کردن جریان ورودی
    String ligne;
    BufferedReader IN=null;
    try{
      IN=new BufferedReader(new InputStreamReader(System.in));
    } catch (Exception e){
      affiche(e);
      System.exit(1);
    }
    // خواندن آرگومان‌های سازندهٔ (String, string)
    String options=null;
    String optionsAcceptables=null;
    while(true){
      System.out.print("Options : ");
      try{
        options=IN.readLine();
      } catch (Exception e){
        affiche(e);
        System.exit(2);
      }
      if(options.length()==0) break;
      System.out.print("Options acceptables: ");
      try{
        optionsAcceptables=IN.readLine();
      } catch (Exception e){
        affiche(e);
        System.exit(2);
      }
      System.out.println(new options(options,optionsAcceptables));
    }//پایان حلقه while
  }//پایان تابع main


public static void affiche(Exception e){
    System.err.println("Erreur : "+e);
  }

}//پایان کلاس

برخی نتایج:

C:\Serge\java\options>java test1
Options : 1 2 3 -a a1 a2 -b b1 -c c1 c2 c3 -b b2 b3
Options acceptables: -a -b
Erreur 6
Options valides :(-b,b1,b2,b3)  (-a,a1,a2)
Options invalides : (-c,c1,c2,c3)
Sans options : 1 2 3

4.12.2. تمرین ۲

ما می‌خواهیم یک کلاس stringtovector بسازیم که امکان انتقال محتویات یک شیء String به یک شیء Vector را فراهم کند. این کلاس از کلاس Vector مشتق خواهد شد:

class stringtovector extends Vector

و دارای سازندهٔ زیر خواهد بود:


    private void stringtovector(String S, String separateur, int[] tChampsVoulus,
            boolean strict){
        
        // یک بردار شامل فیلدهای رشته S ایجاد می‌کند
        // که شامل فیلدهایی است که توسط جداکننده از هم جدا شده‌اند
        // اگر separator=null باشد، رشته یک فیلد واحد تشکیل می‌دهد
        // فقط فیلدهایی که شاخص‌هایشان در آرایه tChampsVoulus هستند 
        // الزامی هستند. شاخص‌ها از ۱ شروع می‌شوند
        //اگر tChampsvoulus برابر با null یا دارای طول صفر باشد، همه فیلدها در نظر گرفته می‌شوند
        // اگر strict=true باشد، همه فیلدهای الزامی باید موجود باشند

کلاس دارای ویژگی خصوصی زیر خواهد بود:

        private int erreur;

این ویژگی توسط سازنده قبلی با مقادیر زیر تنظیم می‌شود:

0: ساخت با موفقیت انجام شد

4: برخی از فیلدهای الزامی وجود ندارند، با اینکه strict=true

کلاس همچنین دو متد خواهد داشت:

    public int getErreur()

که مقدار ویژگی خصوصی erreur را برمی‌گرداند.

    public String identite(){

که مقدار شیء را به صورت (خطا، عنصر ۱، عنصر ۲، …) نمایش می‌دهد، جایی که عناصر i، عناصر برداری هستند که از رشته ساخته شده‌اند.

یک برنامهٔ آزمایشی ممکن است به این شکل باشد:


import java.io.*;
//import stringtovector;

public class essai2{
  public static void main(String arg[]){
    int[] T1={1,3};
    System.out.println(new stringtovector("a : b : c :d:e",":",T1,true).identite());
    int[] T2={1,3,7};
    System.out.println(new stringtovector("a : b : c :d:e",":",T2,true).identite());
    int [] T3={1,4,7};
    System.out.println(new stringtovector("a : b : c :d:e",":",T3,false).identite());
    System.out.println(new stringtovector("a : b : c :d:e","",T1,false).identite());
    System.out.println(new stringtovector("a : b : c :d:e",null,T1,false).identite());
    int[] T4={1};
    System.out.println(new stringtovector("a : b : c :d:e","!",T4,true).identite());
    int[] T5=null;
    System.out.println(new stringtovector("a : b : c :d:e",":",T5,true).identite());
    System.out.println(new stringtovector("a : b : c :d:e",null,T5,true).identite());
    int[] T6=new int[0];
    System.out.println(new stringtovector("a : b : c :d:e","",T6,true).identite());
    int[] T7={1,3,4};
    System.out.println(new stringtovector("a  b  c d e"," ",T6,true).identite());
  }
}

نتایج:

(0,a,c)
(4,a,c)
(0,a,d)
(0,a : b : c :d:e)
(0,a : b : c :d:e)
(0,a : b : c :d:e)
(0,a,b,c,d,e)
(0,a : b : c :d:e)
(0,a : b : c :d:e)
(0,a,b,c,d,e)

چند نکته:

  1. برای تقسیم رشته S به فیلدها، از متد split در کلاس String استفاده کنید.
  2. میدان‌های S را در یک دیکشنری D قرار دهید که شاخص آن شماره میدان باشد
  3. از دیکشنری D تنها آن فیلدهایی را بازیابی کنید که کلید (شاخص) آن‌ها در آرایه tChampsVoulus موجود است.

4.12.3. تمرین ۳

ما می‌خواهیم سازنده زیر را به کلاس **stringtovector** اضافه کنیم:


public stringtovector(String S, String separateur, String sChampsVoulus,boolean strict){
        
        //یک بردار شامل فیلدهای رشته S ایجاد می‌کند
        //این رشته از فیلدهایی تشکیل شده که با جداکننده از هم جدا شده‌اند
        //اگر separator=null باشد، رشته یک فیلد واحد تشکیل می‌دهد
        //تنها فیلدهایی که شاخص‌هایشان در sChampsVoulus قرار دارند، الزامی هستند
        // شاخص‌ها از ۱ شروع می‌شوند
        //اگر sChampsvoulus برابر null یا "" باشد، همه فیلدها گنجانده می‌شوند
        // اگر strict=true باشد، همه فیلدهای الزامی باید موجود باشند

بنابراین فهرست فیلدهای مورد نظر به جای یک آرایه از اعداد صحیح (int[]) به صورت یک رشته (String) ذخیره می‌شود. ویژگی خصوصی کلاس erreur می‌تواند مقدار جدیدی به خود اختصاص دهد:

۲: رشتهٔ شاخص‌ها برای فیلدهای مورد نظر نادرست است

در اینجا یک برنامهٔ نمونه آورده شده است:


import java.io.*;
//import stringtovector;

public class essai1{
  public static void main(String arg[]){
    String champs=null;
    System.out.println(new stringtovector("a: b :c :d:e ",":","1 3",true).identite());
    System.out.println(new stringtovector("a: b :c :d:e ",":","1 3 7",true).identite());
    System.out.println(new stringtovector("a: b :c :d:e ",":","1 4 7",false).identite());
    System.out.println(new stringtovector("a: b :c :d:e ","","1 3",false).identite());
    System.out.println(new stringtovector("a: b :c :d:e ",null,"1 3",false).identite());
    System.out.println(new stringtovector("a: b :c :d:e ","!","1",true).identite());
    System.out.println(new stringtovector("a: b :c :d:e ",":","",true).identite());
    System.out.println(new stringtovector("a: b :c :d:e ",":",champs,true).identite());
    System.out.println(new stringtovector("a: b :c :d:e ",null,champs,true).identite());
    System.out.println(new stringtovector("a: b :c :d:e ","","",true).identite());
    System.out.println(new stringtovector("a: b :c :d:e ",":","1 !",true).identite());
    System.out.println(new stringtovector("a b c d       e "," ","1 3",false).identite());
  }
}

برخی نتایج:

(0,a,c)
(4,a,c)
(0,a,d)
(0,a: b :c :d:e)
(0,a: b :c :d:e)
(0,a: b :c :d:e)
(0,a,b,c,d,e)
(0,a,b,c,d,e)
(0,a: b :c :d:e)
(0,a: b :c :d:e)
(2)
(0,a,c)

چند نکته:

  1. برای این کار، باید با انتقال فیلدها از رشته sChampsVoulus به یک آرایه از اعداد صحیح، به سازنده قبلی بازگردید. برای این کار، sChampsVoulus را با استفاده از یک شی StringTokenizer به فیلدها تقسیم کنید، که ویژگی countTokens آن تعداد فیلدهای به‌دست‌آمده را بازمی‌گرداند. سپس می‌توانید یک آرایه از اعداد صحیح با اندازه مناسب ایجاد کرده و آن را با فیلدهای به‌دست‌آمده پر کنید.
  2. برای بررسی اینکه آیا یک فیلد عدد صحیح است، از متد Integer.parseInt برای تبدیل فیلد به عدد صحیح استفاده کنید و استثنایی را که در صورت امکان‌ناپذیر بودن این تبدیل ایجاد می‌شود، مدیریت کنید.

4.12.4. تمرین ۴

ما می‌خواهیم یک کلاس filetovector ایجاد کنیم که امکان انتقال محتویات یک فایل متنی به یک شیء Vector را فراهم کند. این کلاس از کلاس Vector مشتق خواهد شد:

class filetovector extends Vector

و دارای سازندهٔ زیر خواهد بود:


    // --------------------- سازنده 
    public filetovector(String nomFichier, String separateur, int [] tChampsVoulus,boolean strict, String tagCommentaire){
        
        // یک بردار شامل خطوط فایل متنی nomFichier ایجاد می‌کند
        //خطوط از فیلدهایی تشکیل شده‌اند که با جداکننده از هم جدا شده‌اند
        // اگر separator=null باشد، خط از یک فیلد واحد تشکیل شده است
        //تنها فیلدهایی که شاخص‌هایشان در tChampsVoulus قرار دارند، الزامی هستند
        // شاخص‌ها از ۱ شروع می‌شوند
        //اگر tChampsvoulus برابر null یا خالی باشد، همه فیلدها گنجانده می‌شوند
        // اگر strict=true باشد، همه فیلدهای الزامی باید موجود باشند
        // اگر اینطور نباشد، سطر ذخیره نمی‌شود و شاخص آن
        //در بردار lignesErronees قرار می‌گیرد
        //خطوط خالی نادیده گرفته می‌شوند
        // همچنین خطوطی که با tagCommentaire شروع می‌شوند نادیده گرفته می‌شوند اگر tagCommentaire != null

کلاس دارای ویژگی‌های خصوصی زیر خواهد بود:

        private int erreur=0;
        private Vector lignesErronees=null;

ویژگی erreur توسط سازنده قبلی با مقادیر زیر تنظیم شده است:

0: ساخت با موفقیت انجام شد

۱: فایل مورد پردازش باز نشد

4: برخی از فیلدهای مورد نیاز وجود ندارند، با وجود اینکه strict=true

8: یک خطای ورودی/خروجی هنگام پردازش فایل رخ داد

ویژگی lignesErronees یک آرایه است که عناصر آن شماره‌های خطوط خطا به صورت رشته‌های کاراکتری هستند. یک خط زمانی خطا در نظر گرفته می‌شود که نتواند در حالی که strict=true، فیلدهای مورد نیاز را فراهم کند.

کلاس همچنین دو متد خواهد داشت:

    public int getErreur()

که مقدار ویژگی خصوصی erreur را برمی‌گرداند.

    public String identite(){

که مقدار شیء را به صورت (خطا، عنصر 1، عنصر 2 …، (l1، l2، …)) نمایش می‌دهد، که در آن عناصر i، عناصر برداری هستند که از فایل ساخته شده‌اند و li شماره‌های خطوط دارای خطا می‌باشند.

در اینجا یک مثال آزمایشی آورده شده است:


import java.io.*;
//import filetovector;

public class test2{
  public static void main(String arg[]){
    int[] T1={1,3};
    System.out.println(new filetovector("data.txt",":",T1,false,"#").identite());
    System.out.println(new filetovector("data.txt",":",T1,true,"#").identite());
    System.out.println(new filetovector("data.txt","",T1,false,"#").identite());
    System.out.println(new filetovector("data.txt",null,T1,false,"#").identite());
    int[] T2=null;
    System.out.println(new filetovector("data.txt",":",T2,false,"#").identite());
    System.out.println(new filetovector("data.txt",":",T2,false,"").identite());
    int[] T3=new int[0];
    System.out.println(new filetovector("data.txt",":",T3,false,null).identite());
  }
}

نتایج اجرا:

[0,(0,a,c) (0,1,3) (0,azerty,cvf) (0,s)]
[4,(0,a,c) (0,1,3) (0,azerty,cvf),[5]]
[0,(0,a:b:c:d:e) (0,1 :2 : 3:  4: 5) (0,azerty : 1 : cvf : fff: qqqq) (0,s)]
[0,(0,a:b:c:d:e) (0,1 :2 : 3:  4: 5) (0,azerty : 1 : cvf : fff: qqqq) (0,s)]
[0,(0,a,b,c,d,e) (0,1,2,3,4,5) (0,azerty,1,cvf,fff,qqqq) (0,s)]
[0,(0,a,b,c,d,e) (0,1,2,3,4,5) (0,# comment) (0,azerty,1,cvf,fff,qqqq) (0,s)]
[0,(0,a,b,c,d,e) (0,1,2,3,4,5) (0,# comment) (0,azerty,1,cvf,fff,qqqq) (0,s)]

چند نکته

  1. فایل متنی خط به خط پردازش می‌شود. هر خط با استفاده از کلاس **stringtovector** که قبلاً مورد بحث قرار گرفت، به فیلدها تقسیم می‌شود.

  2. بنابراین، عناصر برداری که از فایل متنی ایجاد شده‌اند، اشیایی از نوع **stringtovector** هستند.

  3. متد identite از کلاس filetovector می‌تواند از متد **stringtovector.identite() برای نمایش عناصر خود و همچنین از متد Vector.toString()** برای نمایش شماره‌ی هر خطی که خطا دارد، استفاده کند.

4.12.5. تمرین ۵

ما می‌خواهیم سازنده زیر را به کلاس **filetovector** اضافه کنیم:


    public filetovector(String nomFichier, String separateur, String sChampsVoulus,
            boolean strict, String tagCommentaire){
        
        //یک بردار حاوی خطوط فایل متنی nomFichier ایجاد می‌کند
        // خطوط از فیلدهایی تشکیل شده‌اند که توسط جداکننده از هم جدا شده‌اند
        // اگر separator=null باشد، خط از یک فیلد واحد تشکیل شده است
        //تنها فیلدهایی که شاخص‌هایشان در tChampsVoulus قرار دارند، الزامی هستند
        //  شاخص‌ها از   1   شروع می‌شوند
        //اگر sChampsvoulus برابر null یا خالی باشد، همه فیلدها گنجانده می‌شوند
        //اگر strict=true باشد، همه فیلدهای الزامی باید موجود باشند
        // اگر اینطور نباشد، سطر ذخیره نمی‌شود و شاخص آن
        //در بردار lignesErronees قرار می‌گیرد
        //خطوط خالی نادیده گرفته می‌شوند
        // همچنین خطوطی که با tagCommentaire شروع می‌شوند نادیده گرفته می‌شوند اگر tagCommentaire != null

فهرست شاخص‌ها برای فیلدهای مورد نظر اکنون به جای یک آرایه از اعداد صحیح، به صورت یک رشته (String) ذخیره می‌شود.

ویژگی private با مقدار erreur ممکن است دارای مقدار اضافی دیگری باشد:

2: رشته حاوی شاخص‌های فیلدهای مورد نظر نادرست است

در اینجا یک آزمون نمونه آورده شده است:


import java.io.*;
//import filetovector;

public class test1{
  public static void main(String arg[]){
    System.out.println(new filetovector("data.txt",":","1 3",false,"#").identite());
    System.out.println(new filetovector("data.txt",":","1 3",true,"#").identite());
    System.out.println(new filetovector("data.txt","","1 3",false,"#").identite());
    System.out.println(new filetovector("data.txt",null," 1 3",false,"#").identite());
    String S2=null;
    System.out.println(new filetovector("data.txt",":",S2,false,"#").identite());
    System.out.println(new filetovector("data.txt",":",S2,false,"").identite());
    String S3="";
    System.out.println(new filetovector("data.txt",":",S3,false,null).identite());
  }
}

نتایج:

[0,(0,a,c) (0,1,3) (0,azerty,cvf) (0,s)][4,(0,a,c) (0,1,3) (0,azerty,cvf),[5]]
[0,(0,a:b:c:d:e) (0,1 :2 : 3:  4: 5) (0,azerty : 1 : cvf : fff: qqqq) (0,s)]
[0,(0,a:b:c:d:e) (0,1 :2 : 3:  4: 5) (0,azerty : 1 : cvf : fff: qqqq) (0,s)]
[0,(0,a,b,c,d,e) (0,1,2,3,4,5) (0,azerty,1,cvf,fff,qqqq) (0,s)]
[0,(0,a,b,c,d,e) (0,1,2,3,4,5) (0,# comment) (0,azerty,1,cvf,fff,qqqq) (0,s)]
[0,(0,a,b,c,d,e) (0,1,2,3,4,5) (0,# comment) (0,azerty,1,cvf,fff,qqqq) (0,s)]

چند نکته

  1. ما رشته sChampsVoulus را به آرایه‌ای از اعداد صحیح tChampVoulus تبدیل می‌کنیم تا آن را به حالت سازنده قبلی بازگردانیم.