أساسيات مكتبة نظام التشغيل
توفر حزمة "os" في لغة البرمجة جولانج واجهة مستقلة عن النظام لوظائف نظام التشغيل. فيما يلي، سنناقش كيفية استخدام حزمة "os" للتعامل مع فتح الملفات، وإغلاقها، وقراءتها، وكتابتها، بالإضافة إلى الحصول على السمات وضبطها.
1.1 فتح وإغلاق الملفات
في لغة البرمجة جولانج، يمكنك استخدام دالة "os.Open" لفتح ملف، حيث سترجع كائن "*os.File" وخطأ. بمجرد فتح الملف، يمكنك إجراء عمليات قراءة، كتابة، وغيرها. بعد الانتهاء من العمليات، يجب عليك استدعاء "file.Close" لإغلاق الملف وإطلاق الموارد المقابلة.
فيما يلي مثال على فتح ملف:
package main
import (
"fmt"
"os"
)
func main() {
// فتح ملف test.txt في الدليل الحالي
file, err := os.Open("test.txt")
if err != nil {
// التعامل مع خطأ فتح الملف
fmt.Println("خطأ في فتح الملف:", err)
return
}
// استخدام بيان defer لضمان إغلاق الملف في النهاية
defer file.Close()
// عمليات التعامل مع الملف...
fmt.Println("تم فتح الملف بنجاح")
}
في الكود أعلاه، نستخدم بيان "defer" لضمان أن "file.Close" سيتم تنفيذه بصورة متأكدة. وهذا ممارسة شائعة في لغة الجولانج لتنظيف الموارد.
1.2 عمليات قراءة وكتابة الملف
نوع "os.File" يحتوي على أساليب "Read" و "Write"، التي يمكن استخدامها لعمليات قراءة وكتابة الملف. تقوم الأسلوب "Read" بقراءة البيانات من الملف إلى شريحة بايت، بينما يقوم الأسلوب "Write" بكتابة البيانات من شريحة بايت إلى الملف.
يوضح المثال التالي كيفية القراءة من الملف والكتابة إليه:
package main
import (
"fmt"
"os"
)
func main() {
// فتح الملف
file, err := os.OpenFile("test.txt", os.O_RDWR, 0644)
if err != nil {
fmt.Println("خطأ في فتح الملف:", err)
return
}
defer file.Close()
// كتابة محتوى الملف
message := []byte("مرحبًا، جوفرز!")
_, writeErr := file.Write(message)
if writeErr != nil {
fmt.Println("خطأ في كتابة الملف:", writeErr)
return
}
// قراءة الملف من البداية
file.Seek(0, 0)
buffer := make([]byte, len(message))
_, readErr := file.Read(buffer)
if readErr != nil {
fmt.Println("خطأ في قراءة الملف:", readErr)
return
}
fmt.Println("محتوى الملف:", string(buffer))
}
في هذا المثال، نستخدم "os.OpenFile" بدلاً من "os.Open". دالة "os.OpenFile" تسمح لك بتحديد الوضع والأذونات المستخدمة عند فتح الملف. في المثال أعلاه، نستخدم العلم "os.O_RDWR"، مما يعني أن الملف سيتم فتحه في وضع القراءة والكتابة.
1.3 خصائص الملف والأذونات
يمكنك استخدام الوظائف من حزمة os
للوصول إلى معلومات حالة الملف وتعديلها. استخدم os.Stat
أو os.Lstat
للحصول على واجهة os.FileInfo
، والتي توفر معلومات حول الملف، مثل الحجم، والأذونات، ووقت التعديل، وأكثر من ذلك.
إليك مثال على كيفية الحصول على حالة الملف:
package main
import (
"fmt"
"os"
)
func main() {
fileInfo, err := os.Stat("test.txt")
if err != nil {
fmt.Println("حدث خطأ أثناء الحصول على معلومات الملف:", err)
return
}
// طباعة حجم الملف
fmt.Printf("حجم الملف: %d بايت\n", fileInfo.Size())
// طباعة الأذونات للملف
fmt.Printf("أذونات الملف: %s\n", fileInfo.Mode())
}
إذا كنت بحاجة لتغيير اسم الملف أو تعديل أذونات الملف، يمكنك استخدام os.Rename
لإعادة تسمية الملف أو os.Chmod
لتغيير أذونات الملف.
package main
import (
"fmt"
"os"
)
func main() {
// تغيير أذونات الملف إلى قراءة فقط
err := os.Chmod("test.txt", 0444)
if err != nil {
fmt.Println("حدث خطأ أثناء تغيير أذونات الملف:", err)
return
}
// إعادة تسمية الملف
renameErr := os.Rename("test.txt", "renamed.txt")
if renameErr != nil {
fmt.Println("حدث خطأ أثناء إعادة تسمية الملف:", renameErr)
return
}
fmt.Println("عمليات الملف تمت بنجاح")
}
هنا، نقوم بتغيير أذونات ملف test.txt
إلى قراءة فقط، ثم نعيد تسمية الملف إلى renamed.txt
. يرجى ملاحظة أنه عند تعديل أذونات الملف، يجب أن تكون حذرًا، حيث أن إعدادات الأذونات غير الصحيحة قد تؤدي إلى ملفات غير قابلة للوصول.
2. الاستخدام الأساسي لمكتبة الإدخال/الإخراج (IO)
في لغة Go، توفر مكتبة io
واجهات أساسية للعمليات الأساسية للإدخال/الإخراج (I/O). تتبع تصميم مكتبة io
مبادئ البساطة والواجهات الموحدة، مما يوفر الدعم الأساسي لأنواع مختلفة من عمليات الإدخال/الإخراج، مثل قراءة/كتابة الملفات، والتواصل عبر الشبكة، وتخزين البيانات، وأكثر من ذلك.
2.2 استخدام واجهتي القارئ والكاتب
io.Reader
و io.Writer
هما واجهتان أساسيتان تُستخدم لتحديد عمليات القراءة والكتابة لكائن. تتم تنفيذهما بواسطة أنواع مختلفة، مثل الملفات واتصالات الشبكة والبوافر.
io.Reader
واجهة io.Reader
تحتوي على طريقة قراءة:
Read(p []byte) (n int, err error)
تقوم هذه الطريقة بقراءة ما يصل إلى len(p)
بايت من البيانات من io.Reader
إلى p
. وتُرجع عدد بايتات القراءة n
(0 <= n
<= len(p
)) وأي خطأ يحدث.
مثال الكود:
package main
import (
"fmt"
"io"
"strings"
)
func main() {
r := strings.NewReader("مرحباً، عالم!")
buf := make([]byte, 4)
for {
n, err := r.Read(buf)
if err == io.EOF {
break
}
fmt.Printf("البايتات المُقروءة: %d، المحتوى: %s\n", n, buf[:n])
}
}
في هذا المثال، نقوم بإنشاء strings.NewReader
لقراءة البيانات من سلسلة ثم نقوم بقراءة البيانات بشكل متقطع في دفعات ذات 4 بايت.
io.Writer
واجهة io.Writer
تحتوي على طريقة كتابة:
Write(p []byte) (n int, err error)
تقوم هذه الطريقة بكتابة البيانات من p
إلى تيار البيانات الأساسي، وتُرجع عدد البايتات المكتوبة وأي خطأ يحدث.
مثال الكود:
package main
import (
"fmt"
"os"
)
func main() {
data := []byte("مرحباً، عالم!\n")
n, err := os.Stdout.Write(data)
if err != nil {
panic(err)
}
fmt.Printf("البايتات المكتوبة: %d\n", n)
}
في هذا المثال، نقوم بكتابة سلسلة بسيطة إلى الإخراج القياسي os.Stdout
، وهو يعمل كتنفيذ لـ io.Writer
.
2.3 وظائف القراءة/الكتابة المتقدمة
يوفر جهاز السحب بعض الوظائف المتقدمة التي يمكن أن تبسط المهام الشائعة، مثل نسخ البيانات وقراءة كمية محددة من البيانات.
وظيفة النسخ
io.Copy
هي طريقة ملائمة لنسخ البيانات مباشرة من io.Reader
إلى io.Writer
دون الحاجة إلى وسيط مؤقت.
الكود العينة:
package main
import (
"io"
"os"
"strings"
)
func main() {
r := strings.NewReader("مثال على عملية النسخ البسيطة")
_, err := io.Copy(os.Stdout, r)
if err != nil {
panic(err)
}
}
في هذا المثال، نقوم بنسخ سلسلة مباشرة إلى المخرج القياسي.
وظيفة ReadAtLeast
تستخدم وظيفة io.ReadAtLeast
لضمان أنه يتم قراءة ما لا يقل عن كمية محددة من البيانات من io.Reader
قبل العودة.
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)
الكود العينة:
package main
import (
"fmt"
"io"
"strings"
)
func main() {
r := strings.NewReader("موقع لغة جو باللغة الصينية")
buf := make([]byte, 14)
n, err := io.ReadAtLeast(r, buf, 14)
if err != nil {
fmt.Println(err)
}
fmt.Printf("%s\n", buf[:n])
}
في هذا المثال، تحاول io.ReadAtLeast
قراءة ما لا يقل عن 14 بايتًا من البيانات إلى buf
.
هذه الوظائف المتقدمة للقراءة/الكتابة تسمح لك بمعالجة مهام الإدخال/الإخراج بكفاءة أكبر وتوفر أساساً قوياً لبناء منطق البرنامج الأكثر تعقيدا.