TypeScript yordamida Node.js fayl operatsiyalarini oching. Ushbu keng qamrovli qo'llanma sinxron, asinxron va oqimli FS usullarini o'rganadi, tur xavfsizligi, xatoliklarni qayta ishlash va global jamoalar uchun eng yaxshi amaliyotlarga urg'u beradi.
TypeScript Fayl Tizimi Mahorati: Global Dasturchilar uchun Tur Xavfsizligi bilan Node.js Fayl Operatsiyalari
Zamonaviy dasturiy ta'minot ishlab chiqishning keng landshaftida Node.js kengaytiriladigan server tomonidagi ilovalar, buyruq qatori vositalari va boshqalarni yaratish uchun kuchli ish vaqti (runtime) sifatida ajralib turadi. Ko'pgina Node.js ilovalarining asosiy jihati fayl tizimi bilan o'zaro ishlashni o'z ichiga oladi – fayllar va direktoriyalarni o'qish, yozish, yaratish va boshqarish. JavaScript bu operatsiyalarni bajarish uchun moslashuvchanlikni ta'minlasa-da, TypeScript-ning kiritilishi statik turdagi tekshiruv, yaxshilangan vositalar va natijada fayl tizimi kodingizga yuqori ishonchlilik va texnik xizmat ko'rsatish qulayligini olib kelish orqali bu tajribani yuksaltiradi.
Ushbu keng qamrovli qo'llanma, madaniy kelib chiqishi yoki geografik joylashuvidan qat'i nazar, TypeScript taklif qiladigan mustahkamlik bilan Node.js fayl operatsiyalarini o'zlashtirishga intilayotgan global dasturchilar auditoriyasi uchun yaratilgan. Biz asosiy `fs` moduliga chuqur kirib boramiz, uning turli sinxron va asinxron paradigmalarini o'rganamiz, zamonaviy promise-ga asoslangan API-larni ko'rib chiqamiz va TypeScript-ning tur tizimi qanday qilib keng tarqalgan xatolarni sezilarli darajada kamaytirishi va kodingizning aniqligini yaxshilashi mumkinligini ochib beramiz.
Asosiy Tamal Toshi: Node.js Fayl Tizimini (`fs`) Tushunish
Node.js `fs` moduli fayl tizimi bilan standart POSIX funksiyalariga modellashtirilgan tarzda o'zaro ishlash uchun API taqdim etadi. U oddiy fayllarni o'qish va yozishdan tortib, murakkab direktoriya manipulyatsiyalari va fayllarni kuzatishgacha bo'lgan keng ko'lamli usullarni taklif etadi. An'anaviy tarzda, bu operatsiyalar qayta qo'ng'iroqlar (callbacks) bilan bajarilgan, bu esa murakkab stsenariylarda mashhur "callback hell" (qayta qo'ng'iroqlar do'zaxi) ga olib kelgan. Node.js rivojlanishi bilan promise-lar va `async/await` asinxron operatsiyalar uchun afzal ko'rilgan naqshlar sifatida paydo bo'ldi, bu esa kodni o'qish va boshqarishni osonlashtirdi.
Nima uchun Fayl Tizimi Operatsiyalari uchun TypeScript?
Node.js `fs` moduli oddiy JavaScript bilan mukammal ishlasa-da, TypeScript-ni integratsiyalash bir nechta jozibador afzalliklarni beradi:
- Tur Xavfsizligi: Noto'g'ri argument turlari, etishmayotgan parametrlar yoki kutilmagan qaytariladigan qiymatlar kabi keng tarqalgan xatolarni kodingiz ishga tushishidan oldin, kompilyatsiya vaqtida ushlaydi. Bu, ayniqsa, turli fayl kodirovkalari, bayroqlar va `Buffer` obyektlari bilan ishlashda bebahodir.
- Yaxshilangan O'qish Osonligi: Aniq turdagi izohlar funksiyaning qanday ma'lumotlarni kutayotgani va nima qaytarishini aniq ko'rsatib, turli jamoalardagi dasturchilar uchun kodni tushunishni yaxshilaydi.
- Yaxshiroq Asboblar va Avtomatik To'ldirish: IDE-lar (masalan, VS Code) TypeScript-ning tur ta'riflaridan foydalanib, aqlli avtomatik to'ldirish, parametrlar bo'yicha maslahatlar va inline hujjatlarni taqdim etadi, bu esa samaradorlikni sezilarli darajada oshiradi.
- Refaktoringda Ishonch: Interfeys yoki funksiya imzosini o'zgartirganingizda, TypeScript darhol barcha ta'sirlangan joylarni belgilaydi, bu esa keng ko'lamli refaktoringni xatolardan xoli qiladi.
- Global Muvofiqlik: Xalqaro ishlab chiqish jamoalari bo'ylab kodlash uslubi va ma'lumotlar tuzilmalarini bir xil tushunishni ta'minlaydi, noaniqlikni kamaytiradi.
Sinxron va Asinxron Operatsiyalar: Global Perspektiva
Sinxron va asinxron operatsiyalar o'rtasidagi farqni tushunish juda muhim, ayniqsa ishlash samaradorligi va javob berish qobiliyati birinchi o'rinda turadigan global miqyosda joylashtirish uchun ilovalar yaratishda. Ko'pgina `fs` modul funksiyalari sinxron va asinxron variantlarda keladi. Odatda, asinxron usullar bloklanmaydigan I/O operatsiyalari uchun afzal ko'riladi, bu esa Node.js serveringizning javob berish qobiliyatini saqlab qolish uchun zarurdir.
- Asinxron (Bloklanmaydigan): Ushbu usullar oxirgi argument sifatida qayta qo'ng'iroq (callback) funksiyasini oladi yoki `Promise` qaytaradi. Ular fayl tizimi operatsiyasini boshlaydi va darhol qaytadi, bu esa boshqa kodning bajarilishiga imkon beradi. Operatsiya tugagach, qayta qo'ng'iroq chaqiriladi (yoki Promise bajariladi/rad etiladi). Bu dunyoning turli burchaklaridan kelgan foydalanuvchilarning bir nechta bir vaqtda so'rovlariga xizmat ko'rsatadigan server ilovalari uchun ideal, chunki u fayl operatsiyasining tugashini kutib, serverning qotib qolishini oldini oladi.
- Sinxron (Bloklanadigan): Ushbu usullar qaytishdan oldin operatsiyani to'liq bajaradi. Kodlash osonroq bo'lsa-da, ular Node.js voqealar tsiklini bloklaydi, fayl tizimi operatsiyasi tugamaguncha boshqa hech qanday kodning ishlashiga yo'l qo'ymaydi. Bu, ayniqsa, yuqori trafikli muhitlarda sezilarli ishlashdagi to'siqlarga va javob bermaydigan ilovalarga olib kelishi mumkin. Ularni tejamkorlik bilan, odatda ilovani ishga tushirish mantig'i yoki bloklash qabul qilinadigan oddiy skriptlar uchun ishlating.
TypeScript-dagi Asosiy Fayl Operatsiyalari Turlari
Keling, umumiy fayl tizimi operatsiyalari bilan TypeScript-ni amaliy qo'llashga sho'ng'iymiz. Biz Node.js uchun o'rnatilgan tur ta'riflaridan foydalanamiz, ular odatda `@types/node` paketi orqali mavjud.
Boshlash uchun loyihangizda TypeScript va Node.js turlari o'rnatilganligiga ishonch hosil qiling:
npm install typescript @types/node --save-dev
Sizning `tsconfig.json` faylingiz mos ravishda sozlanishi kerak, masalan:
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"]
}
Fayllarni O'qish: `readFile`, `readFileSync` va Promises API
Fayllardan tarkibni o'qish asosiy operatsiyadir. TypeScript fayl yo'llari, kodirovkalar va potentsial xatolarni to'g'ri boshqarishingizni ta'minlashga yordam beradi.
Asinxron Fayl O'qish (Callback-ga asoslangan)
`fs.readFile` funksiyasi asinxron fayl o'qish uchun asosiy vositadir. U yo'l, ixtiyoriy kodirovka va qayta qo'ng'iroq (callback) funksiyasini oladi. TypeScript qayta qo'ng'iroq argumentlarining to'g'ri turlanganligini (`Error | null`, `Buffer | string`) ta'minlaydi.
import * as fs from 'fs';
const filePath: string = 'data/example.txt';
fs.readFile(filePath, 'utf8', (err: NodeJS.ErrnoException | null, data: string) => {
if (err) {
// Xalqaro tuzatish uchun xatoni qayd etish, masalan, 'Fayl topilmadi'
console.error(`'${filePath}' faylini o'qishda xatolik: ${err.message}`);
return;
}
// Fayl tarkibini qayta ishlash, 'utf8' kodirovkasiga muvofiq satr ekanligiga ishonch hosil qilish
console.log(`Fayl tarkibi (${filePath}):\n${data}`);
});
// Misol: Ikkilik ma'lumotlarni o'qish (kodirovka ko'rsatilmagan)
const binaryFilePath: string = 'data/image.png';
fs.readFile(binaryFilePath, (err: NodeJS.ErrnoException | null, data: Buffer) => {
if (err) {
console.error(`'${binaryFilePath}' ikkilik faylini o'qishda xatolik: ${err.message}`);
return;
}
// Bu yerda 'data' - bu Buffer, keyingi ishlov berish uchun tayyor (masalan, mijozga oqim uzatish)
console.log(`${binaryFilePath} dan ${data.byteLength} bayt o'qildi`);
});
Sinxron Fayl O'qish
`fs.readFileSync` voqealar tsiklini bloklaydi. Uning qaytariladigan turi kodirovka berilganligiga qarab `Buffer` yoki `string` bo'ladi. TypeScript buni to'g'ri aniqlaydi.
import * as fs from 'fs';
const syncFilePath: string = 'data/sync_example.txt';
try {
const content: string = fs.readFileSync(syncFilePath, 'utf8');
console.log(`Sinxron o'qilgan tarkib (${syncFilePath}):\n${content}`);
} catch (error: any) {
console.error(`'${syncFilePath}' uchun sinxron o'qish xatosi: ${error.message}`);
}
Promise-ga asoslangan Fayl O'qish (`fs/promises`)
Zamonaviy `fs/promises` API toza, promise-ga asoslangan interfeysni taklif etadi, bu asinxron operatsiyalar uchun juda tavsiya etiladi. TypeScript bu yerda, ayniqsa `async/await` bilan, a'lo darajada ishlaydi.
import * as fsPromises from 'fs/promises';
async function readTextFile(path: string): Promise
Fayllarga Yozish: `writeFile`, `writeFileSync` va Bayroqlar
Ma'lumotlarni fayllarga yozish ham xuddi shunday muhim. TypeScript fayl yo'llari, ma'lumot turlari (string yoki Buffer), kodirovka va faylni ochish bayroqlarini boshqarishga yordam beradi.
Asinxron Faylga Yozish
`fs.writeFile` ma'lumotlarni faylga yozish uchun ishlatiladi va agar fayl allaqachon mavjud bo'lsa, sukut bo'yicha uni almashtiradi. Siz bu xatti-harakatni `flags` bilan boshqarishingiz mumkin.
import * as fs from 'fs';
const outputFilePath: string = 'data/output.txt';
const fileContent: string = 'Bu TypeScript tomonidan yozilgan yangi tarkib.';
fs.writeFile(outputFilePath, fileContent, 'utf8', (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`'${outputFilePath}' fayliga yozishda xatolik: ${err.message}`);
return;
}
console.log(`'${outputFilePath}' fayli muvaffaqiyatli yozildi.`);
});
// Buffer ma'lumotlari bilan misol
const bufferContent: Buffer = Buffer.from('Ikkilik ma`lumotlar namunasi');
const binaryOutputFilePath: string = 'data/binary_output.bin';
fs.writeFile(binaryOutputFilePath, bufferContent, (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`'${binaryOutputFilePath}' ikkilik fayliga yozishda xatolik: ${err.message}`);
return;
}
console.log(`'${binaryOutputFilePath}' ikkilik fayli muvaffaqiyatli yozildi.`);
});
Sinxron Faylga Yozish
`fs.writeFileSync` yozish operatsiyasi tugaguncha voqealar tsiklini bloklaydi.
import * as fs from 'fs';
const syncOutputFilePath: string = 'data/sync_output.txt';
try {
fs.writeFileSync(syncOutputFilePath, 'Sinxron yozilgan tarkib.', 'utf8');
console.log(`'${syncOutputFilePath}' fayli sinxron yozildi.`);
} catch (error: any) {
console.error(`'${syncOutputFilePath}' uchun sinxron yozish xatosi: ${error.message}`);
}
Promise-ga asoslangan Faylga Yozish (`fs/promises`)
`async/await` va `fs/promises` bilan zamonaviy yondashuv ko'pincha asinxron yozishlarni boshqarish uchun toza bo'ladi.
import * as fsPromises from 'fs/promises';
import { constants as fsConstants } from 'fs'; // Bayroqlar uchun
async function writeDataToFile(path: string, data: string | Buffer): Promise
Muhim Bayroqlar:
- `'w'` (sukut bo'yicha): Yozish uchun faylni ochish. Fayl yaratiladi (agar mavjud bo'lmasa) yoki kesiladi (agar mavjud bo'lsa).
- `'w+'`: O'qish va yozish uchun faylni ochish. Fayl yaratiladi (agar mavjud bo'lmasa) yoki kesiladi (agar mavjud bo'lsa).
- `'a'` (qo'shish): Qo'shish uchun faylni ochish. Fayl mavjud bo'lmasa yaratiladi.
- `'a+'`: O'qish va qo'shish uchun faylni ochish. Fayl mavjud bo'lmasa yaratiladi.
- `'r'` (o'qish): O'qish uchun faylni ochish. Fayl mavjud bo'lmasa, istisno yuz beradi.
- `'r+'`: O'qish va yozish uchun faylni ochish. Fayl mavjud bo'lmasa, istisno yuz beradi.
- `'wx'` (eksklyuziv yozish): `'w'` kabi, lekin yo'l mavjud bo'lsa muvaffaqiyatsiz bo'ladi.
- `'ax'` (eksklyuziv qo'shish): `'a'` kabi, lekin yo'l mavjud bo'lsa muvaffaqiyatsiz bo'ladi.
Fayllarga Qo'shish: `appendFile`, `appendFileSync`
Mavjud faylning oxiriga uning tarkibini ustiga yozmasdan ma'lumot qo'shish kerak bo'lganda, `appendFile` sizning tanlovingizdir. Bu, ayniqsa, jurnallash (logging), ma'lumotlar yig'ish yoki audit izlari uchun foydalidir.
Asinxron Qo'shish
import * as fs from 'fs';
const logFilePath: string = 'data/app_logs.log';
function logMessage(message: string): void {
const timestamp: string = new Date().toISOString();
const logEntry: string = `${timestamp} - ${message}\n`;
fs.appendFile(logFilePath, logEntry, 'utf8', (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`'${logFilePath}' log fayliga qo'shishda xatolik: ${err.message}`);
return;
}
console.log(`'${logFilePath}' ga xabar qayd etildi.`);
});
}
logMessage('Foydalanuvchi "Alice" tizimga kirdi.');
setTimeout(() => logMessage('Tizim yangilanishi boshlandi.'), 50);
logMessage('Ma`lumotlar bazasi bilan ulanish o`rnatildi.');
Sinxron Qo'shish
import * as fs from 'fs';
const syncLogFilePath: string = 'data/sync_app_logs.log';
function logMessageSync(message: string): void {
const timestamp: string = new Date().toISOString();
const logEntry: string = `${timestamp} - ${message}\n`;
try {
fs.appendFileSync(syncLogFilePath, logEntry, 'utf8');
console.log(`'${syncLogFilePath}' ga xabar sinxron qayd etildi.`);
} catch (error: any) {
console.error(`'${syncLogFilePath}' log fayliga sinxron qo'shishda xatolik: ${error.message}`);
}
}
logMessageSync('Ilova ishga tushirildi.');
logMessageSync('Konfiguratsiya yuklandi.');
Promise-ga asoslangan Qo'shish (`fs/promises`)
import * as fsPromises from 'fs/promises';
const promiseLogFilePath: string = 'data/promise_app_logs.log';
async function logMessagePromise(message: string): Promise
Fayllarni O'chirish: `unlink`, `unlinkSync`
Fayllarni fayl tizimidan olib tashlash. TypeScript sizning to'g'ri yo'lni o'tkazayotganingizni va xatolarni to'g'ri boshqarayotganingizni ta'minlashga yordam beradi.
Asinxron O'chirish
import * as fs from 'fs';
const fileToDeletePath: string = 'data/temp_to_delete.txt';
// Avval faylni o'chirish namoyishi uchun uning mavjudligiga ishonch hosil qilish uchun yaratamiz
fs.writeFile(fileToDeletePath, 'Vaqtinchalik tarkib.', 'utf8', (err) => {
if (err) {
console.error('O`chirish namoyishi uchun fayl yaratishda xatolik:', err);
return;
}
console.log(`O'chirish namoyishi uchun '${fileToDeletePath}' fayli yaratildi.`);
fs.unlink(fileToDeletePath, (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`'${fileToDeletePath}' faylini o'chirishda xatolik: ${err.message}`);
return;
}
console.log(`'${fileToDeletePath}' fayli muvaffaqiyatli o'chirildi.`);
});
});
Sinxron O'chirish
import * as fs from 'fs';
const syncFileToDeletePath: string = 'data/sync_temp_to_delete.txt';
try {
fs.writeFileSync(syncFileToDeletePath, 'Sinxron vaqtinchalik tarkib.', 'utf8');
console.log(`'${syncFileToDeletePath}' fayli yaratildi.`);
fs.unlinkSync(syncFileToDeletePath);
console.log(`'${syncFileToDeletePath}' fayli sinxron o'chirildi.`);
} catch (error: any) {
console.error(`'${syncFileToDeletePath}' uchun sinxron o'chirish xatosi: ${error.message}`);
}
Promise-ga asoslangan O'chirish (`fs/promises`)
import * as fsPromises from 'fs/promises';
const promiseFileToDeletePath: string = 'data/promise_temp_to_delete.txt';
async function deleteFile(path: string): Promise
Fayl Mavjudligini va Ruxsatlarni Tekshirish: `existsSync`, `access`, `accessSync`
Fayl ustida ishlashdan oldin, uning mavjudligini yoki joriy jarayonning kerakli ruxsatlarga ega ekanligini tekshirish kerak bo'lishi mumkin. TypeScript `mode` parametri uchun turlarni taqdim etish orqali yordam beradi.
Sinxron Mavjudlikni Tekshirish
`fs.existsSync` oddiy, sinxron tekshiruvdir. Qulay bo'lishiga qaramay, u poyga sharti (race condition) zaifligiga ega (fayl `existsSync` va keyingi operatsiya o'rtasida o'chirilishi mumkin), shuning uchun muhim operatsiyalar uchun `fs.access` dan foydalanish yaxshiroqdir.
import * as fs from 'fs';
const checkFilePath: string = 'data/example.txt';
if (fs.existsSync(checkFilePath)) {
console.log(`'${checkFilePath}' fayli mavjud.`);
} else {
console.log(`'${checkFilePath}' fayli mavjud emas.`);
}
Asinxron Ruxsatlarni Tekshirish (`fs.access`)
`fs.access` foydalanuvchining `path` bilan belgilangan fayl yoki direktoriya uchun ruxsatlarini sinovdan o'tkazadi. U asinxrondir va `mode` argumentini oladi (masalan, mavjudlik uchun `fs.constants.F_OK`, o'qish uchun `R_OK`, yozish uchun `W_OK`, bajarish uchun `X_OK`).
import * as fs from 'fs';
import { constants } from 'fs';
const accessFilePath: string = 'data/example.txt';
fs.access(accessFilePath, constants.F_OK, (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`'${accessFilePath}' fayli mavjud emas yoki kirish rad etilgan.`);
return;
}
console.log(`'${accessFilePath}' fayli mavjud.`);
});
fs.access(accessFilePath, constants.R_OK | constants.W_OK, (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`'${accessFilePath}' fayli o'qilmaydi/yozilmaydi yoki kirish rad etilgan: ${err.message}`);
return;
}
console.log(`'${accessFilePath}' fayli o'qiladigan va yoziladigan.`);
});
Promise-ga asoslangan Ruxsatlarni Tekshirish (`fs/promises`)
import * as fsPromises from 'fs/promises';
import { constants } from 'fs';
async function checkFilePermissions(path: string, mode: number): Promise
Fayl Ma'lumotlarini Olish: `stat`, `statSync`, `fs.Stats`
`fs.stat` oilasiga mansub funksiyalar fayl yoki direktoriya haqida batafsil ma'lumot beradi, masalan, hajmi, yaratilgan sanasi, o'zgartirilgan sanasi va ruxsatlar. TypeScript-ning `fs.Stats` interfeysi bu ma'lumotlar bilan ishlashni yuqori darajada tuzilmali va ishonchli qiladi.
Asinxron Stat
import * as fs from 'fs';
import { Stats } from 'fs';
const statFilePath: string = 'data/example.txt';
fs.stat(statFilePath, (err: NodeJS.ErrnoException | null, stats: Stats) => {
if (err) {
console.error(`'${statFilePath}' uchun statistika olishda xatolik: ${err.message}`);
return;
}
console.log(`'${statFilePath}' uchun statistika:`);
console.log(` Faylmi: ${stats.isFile()}`);
console.log(` Direktoriyami: ${stats.isDirectory()}`);
console.log(` Hajmi: ${stats.size} bayt`);
console.log(` Yaratilgan vaqti: ${stats.birthtime.toISOString()}`);
console.log(` Oxirgi o'zgartirilgan: ${stats.mtime.toISOString()}`);
});
Promise-ga asoslangan Stat (`fs/promises`)
import * as fsPromises from 'fs/promises';
import { Stats } from 'fs'; // Hali ham 'fs' modulining Stats interfeysidan foydalaning
async function getFileStats(path: string): Promise
TypeScript bilan Direktoriya Operatsiyalari
Direktoriyalarni boshqarish fayllarni tartibga solish, dasturga xos saqlash joylarini yaratish yoki vaqtinchalik ma'lumotlarni boshqarish uchun umumiy talabdir. TypeScript bu operatsiyalar uchun mustahkam turdagi tekshiruvni ta'minlaydi.
Direktoriyalarni Yaratish: `mkdir`, `mkdirSync`
`fs.mkdir` funksiyasi yangi direktoriyalarni yaratish uchun ishlatiladi. `recursive` opsiyasi, agar ular mavjud bo'lmasa, ota direktoriyalarni yaratish uchun juda foydali bo'lib, Unix-ga o'xshash tizimlardagi `mkdir -p` xatti-harakatini takrorlaydi.
Asinxron Direktoriya Yaratish
import * as fs from 'fs';
const newDirPath: string = 'data/new_directory';
const recursiveDirPath: string = 'data/nested/path/to/create';
// Yagona direktoriya yaratish
fs.mkdir(newDirPath, (err: NodeJS.ErrnoException | null) => {
if (err) {
// Agar direktoriya allaqachon mavjud bo'lsa, EEXIST xatosini e'tiborsiz qoldiring
if (err.code === 'EEXIST') {
console.log(`'${newDirPath}' direktoriyasi allaqachon mavjud.`);
} else {
console.error(`'${newDirPath}' direktoriyasini yaratishda xatolik: ${err.message}`);
}
return;
}
console.log(`'${newDirPath}' direktoriyasi muvaffaqiyatli yaratildi.`);
});
// Ichki direktoriyalarni rekursiv ravishda yaratish
fs.mkdir(recursiveDirPath, { recursive: true }, (err: NodeJS.ErrnoException | null) => {
if (err) {
if (err.code === 'EEXIST') {
console.log(`'${recursiveDirPath}' direktoriyasi allaqachon mavjud.`);
} else {
console.error(`'${recursiveDirPath}' rekursiv direktoriyasini yaratishda xatolik: ${err.message}`);
}
return;
}
console.log(`'${recursiveDirPath}' rekursiv direktoriyalari muvaffaqiyatli yaratildi.`);
});
Promise-ga asoslangan Direktoriya Yaratish (`fs/promises`)
import * as fsPromises from 'fs/promises';
async function createDirectory(path: string, recursive: boolean = false): Promise
Direktoriya Tarkibini O'qish: `readdir`, `readdirSync`, `fs.Dirent`
Berilgan direktoriya ichidagi fayllar va kichik direktoriyalarni ro'yxatlash uchun siz `fs.readdir` dan foydalanasiz. `withFileTypes` opsiyasi zamonaviy qo'shimcha bo'lib, u `fs.Dirent` obyektlarini qaytaradi va har bir elementni alohida `stat` qilishga hojat qoldirmasdan to'g'ridan-to'g'ri batafsil ma'lumot beradi.
Asinxron Direktoriya O'qish
import * as fs from 'fs';
const readDirPath: string = 'data';
fs.readdir(readDirPath, (err: NodeJS.ErrnoException | null, files: string[]) => {
if (err) {
console.error(`'${readDirPath}' direktoriyasini o'qishda xatolik: ${err.message}`);
return;
}
console.log(`'${readDirPath}' direktoriyasining tarkibi:`);
files.forEach(file => {
console.log(` - ${file}`);
});
});
// `withFileTypes` opsiyasi bilan
fs.readdir(readDirPath, { withFileTypes: true }, (err: NodeJS.ErrnoException | null, dirents: fs.Dirent[]) => {
if (err) {
console.error(`'${readDirPath}' direktoriyasini fayl turlari bilan o'qishda xatolik: ${err.message}`);
return;
}
console.log(`'${readDirPath}' direktoriyasining tarkibi (turlari bilan):`);
dirents.forEach(dirent => {
const type: string = dirent.isFile() ? 'Fayl' : dirent.isDirectory() ? 'Direktoriya' : 'Boshqa';
console.log(` - ${dirent.name} (${type})`);
});
});
Promise-ga asoslangan Direktoriya O'qish (`fs/promises`)
import * as fsPromises from 'fs/promises';
import { Dirent } from 'fs'; // Hali ham 'fs' modulining Dirent interfeysidan foydalaning
async function listDirectoryContents(path: string): Promise
Direktoriyalarni O'chirish: `rmdir` (eskirgan), `rm`, `rmSync`
Node.js direktoriya o'chirish usullarini rivojlantirdi. `fs.rmdir` endi asosan rekursiv o'chirishlar uchun `fs.rm` bilan almashtirilgan bo'lib, u yanada mustahkam va izchil API taklif qiladi.
Asinxron Direktoriya O'chirish (`fs.rm`)
`fs.rm` funksiyasi (Node.js 14.14.0 dan beri mavjud) fayllar va direktoriyalarni olib tashlashning tavsiya etilgan usulidir. `recursive: true` opsiyasi bo'sh bo'lmagan direktoriyalarni o'chirish uchun juda muhimdir.
import * as fs from 'fs';
const dirToDeletePath: string = 'data/dir_to_delete';
const nestedDirToDeletePath: string = 'data/nested_dir/sub';
// Sozlash: Rekursiv o'chirish namoyishi uchun ichida fayli bor direktoriya yaratish
fs.mkdir(nestedDirToDeletePath, { recursive: true }, (err) => {
if (err && err.code !== 'EEXIST') {
console.error('Namoyish uchun ichki direktoriya yaratishda xatolik:', err);
return;
}
fs.writeFile(`${nestedDirToDeletePath}/file_inside.txt`, 'Qandaydir tarkib', (err) => {
if (err) { console.error('Ichki direktoriya ichida fayl yaratishda xatolik:', err); return; }
console.log(`O'chirish namoyishi uchun '${nestedDirToDeletePath}' direktoriyasi va fayli yaratildi.`);
fs.rm(nestedDirToDeletePath, { recursive: true, force: true }, (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`'${nestedDirToDeletePath}' rekursiv direktoriyasini o'chirishda xatolik: ${err.message}`);
return;
}
console.log(`'${nestedDirToDeletePath}' rekursiv direktoriyasi muvaffaqiyatli o'chirildi.`);
});
});
});
// Bo'sh direktoriyani o'chirish
fs.mkdir(dirToDeletePath, (err) => {
if (err && err.code !== 'EEXIST') {
console.error('Namoyish uchun bo`sh direktoriya yaratishda xatolik:', err);
return;
}
console.log(`O'chirish namoyishi uchun '${dirToDeletePath}' direktoriyasi yaratildi.`);
fs.rm(dirToDeletePath, { recursive: false }, (err: NodeJS.ErrnoException | null) => {
if (err) {
console.error(`'${dirToDeletePath}' bo'sh direktoriyasini o'chirishda xatolik: ${err.message}`);
return;
}
console.log(`'${dirToDeletePath}' bo'sh direktoriyasi muvaffaqiyatli o'chirildi.`);
});
});
Promise-ga asoslangan Direktoriya O'chirish (`fs/promises`)
import * as fsPromises from 'fs/promises';
async function deleteDirectory(path: string, recursive: boolean = false): Promise
TypeScript bilan Ilg'or Fayl Tizimi Konsepsiyalari
Oddiy o'qish/yozish operatsiyalaridan tashqari, Node.js kattaroq fayllar bilan ishlash, uzluksiz ma'lumotlar oqimlari va fayl tizimini real vaqtda kuzatish uchun kuchli xususiyatlarni taklif etadi. TypeScript-ning tur deklaratsiyalari bu ilg'or stsenariylarga ham bemalol tatbiq etilib, mustahkamlikni ta'minlaydi.
Fayl Deskriptorlari va Oqimlar
Juda katta fayllar uchun yoki faylga kirishni nozik nazorat qilish kerak bo'lganda (masalan, fayl ichidagi ma'lum bir pozitsiyalar), fayl deskriptorlari va oqimlar muhim ahamiyat kasb etadi. Oqimlar katta hajmdagi ma'lumotlarni qismlarga bo'lib o'qish yoki yozishning samarali usulini taqdim etadi, bu esa butun faylni xotiraga yuklash o'rniga, kengaytiriladigan ilovalar va serverlarda resurslarni samarali boshqarish uchun juda muhimdir.
Fayllarni Deskriptorlar bilan Ochish va Yopish (`fs.open`, `fs.close`)
Fayl deskriptori bu operatsion tizim tomonidan ochiq faylga tayinlangan noyob identifikator (raqam). Siz `fs.open` dan fayl deskriptorini olish uchun foydalanishingiz, keyin ushbu deskriptor yordamida `fs.read` yoki `fs.write` kabi operatsiyalarni bajarishingiz va nihoyat uni `fs.close` qilishingiz mumkin.
import * as fs from 'fs';
import { promises as fsPromises } from 'fs';
import { constants } from 'fs';
const descriptorFilePath: string = 'data/descriptor_example.txt';
async function demonstrateFileDescriptorOperations(): Promise
Fayl Oqimlari (`fs.createReadStream`, `fs.createWriteStream`)
Oqimlar katta fayllar bilan samarali ishlash uchun kuchli vositadir. `fs.createReadStream` va `fs.createWriteStream` mos ravishda `Readable` va `Writable` oqimlarini qaytaradi, ular Node.js oqim API-si bilan muammosiz integratsiyalashadi. TypeScript bu oqim hodisalari (masalan, `'data'`, `'end'`, `'error'`) uchun a'lo darajadagi tur ta'riflarini taqdim etadi.
import * as fs from 'fs';
const largeFilePath: string = 'data/large_file.txt';
const copiedFilePath: string = 'data/copied_file.txt';
// Namoyish uchun namunaviy katta fayl yaratish
function createLargeFile(path: string, sizeInMB: number): void {
const content: string = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. '; // 56 belgi
const stream = fs.createWriteStream(path);
const totalChars = sizeInMB * 1024 * 1024; // MB ni baytlarga o'tkazish
const iterations = Math.ceil(totalChars / content.length);
for (let i = 0; i < iterations; i++) {
stream.write(content);
}
stream.end(() => console.log(`Katta fayl '${path}' (${sizeInMB}MB) yaratildi.`));
}
// Namoyish uchun, avval 'data' direktoriyasi mavjudligiga ishonch hosil qilaylik
fs.mkdir('data', { recursive: true }, (err) => {
if (err && err.code !== 'EEXIST') {
console.error('Ma`lumotlar direktoriyasini yaratishda xatolik:', err);
return;
}
createLargeFile(largeFilePath, 1); // 1MB hajmdagi fayl yaratish
});
// Oqimlar yordamida faylni nusxalash
function copyFileWithStreams(source: string, destination: string): void {
const readStream = fs.createReadStream(source);
const writeStream = fs.createWriteStream(destination);
readStream.on('open', () => console.log(`'${source}' uchun o'qish oqimi ochildi.`));
writeStream.on('open', () => console.log(`'${destination}' uchun yozish oqimi ochildi.`));
// O'qish oqimidan yozish oqimiga ma'lumotlarni uzatish
readStream.pipe(writeStream);
readStream.on('error', (err: Error) => {
console.error(`O'qish oqimi xatosi: ${err.message}`);
});
writeStream.on('error', (err: Error) => {
console.error(`Yozish oqimi xatosi: ${err.message}`);
});
writeStream.on('finish', () => {
console.log(`'${source}' fayli '${destination}' ga oqimlar yordamida muvaffaqiyatli nusxalandi.`);
// Nusxalashdan keyin namunaviy katta faylni tozalash
fs.unlink(largeFilePath, (err) => {
if (err) console.error('Katta faylni o`chirishda xatolik:', err);
else console.log(`Katta fayl '${largeFilePath}' o'chirildi.`);
});
});
}
// Nusxalashga urinishdan oldin katta fayl yaratilishini biroz kuting
setTimeout(() => {
copyFileWithStreams(largeFilePath, copiedFilePath);
}, 1000);
O'zgarishlarni Kuzatish: `fs.watch`, `fs.watchFile`
Fayl tizimidagi o'zgarishlarni kuzatish, masalan, ishlab chiqish serverlarini issiq qayta yuklash, qurish jarayonlari yoki real vaqtda ma'lumotlarni sinxronizatsiya qilish kabi vazifalar uchun juda muhimdir. Node.js buning uchun ikkita asosiy usulni taqdim etadi: `fs.watch` va `fs.watchFile`. TypeScript hodisa turlari va tinglovchi parametrlarining to'g'ri boshqarilishini ta'minlaydi.
`fs.watch`: Hodisaga asoslangan Fayl Tizimini Kuzatish
`fs.watch` odatda samaraliroq, chunki u ko'pincha operatsion tizim darajasidagi bildirishnomalardan foydalanadi (masalan, Linux-da `inotify`, macOS-da `kqueue`, Windows-da `ReadDirectoryChangesW`). U ma'lum fayllar yoki direktoriyalardagi o'zgarishlar, o'chirishlar yoki qayta nomlashlarni kuzatish uchun javob beradi.
import * as fs from 'fs';
const watchedFilePath: string = 'data/watched_file.txt';
const watchedDirPath: string = 'data/watched_dir';
// Kuzatish uchun fayllar/direktoriyalar mavjudligiga ishonch hosil qiling
fs.writeFileSync(watchedFilePath, 'Dastlabki tarkib.');
fs.mkdirSync(watchedDirPath, { recursive: true });
console.log(`'${watchedFilePath}' o'zgarishlar uchun kuzatilmoqda...`);
const fileWatcher = fs.watch(watchedFilePath, (eventType: string, filename: string | Buffer | null) => {
const fname = typeof filename === 'string' ? filename : filename?.toString('utf8');
console.log(`'${fname || 'N/A'}' fayli hodisasi: ${eventType}`);
if (eventType === 'change') {
console.log('Fayl tarkibi o`zgargan bo`lishi mumkin.');
}
// Haqiqiy dasturda siz bu yerda faylni o'qishingiz yoki qayta qurishni ishga tushirishingiz mumkin
});
console.log(`'${watchedDirPath}' direktoriyasi o'zgarishlar uchun kuzatilmoqda...`);
const dirWatcher = fs.watch(watchedDirPath, (eventType: string, filename: string | Buffer | null) => {
const fname = typeof filename === 'string' ? filename : filename?.toString('utf8');
console.log(`'${watchedDirPath}' direktoriyasi hodisasi: '${fname || 'N/A'}' da ${eventType}`);
});
fileWatcher.on('error', (err: Error) => console.error(`Fayl kuzatuvchisi xatosi: ${err.message}`));
dirWatcher.on('error', (err: Error) => console.error(`Direktoriya kuzatuvchisi xatosi: ${err.message}`));
// Kechikishdan so'ng o'zgarishlarni simulyatsiya qilish
setTimeout(() => {
console.log('\n--- O`zgarishlarni simulyatsiya qilish ---');
fs.appendFileSync(watchedFilePath, '\nYangi qator qo`shildi.');
fs.writeFileSync(`${watchedDirPath}/new_file.txt`, 'Tarkib.');
fs.unlinkSync(`${watchedDirPath}/new_file.txt`); // Shuningdek, o'chirishni sinab ko'ring
setTimeout(() => {
fileWatcher.close();
dirWatcher.close();
console.log('\nKuzatuvchilar yopildi.');
// Vaqtinchalik fayllar/direktoriyalarni tozalash
fs.unlinkSync(watchedFilePath);
fs.rmSync(watchedDirPath, { recursive: true, force: true });
}, 2000);
}, 1000);
`fs.watch` haqida eslatma: U barcha platformalarda barcha turdagi hodisalar uchun har doim ham ishonchli emas (masalan, faylni qayta nomlashlar o'chirish va yaratish sifatida xabar qilinishi mumkin). Mustahkam kross-platforma fayllarni kuzatish uchun `chokidar` kabi kutubxonalarni ko'rib chiqing, ular ko'pincha `fs.watch` ni kapot ostida ishlatadi, lekin normallashtirish va zaxira mexanizmlarini qo'shadi.
`fs.watchFile`: So'rovga asoslangan Fayl Kuzatish
`fs.watchFile` o'zgarishlarni aniqlash uchun so'rovdan (faylning `stat` ma'lumotlarini vaqti-vaqti bilan tekshirish) foydalanadi. U kamroq samarali, lekin turli fayl tizimlari va tarmoq drayvlarida barqarorroq. U `fs.watch` ishonchsiz bo'lishi mumkin bo'lgan muhitlar uchun (masalan, NFS ulushlari) yaxshiroq mos keladi.
import * as fs from 'fs';
import { Stats } from 'fs';
const pollFilePath: string = 'data/polled_file.txt';
fs.writeFileSync(pollFilePath, 'Dastlabki so`ralgan tarkib.');
console.log(`'${pollFilePath}' o'zgarishlar uchun so'ralmoqda...`);
fs.watchFile(pollFilePath, { interval: 1000 }, (curr: Stats, prev: Stats) => {
// TypeScript 'curr' va 'prev' ning fs.Stats obyektlari ekanligini ta'minlaydi
if (curr.mtimeMs !== prev.mtimeMs) {
console.log(`'${pollFilePath}' fayli o'zgartirildi (mtime o'zgardi). Yangi hajm: ${curr.size} bayt.`);
}
});
setTimeout(() => {
console.log('\n--- So`ralgan fayl o`zgarishini simulyatsiya qilish ---');
fs.appendFileSync(pollFilePath, '\nSo`ralgan faylga yana bir qator qo`shildi.');
setTimeout(() => {
fs.unwatchFile(pollFilePath);
console.log(`\n'${pollFilePath}' ni kuzatish to'xtatildi.`);
fs.unlinkSync(pollFilePath);
}, 2000);
}, 1500);
Global Kontekstda Xatolarni Qayta Ishlash va Eng Yaxshi Amaliyotlar
Ishlab chiqarishga tayyor har qanday dastur uchun, ayniqsa fayl tizimi bilan ishlaydigan dastur uchun mustahkam xatolarni qayta ishlash juda muhimdir. Fayl operatsiyalari ko'plab sabablarga ko'ra muvaffaqiyatsizlikka uchrashi mumkin: ruxsatlar bilan bog'liq muammolar, disk to'lishi xatolari, fayl topilmasligi, I/O xatolari, tarmoq muammolari (tarmoqqa ulangan drayvlar uchun) yoki bir vaqtda kirish ziddiyatlari. TypeScript sizga tur bilan bog'liq muammolarni aniqlashga yordam beradi, ammo ish vaqti xatolarini hali ham ehtiyotkorlik bilan boshqarish kerak.
Xatolarni Qayta Ishlash Strategiyalari
- Sinxron Operatsiyalar: Har doim `fs.xxxSync` chaqiruvlarini `try...catch` bloklariga o'rang. Bu usullar xatolarni to'g'ridan-to'g'ri chiqaradi.
- Asinxron Qayta Qo'ng'iroqlar: `fs` qayta qo'ng'irog'iga birinchi argument har doim `err: NodeJS.ErrnoException | null`. Har doim avval ushbu `err` ob'ektini tekshiring.
- Promise-ga asoslangan (`fs/promises`): Rad etishlarni boshqarish uchun `await` bilan `try...catch` yoki `.then()` zanjirlari bilan `.catch()` dan foydalaning.
Agar ilovangizning xato haqidagi fikr-mulohazalari foydalanuvchiga yo'naltirilgan bo'lsa, xatolarni qayd etish formatlarini standartlashtirish va xato xabarlari uchun xalqarolashtirishni (i18n) ko'rib chiqish foydalidir.
import * as fs from 'fs';
import { promises as fsPromises } from 'fs';
import * as path from 'path';
const problematicPath = path.join('non_existent_dir', 'file.txt');
// Sinxron xatolarni qayta ishlash
try {
fs.readFileSync(problematicPath, 'utf8');
} catch (error: any) {
console.error(`Sinxron xato: ${error.code} - ${error.message} (Yo'l: ${problematicPath})`);
}
// Qayta qo'ng'iroqqa asoslangan xatolarni qayta ishlash
fs.readFile(problematicPath, 'utf8', (err, data) => {
if (err) {
console.error(`Qayta qo'ng'iroq xatosi: ${err.code} - ${err.message} (Yo'l: ${problematicPath})`);
return;
}
// ... ma'lumotlarni qayta ishlash
});
// Promise-ga asoslangan xatolarni qayta ishlash
async function safeReadFile(filePath: string): Promise
Resurslarni Boshqarish: Fayl Deskriptorlarini Yopish
`fs.open` (yoki `fsPromises.open`) bilan ishlaganda, operatsiyalar tugagandan so'ng, hatto xatolar yuz berganda ham, fayl deskriptorlari har doim `fs.close` (yoki `fileHandle.close()`) yordamida yopilishini ta'minlash juda muhimdir. Buni qilmaslik resurslarning oqib ketishiga, operatsion tizimning ochiq fayllar chegarasiga yetishiga va potentsial ravishda ilovangizning ishdan chiqishiga yoki boshqa jarayonlarga ta'sir qilishiga olib kelishi mumkin.
`FileHandle` ob'ektlari bilan `fs/promises` API odatda buni soddalashtiradi, chunki `fileHandle.close()` aynan shu maqsadda ishlab chiqilgan va `FileHandle` namunalari `Disposable` hisoblanadi (agar Node.js 18.11.0+ va TypeScript 5.2+ dan foydalanilsa).
Yo'llarni Boshqarish va Kross-Platforma Muvofiqligi
Fayl yo'llari operatsion tizimlar o'rtasida sezilarli darajada farq qiladi (masalan, Windows-da `\`, Unix-ga o'xshash tizimlarda `/`). Node.js `path` moduli fayl yo'llarini kross-platformaga mos keladigan tarzda qurish va tahlil qilish uchun ajralmas vositadir, bu global joylashtirishlar uchun muhimdir.
- `path.join(...paths)`: Barcha berilgan yo'l segmentlarini birlashtiradi va natijaviy yo'lni normallashtiradi.
- `path.resolve(...paths)`: Yo'llar yoki yo'l segmentlari ketma-ketligini mutlaq yo'lga aylantiradi.
- `path.basename(path)`: Yo'lning oxirgi qismini qaytaradi.
- `path.dirname(path)`: Yo'lning direktoriya nomini qaytaradi.
- `path.extname(path)`: Yo'lning kengaytmasini qaytaradi.
TypeScript `path` moduli uchun to'liq turdagi ta'riflarni taqdim etadi, bu esa uning funksiyalaridan to'g'ri foydalanishingizni ta'minlaydi.
import * as path from 'path';
const dir = 'my_app_data';
const filename = 'config.json';
// Kross-platforma yo'llarni birlashtirish
const fullPath: string = path.join(__dirname, dir, filename);
console.log(`Kross-platforma yo'li: ${fullPath}`);
// Direktoriya nomini olish
const dirname: string = path.dirname(fullPath);
console.log(`Direktoriya nomi: ${dirname}`);
// Asosiy fayl nomini olish
const basename: string = path.basename(fullPath);
console.log(`Asosiy nom: ${basename}`);
// Fayl kengaytmasini olish
const extname: string = path.extname(fullPath);
console.log(`Kengaytma: ${extname}`);
Bir vaqtda ishlash va Poyga Shartlari (Race Conditions)
Bir nechta asinxron fayl operatsiyalari bir vaqtning o'zida, ayniqsa yozish yoki o'chirishlar boshlanganda, poyga shartlari yuzaga kelishi mumkin. Masalan, agar bir operatsiya faylning mavjudligini tekshirsa va boshqasi birinchi operatsiya harakat qilishidan oldin uni o'chirib tashlasa, birinchi operatsiya kutilmaganda muvaffaqiyatsiz bo'lishi mumkin.
- Muhim yo'l mantig'i uchun `fs.existsSync` dan qoching; `fs.access` ni afzal ko'ring yoki shunchaki operatsiyani sinab ko'ring va xatoni qayta ishlang.
- Eksklyuziv kirishni talab qiladigan operatsiyalar uchun tegishli `flag` opsiyalaridan foydalaning (masalan, eksklyuziv yozish uchun `'wx'`).
- Juda muhim umumiy resurslarga kirish uchun blokirovka mexanizmlarini (masalan, fayl blokirovkalari yoki dastur darajasidagi blokirovkalar) joriy qiling, garchi bu murakkablikni oshirsa ham.
Ruxsatlar (ACLs)
Fayl tizimi ruxsatlari (Kirishni Boshqarish Ro'yxatlari yoki standart Unix ruxsatlari) keng tarqalgan xato manbai hisoblanadi. Node.js jarayoningiz fayllar va direktoriyalarni o'qish, yozish yoki bajarish uchun kerakli ruxsatlarga ega ekanligiga ishonch hosil qiling. Bu, ayniqsa, konteynerlashtirilgan muhitlarda yoki jarayonlar maxsus foydalanuvchi hisoblari bilan ishlaydigan ko'p foydalanuvchili tizimlarda dolzarbdir.
Xulosa: Global Fayl Tizimi Operatsiyalari uchun Tur Xavfsizligini Qabul Qilish
Node.js `fs` moduli fayl tizimi bilan o'zaro ishlash uchun kuchli va ko'p qirrali vosita bo'lib, oddiy fayl manipulyatsiyalaridan tortib ilg'or oqimga asoslangan ma'lumotlarni qayta ishlashgacha bo'lgan keng imkoniyatlarni taklif etadi. Ushbu operatsiyalar ustiga TypeScript-ni qo'llash orqali siz bebaho afzalliklarga ega bo'lasiz: kompilyatsiya vaqtidagi xatolarni aniqlash, yaxshilangan kod aniqligi, yuqori darajadagi vositalarni qo'llab-quvvatlash va refaktoring paytida ishonchning ortishi. Bu, ayniqsa, turli kod bazalari bo'ylab izchillik va noaniqlikni kamaytirish hayotiy muhim bo'lgan global ishlab chiqish jamoalari uchun juda muhimdir.
Kichik yordamchi skript yoki yirik korporativ dastur yaratayotgan bo'lsangiz ham, Node.js fayl operatsiyalaringiz uchun TypeScript-ning mustahkam tur tizimidan foydalanish yanada qo'llab-quvvatlanadigan, ishonchli va xatolarga chidamli kodga olib keladi. Toza asinxron naqshlar uchun `fs/promises` API-ni qabul qiling, sinxron va asinxron chaqiruvlar o'rtasidagi nozikliklarni tushuning va har doim mustahkam xatolarni qayta ishlash va kross-platforma yo'llarni boshqarishga ustunlik bering.
Ushbu qo'llanmada muhokama qilingan tamoyillar va misollarni qo'llash orqali butun dunyodagi dasturchilar nafaqat samarali va unumli, balki tabiatan xavfsizroq va tushunish osonroq bo'lgan fayl tizimi o'zaro ta'sirlarini yaratishlari mumkin, bu esa natijada yuqori sifatli dasturiy ta'minot mahsulotlariga hissa qo'shadi.