Skip to content

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

یک فایل متنی فایلی است که شامل خطوط متنی است. بیایید با استفاده از مثال‌ها، ایجاد و استفاده از چنین فایل‌هایی را بررسی کنیم.

6.1. ایجاد و استفاده

برنامه
نتایج
C:\>cscript fic1.vbs

C:\>dir

FIC1     VBS           352  07/01/02   7:07 fic1.vbs
TESTFILE TXT            25  07/01/02   7:07 testfile.txt

C:\>more testfile.txt

Ceci est un autre test.

توضیحات

  • خط ۷ یک شیء فایل از نوع "Scripting.FileSystemObject" را با استفاده از تابع CreateObject("Scripting.FileSystemObject") ایجاد می‌کند. چنین شیء‌ای امکان دسترسی به هر فایلی در سیستم را فراهم می‌کند، نه فقط فایل‌های متنی.
  • خط ۹ یک شیء «TextStream» ایجاد می‌کند. ایجاد این شیء به ایجاد فایل testfile.txt وابسته است. این فایل با یک مسیر مطلق مانند c:\dir1\dir2\....\testfile.txt مشخص نشده، بلکه با یک مسیر نسبی، testfile.txt، مشخص شده است. بنابراین، این فایل در دایرکتوری‌ای که دستور اجرای آن از آنجا فراخوانی می‌شود، ایجاد خواهد شد.
  • سیستم فایل ویندوز با مفاهیمی مانند فایل‌های متنی یا غیرمتنی آشنا نیست. این سیستم فقط فایل‌ها را تشخیص می‌دهد. بنابراین، این وظیفه برنامه کاربری که از این فایل استفاده می‌کند است که تعیین کند آیا باید آن را به عنوان یک فایل متنی در نظر بگیرد یا خیر.
  • خط ۹ یک شیء ایجاد می‌کند که از آن برای تخصیص دستور set استفاده می‌شود. ایجاد یک شیء فایل متنی مستلزم ایجاد دو شیء است:
    • ایجاد یک شیء Scripting.FileSystemObject (خط ۷)
    • که به دنبال آن ایجاد یک شیء «TextStream» (فایل متنی) با استفاده از متد OpenTextFile شیء Scripting.FileSystemObject انجام می‌شود، که چندین پارامتر را می‌پذیرد:
      • نام فایلی که باید پردازش شود (الزامی)
      • حالت دسترسی به فایل. این یک عدد صحیح با سه مقدار ممکن است:
        • ۱: دسترسی فقط خواندنی به فایل
        • ۲: حالت نوشتن. اگر فایل از قبل وجود نداشته باشد و پارامتر سوم موجود باشد و روی true تنظیم شده باشد، فایل ایجاد می‌شود؛ در غیر این صورت، ایجاد نمی‌شود. اگر از قبل وجود داشته باشد، جایگزین می‌شود.
        • ۸: حالت الحاق؛ c.a.d در انتهای فایل می‌نویسد. اگر فایل از قبل وجود نداشته باشد و پارامتر سوم موجود و روی true تنظیم شده باشد، فایل ایجاد می‌شود؛ در غیر این صورت، ایجاد نمی‌شود.
  • خط ۱۱ با استفاده از متد WriteLine از شی TextStream که ایجاد شده است، یک خط متن را می‌نویسد.
  • خط ۱۳ فایل را «بسته» می‌کند. پس از آن دیگر نمی‌توان در آن نوشت یا از آن خواند.
  • خط ۱۶ یک شیء جدید به نام «TextStream» برای پردازش همان فایل قبلی ایجاد می‌کند، اما این بار در حالت «append» ( الحاقی). هر خط جدیدی که نوشته شود به انتهای خطوط موجود اضافه خواهد شد.
  • خط ۱۸ دو خط جدید می‌نویسد، با در نظر گرفتن اینکه ثابت vbCRLF نشانگر پایان خط برای فایل‌های متنی است.
  • خط ۲۰ فایل را دوباره می‌بندد
  • خط ۲۳ آن را در حالت «خواندن» دوباره باز می‌کند: ما قصد داریم محتویات فایل را بخوانیم.
  • خط ۲۷ یک خط متن را با استفاده از متد ReadLine از شیء TextStream می‌خواند. هنگامی که فایل به تازگی «باز» شده باشد، مکان‌نما روی خط اول متن آن قرار می‌گیرد. پس از اینکه این خط توسط متد ReadLine خوانده شد، مکان‌نما روی خط دوم قرار می‌گیرد. بنابراین، متد Readline نه تنها خط فعلی را می‌خواند، بلکه به طور خودکار به خط بعدی «حرکت» می‌کند.
  • برای پردازش تمام خطوط متن، متد ReadLine باید به طور مکرر در یک حلقه اجرا شود. این حلقه (خط ۲۶) زمانی پایان می‌یابد که ویژگی AtEndOfStream از شیء TextStream مقدار true را داشته باشد. این بدان معناست که دیگر خطی برای خواندن از فایل باقی نمانده است.

6.2. سناریوهای خطا

دو سناریوی خطای رایج وجود دارد:

  • تلاش برای باز کردن فایلی برای خواندن که وجود ندارد
  • باز کردن یک فایل برای نوشتن یا افزودن فایلی که وجود ندارد، با تنظیم پارامتر سوم روی false در فراخوانی متد OpenTextFile.

برنامه زیر نشان می‌دهد چگونه این خطاها را تشخیص دهیم:

برنامه
' ایجاد و پر کردن یک فایل متنی
Option Explicit
Dim objFichier,MyFile
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim codeErreur

' یک شیء فایل ایجاد می‌کند
Set objFichier=CreateObject("Scripting.FileSystemObject")

' یک فایل متنی (که باید از قبل وجود داشته باشد) را در حالت فقط خواندنی باز کنید
On Error Resume Next
Set MyFile= objFichier.OpenTextFile("abcd", ForReading)
codeErreur=err.number
On Error GoTo 0
If codeErreur<>0 Then  
    ' فایل وجود ندارد
    wscript.echo "Le fichier [abcd] n'existe pas"
Else
    'بستن فایل متنی  
    MyFile.Close
End If


'باز کردن یک فایل متنی که باید از قبل وجود داشته باشد در حالت فقط خواندنی
On Error Resume Next
Set MyFile= objFichier.OpenTextFile("abcd", ForWriting, False)
codeErreur=err.number
On Error GoTo 0
If codeErreur<>0 Then  
    wscript.echo "Le fichier [abcd] n'existe pas"
Else
    ' فایل متنی بسته است
    MyFile.Close
End If

' باز کردن یک فایل متنی که باید در حالت الحاق وجود داشته باشد
On Error Resume Next
Set MyFile= objFichier.OpenTextFile("abcd", ForAppending, False)
codeErreur=err.number
On Error GoTo 0
If codeErreur<>0 Then  
    wscript.echo "Le fichier [abcd] n'existe pas"
Else
    ' فایل متنی را می‌بندد
    MyFile.Close
End If

' پایان
wscript.quit 0
نتایج
C:\>dir

FIC1     VBS           964  07/01/02   7:54 fic1.vbs
TESTFILE TXT             0  07/01/02   8:18 testfile.txt
FIC2     VBS         1 252  07/01/02   8:23 fic2.vbs
3 fichier(s)              2 216 octets
2 répertoire(s)        4 007.11 Mo libre

C:\>cscript fic2.vbs

Le fichier [abcd] n'existe pas
Le fichier [abcd] n'existe pas
Le fichier [abcd] n'existe pas

6.3. برنامه IMPOTS با یک فایل متنی

اکنون به برنامه محاسبه مالیات می‌پردازیم، با این فرض که داده‌های مورد نیاز برای محاسبه مالیات در یک فایل متنی به نام data.txt قرار دارد:

12620 13190 15640 24740 31810 39970 48360 55790 92970 127860 151250 172040 195000 0
0 0,05 0,1 0,15 0,2 0,25 0,3 0,35 0,4 0,45 0,5 0,55 0,6 0,65
0 631 1290,5 2072,5 3309,5 4900 6898,5 9316,5 12106 16754,5 23147,5 30710 39312 49062

این سه خط به ترتیب حاوی داده‌های جدول‌های آستانه برنامه، coeffR و coeffN هستند. به لطف طراحی مدولار برنامه ما، تغییرات عمدتاً در رویه getData که مسئول ساخت این سه جدول است، اعمال می‌شوند. برنامه جدید به شرح زیر است:

برنامه
' محاسبه مالیات یک مؤدی
' برنامه باید با سه پارامتر فراخوانی شود: متأهل، تعداد فرزندان، حقوق
' married: کاراکتر 'O' اگر متأهل، 'N' اگر مجرد
' فرزندان: تعداد فرزندان
' حقوق: حقوق سالانه بدون احتساب پنی

' اعلام متغیر الزامی
Option Explicit
Dim erreur

' آرگومان‌ها با بررسی اعتبارشان بازیابی می‌شوند
Dim marie, enfants, salaire
erreur=getArguments(marie,enfants,salaire)
' خطا؟
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit erreur(0)

' بازیابی داده‌های مورد نیاز برای محاسبه مالیات
Dim limites, coeffR, coeffN
erreur=getData(limites,coeffR,coeffN)
' خطا؟
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit 5

' نتیجه نمایش داده می‌شود
wscript.echo "impôt=" & calculerImpot(marie,enfants,salaire,limites,coeffR,coeffN)

'خروج بدون خطا
wscript.quit 0

' ------------ توابع و رویه‌ها

' ----------- getArguments
Function getArguments(byref marie, ByRef enfants, ByRef salaire)
    ' باید سه مقدار را که به‌عنوان آرگومان به برنامهٔ اصلی ارسال شده‌اند، بازیابی کند
    'یک آرگومان بدون فاصله قبل یا بعد از آن به برنامه ارسال می‌شود
    ' برای بررسی اعتبار داده‌ها از عبارت‌های منظم استفاده خواهد شد

    ' یک نوع آرایه خطا را بازمی‌گرداند که شامل دو مقدار است
    'error(0): کد خطا، 0 در صورت عدم وجود خطا
    ' error(1): پیام خطا در صورت رخ دادن خطا، در غیر این صورت رشته‌ای خالی

    Dim syntaxe
    syntaxe= _
    "Syntaxe : pg marié enfants salaire" & vbCRLF & _
    "marié : caractère O si marié, N si non marié" & vbCRLF & _
    "enfants : nombre d'enfants (entier >=0)" & vbCRLF & _
    "salaire : salaire annuel sans les centimes (entier >=0)"

    'بررسی می‌کند که ۳ آرگومان وجود دارد
    Dim nbArguments
    nbArguments=wscript.arguments.count
    If nbArguments<>3 Then
        ' پیام خطا
        getArguments= array(1,syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect")
        ' پایان
        Exit Function
    End If

    Dim modele, correspondances
    Set modele=new regexp

    'وضعیت تأهل باید شامل حروف oOnN باشد
    modele.pattern="^[oOnN]$"
    Set correspondances=modele.execute(wscript.arguments(0))
    If correspondances.count=0 Then
        ' پیام خطا
        getArguments=array(2,syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect")
        'خروج
        Exit Function
    End If
    ' بازیابی مقدار
    If lcase(wscript.arguments(0)) = "o"Then
        marie=true
    Else
        marie=false
    End If

    ' فرزندان باید یک عدد صحیح ≥ 0 باشند
    modele.pattern="^\d{1,2}$"
    Set correspondances=modele.execute(wscript.arguments(1))
    If correspondances.count=0 Then
        ' خطا
        getArguments= array(3,syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect")
        'خروج
        Exit Function
    End If
    ' بازیابی مقدار
    enfants=cint(wscript.arguments(1))

    ' حقوق باید یک عدد صحیح ≥ 0 باشد
    modele.pattern="^\d{1,9}$"
    Set correspondances=modele.execute(wscript.arguments(2))
    If correspondances.count=0 Then
        ' خطا
        getArguments= array(4,syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect")
        'خروج
        Exit Function
    End If
    ' ارزش را بازیابی می‌کند
    salaire=clng(wscript.arguments(2))

    ' بدون خطا تکمیل شد
    getArguments=array(0,"")
End Function

' ----------- getData
Function getData(byref limites, ByRef coeffR, ByRef coeffN)
    'داده‌ها از سه جدول محدوده، coeffR و coeffN، در یک فایل متنی هستند
    'به نام data.txt. هر آرایه یک خط را به شکل val1 val2 ... valn اشغال می‌کند.
    'به ترتیب شامل محدودیت‌های coeffR و coeffN است

    'یک آرایهٔ دو عنصری بازگشتی برای رسیدگی به هرگونه خطا است
    'خطا(0): 0 در صورت عدم وجود خطا، در غیر این صورت یک عدد صحیح > 0
    ' error(1): پیام خطا در صورت رخ دادن خطا

    Dim objFichier,MyFile,codeErreur
    Const ForReading = 1, dataFileName="data.txt"

    'یک شیء فایل ایجاد می‌کند
    Set objFichier=CreateObject("Scripting.FileSystemObject")
    ' فایل data.txt را در حالت خواندن باز می‌کند
    On Error Resume Next
    Set MyFile= objFichier.OpenTextFile(dataFileName, ForReading)
    ' خطا؟
    codeErreur=err.number
    On Error GoTo 0
    If codeErreur<>0 Then
        ' یک خطا رخ داده است – آن را یادداشت کنید
        getData=array(1,"Impossible d'ouvrir le fichier des données [" & dataFileName & "] en lecture")
        ' ادامه می‌دهیم
        Exit Function
    End If

    ' ما اکنون فرض می‌کنیم محتوا صحیح است و هیچ بررسی‌ای انجام نمی‌دهیم
    ' ما سه خط را می‌خوانیم

    ' محدودیت‌ها
    Dim ligne, i
    ligne=MyFile.ReadLine
    getDataFromLine ligne,limites

    ' coeffR
    ligne=MyFile.ReadLine
    getDataFromLine ligne,coeffR


    'coeffN
    ligne=MyFile.ReadLine
    coeffN=split(ligne," ")
    getDataFromLine ligne,coeffN

    ' پایان فایل
    MyFile.close

    ' بدون هیچ خطایی به پایان رسید
    getData=array(0,"")
End Function

' ----------- getDataFromLine
Sub getDataFromLine(byref ligne, ByRef tableau)
    ' مقادیر عددی موجود در سطر را در یک جدول قرار می‌دهد
    ' این‌ها با یک یا چند فاصله از هم جدا شده‌اند

    ' در ابتدا، آرایه خالی است
    tableau=array()
    'یک قالب برای خط تعریف شده است
    Dim modele, correspondances
    Set modele= New RegExP
    With modele
        .pattern="\d+,\d+|\d+"    ' 140,5 ou 140
        .global=true              ' toutes les valeurs
    End With

    ' ردیف تحلیل می‌شود
    Set correspondances=modele.execute(ligne)
    Dim i
    For i=0 To correspondances.count-1
        ' آرایه بازاندازه می‌شود
        ReDim Preserve tableau(i)
        'یک مقدار به عنصر جدید اختصاص داده می‌شود
        tableau(i)=cdbl(correspondances(i).value)
    Next

    'پایان
End Sub




' ----------- calculerImpot
Function calculerImpot(byval marie,ByVal enfants,ByVal salaire, ByRef limites, ByRef coeffR, ByRef coeffN)

    ' تعداد سهام محاسبه می‌شود
    Dim nbParts
    If marie=true Then
        nbParts=(enfants/2)+2
    Else
        nbParts=(enfants/2)+1
    End If
    If enfants>=3 Then nbParts=nbParts+0.5

    'ضریب خانوادگی و درآمد مشمول مالیات محاسبه می‌شوند
    Dim revenu, qf
    revenu=0.72*salaire
    qf=revenu/nbParts

    ' مالیات محاسبه می‌شود
    Dim i, impot
    i=0
    Do While i<ubound(limites) And qf>limites(i)
        i=i+1
    Loop
    calculerImpot=int(revenu*coeffr(i)-nbParts*coeffn(i))
End Function

توضیحات:

  • در فایل متنی data.txt، مقادیر ممکن است با یک یا چند فاصله از هم جدا شوند که استفاده از تابع split برای استخراج مقادیر از خط را غیرممکن می‌سازد. لازم بود از یک عبارت منظم استفاده شود.
  • تابع getData علاوه بر سه آرایه محدودکننده (coeffR و coeffN)، یک نتیجه بازمی‌گرداند که نشان می‌دهد آیا خطایی رخ داده است یا خیر. این نتیجه یک آرایه واریانت حاوی دو عنصر است. عنصر اول یک کد خطا است (0 در صورت عدم وجود خطا) و عنصر دوم پیام خطا در صورت وقوع خطا است.
  • تابع getData اعتبار مقادیر یافت‌شده در فایل data.txt را بررسی نمی‌کند. در یک سناریوی دنیای واقعی، این کار باید انجام شود.