18-bo‘lim
Fayllar va kirish-chiqish
Path va Files sinflari, matn o'qish va yozish, kodlash muammosi, kataloglar bilan ishlash, oqim sifatida o'qish va CSV tahlili.
Ushbu bo‘lim mundarijasi
Dastur ishini saqlab qolishi kerak. Java'da fayl bilan ishlashning
zamonaviy usuli - java.nio.file paketi.
Path va Files #
import java.nio.file.*;
public class Yollar {
public static void main(String[] args) {
Path yol = Path.of("hujjatlar", "hisobot", "2026-yil.txt");
System.out.println("To'liq yo'l: " + yol);
System.out.println("Fayl nomi: " + yol.getFileName());
System.out.println("Papka: " + yol.getParent());
System.out.println("Qismlar soni: " + yol.getNameCount());
System.out.println("Mutlaqmi: " + yol.isAbsolute());
System.out.println("Qo'shilgan: " + yol.resolveSibling("eski.txt"));
}
}
To'liq yo'l: hujjatlar\hisobot\2026-yil.txt
Fayl nomi: 2026-yil.txt
Papka: hujjatlar\hisobot
Qismlar soni: 3
Mutlaqmi: false
Qo'shilgan: hujjatlar\hisobot\eski.txt
Yuqoridagi chiqishda teskari chiziq (\) ko'rinadi, chunki misol
Windows'da bajarildi. Linux va macOS'da xuddi shu kod to'g'ri
chiziq (/) chiqaradi.
Aynan shuning uchun yo'llarni qo'lda birlashtirmang:
String yomon = "hujjatlar" + "\\" + "fayl.txt"; // faqat Windows
Path yaxshi = Path.of("hujjatlar", "fayl.txt"); // hamma joyda
Path.of ishlayotgan tizimga mos ajratuvchini o'zi qo'yadi. Bu
darslikdagi yagona misol bo'lib, uning natijasi tizimga bog'liq -
qolgan hamma narsa hamma joyda bir xil.
Matn yozish va o'qish #
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
public class Matn {
public static void main(String[] args) throws IOException {
Path yol = Files.createTempFile("sinov", ".txt");
Files.writeString(yol, "Birinchi qator\nIkkinchi qator",
StandardCharsets.UTF_8);
String matn = Files.readString(yol, StandardCharsets.UTF_8);
System.out.println("Uzunligi: " + matn.length());
System.out.println(matn);
System.out.println("Mavjudmi: " + Files.exists(yol));
Files.delete(yol);
System.out.println("O'chirilgach: " + Files.exists(yol));
}
}
Uzunligi: 29
Birinchi qator
Ikkinchi qator
Mavjudmi: true
O'chirilgach: false
Files.readString(yol) deb yozsangiz ham ishlaydi, lekin
StandardCharsets.UTF_8 ni oshkora berish yaxshi odat.
Java 18 gacha sukut kodlash operatsion tizim sozlamasidan
olinardi. Ya'ni Windows'da fayl windows-1251 da o'qilishi, Linux'da
esa UTF-8 da o'qilishi mumkin edi - va o'zbek harflari buzilib
chiqardi.
Java 18 dan sukut UTF-8 ga o'tdi, lekin:
- eski Java versiyalarida kod boshqacha ishlaydi;
FileReaderkabi eski sinflar hali ham tizim sozlamasiga tayanadi.
Qoida: fayl bilan ishlaganda kodlashni har doim yozing. Bu bir necha belgi qo'shimcha, lekin o'zbek matni bilan ishlaganda jiddiy muammodan saqlaydi.
Qatorlar bilan ishlash #
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.List;
public class Qatorlar {
public static void main(String[] args) throws IOException {
Path yol = Files.createTempFile("shaharlar", ".txt");
Files.write(yol, List.of("Namangan", "Andijon", "Samarqand"),
StandardCharsets.UTF_8);
List<String> qatorlar =
Files.readAllLines(yol, StandardCharsets.UTF_8);
System.out.println(qatorlar.size() + " ta qator:");
for (int i = 0; i < qatorlar.size(); i++) {
System.out.println(" " + (i + 1) + ". " + qatorlar.get(i));
}
Files.writeString(yol, "Toshkent\n", StandardCharsets.UTF_8,
StandardOpenOption.APPEND);
System.out.println("Qo'shilgach: "
+ Files.readAllLines(yol, StandardCharsets.UTF_8).size()
+ " ta");
Files.delete(yol);
}
}
3 ta qator:
1. Namangan
2. Andijon
3. Samarqand
Qo'shilgach: 4 ta
Files.writeString sukut bo'yicha ustiga yozadiQo'shish uchun StandardOpenOption.APPEND berish shart. Usiz
mavjud mazmun butunlay almashtiriladi va hech qanday ogohlantirish
bo'lmaydi.
Boshqa foydali variantlar:
| Variant | Nima qiladi |
|---|---|
CREATE | Yo'q bo'lsa yaratadi (sukut) |
APPEND | Oxiriga qo'shadi |
TRUNCATE_EXISTING | Mavjudini tozalaydi (sukut) |
CREATE_NEW | Faqat yangi yaratadi, bor bo'lsa istisno |
CREATE_NEW mavjud faylni tasodifan buzib qo'yishdan himoya qiladi.
Oqim sifatida o'qish #
Katta faylni butunlay xotiraga yuklamaslik uchun:
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.List;
import java.util.stream.Stream;
public class OqimBilan {
public static void main(String[] args) throws IOException {
Path yol = Files.createTempFile("ballar", ".txt");
Files.write(yol, List.of("92", "78", "85", "", "95", "64"),
StandardCharsets.UTF_8);
try (Stream<String> qatorlar =
Files.lines(yol, StandardCharsets.UTF_8)) {
var statistika = qatorlar
.filter(q -> !q.isBlank())
.mapToInt(Integer::parseInt)
.summaryStatistics();
System.out.println("Soni: " + statistika.getCount());
System.out.println("Yig'indi: " + statistika.getSum());
System.out.println("Eng past: " + statistika.getMin());
System.out.println("Eng yuqori: " + statistika.getMax());
}
Files.delete(yol);
}
}
Soni: 5
Yig'indi: 414
Eng past: 64
Eng yuqori: 95
Files.lines ni try-with-resources ichida ishlatingFiles.lines ochiq fayl deskriptorini ushlab turadi va u
AutoCloseable. Uni yopmasangiz, fayl ochiq qoladi.
Bitta faylda bu sezilmaydi. Lekin minglab faylni qayta ishlaydigan dasturda tizim chegarasi tugaydi:
java.nio.file.FileSystemException: Too many open files
Files.readAllLines esa faylni to'liq o'qib, darhol yopadi - unda
bu muammo yo'q, lekin katta fayl xotirani to'ldiradi.
Qoida: kichik fayl - readAllLines, katta fayl -
try (Stream<String> ...).
Kataloglar #
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.stream.Stream;
public class Kataloglar {
public static void main(String[] args) throws IOException {
Path asos = Files.createTempDirectory("sinov");
Path ichki = asos.resolve("ichki");
Files.createDirectories(ichki);
Files.writeString(asos.resolve("a.txt"), "a", StandardCharsets.UTF_8);
Files.writeString(asos.resolve("b.txt"), "bb",
StandardCharsets.UTF_8);
Files.writeString(ichki.resolve("c.txt"), "ccc",
StandardCharsets.UTF_8);
try (Stream<Path> yuza = Files.list(asos)) {
System.out.println("Faqat asosda: " + yuza.count() + " ta");
}
try (Stream<Path> chuqur = Files.walk(asos)) {
long fayllar = chuqur.filter(Files::isRegularFile).count();
System.out.println("Barcha fayllar: " + fayllar + " ta");
}
System.out.println("a.txt hajmi: "
+ Files.size(asos.resolve("a.txt")) + " bayt");
System.out.println("Katalogmi: " + Files.isDirectory(ichki));
ochir(asos);
System.out.println("O'chirilgach mavjudmi: " + Files.exists(asos));
}
static void ochir(Path yol) throws IOException {
try (Stream<Path> hammasi = Files.walk(yol)) {
for (Path p : hammasi.sorted((a, b) -> b.compareTo(a)).toList()) {
Files.delete(p);
}
}
}
}
Faqat asosda: 3 ta
Barcha fayllar: 3 ta
a.txt hajmi: 1 bayt
Katalogmi: true
O'chirilgach mavjudmi: false
Files.delete faqat bo'sh katalogni o'chiradi. To'la katalogni
o'chirish uchun avval ichidagilarni tozalash kerak.
Yuqoridagi ochir metodi buni teskari tartibda saralab hal
qiladi: Files.walk yuqoridan pastga yuradi, teskari saralash esa
eng chuqur fayllarni birinchi qo'yadi. Shunda har bir katalog
o'chirilayotganda allaqachon bo'sh bo'ladi.
Diqqat: bu kod haqiqiy loyihada xavfli - noto'g'ri yo'l berilsa ko'p narsani o'chirib yuborishi mumkin. Amalda tayyor kutubxona ishlating.
CSV o'qish #
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.*;
import java.util.stream.*;
public class Csv {
public static void main(String[] args) throws IOException {
Path yol = Files.createTempFile("jurnal", ".csv");
Files.write(yol, List.of(
"ism,ball,guruh",
"Husanboy,92,A",
"Malika,78,B",
"Nodira,85,A"), StandardCharsets.UTF_8);
List<Talaba> talabalar;
try (Stream<String> qatorlar =
Files.lines(yol, StandardCharsets.UTF_8)) {
talabalar = qatorlar
.skip(1)
.map(q -> q.split(","))
.map(q -> new Talaba(q[0], Integer.parseInt(q[1]), q[2]))
.toList();
}
talabalar.forEach(System.out::println);
Map<String, Double> ortacha = talabalar.stream()
.collect(Collectors.groupingBy(Talaba::guruh, TreeMap::new,
Collectors.averagingInt(Talaba::ball)));
System.out.println("Guruh o'rtachasi: " + ortacha);
Files.delete(yol);
}
}
record Talaba(String ism, int ball, String guruh) {
}
Talaba[ism=Husanboy, ball=92, guruh=A]
Talaba[ism=Malika, ball=78, guruh=B]
Talaba[ism=Nodira, ball=85, guruh=A]
Guruh o'rtachasi: {A=88.5, B=78.0}
split(",") dan murakkabroqYuqoridagi kod oddiy holatda ishlaydi, lekin haqiqiy CSV fayllarda:
- qiymat ichida vergul bo'lishi mumkin:
"Qodirov, Husanboy"; - qo'shtirnoq ichida yangi qator bo'lishi mumkin;
- qo'shtirnoqning o'zi ikkilantirilib yoziladi:
"".
Bunday fayllarni split(",") bilan o'qish buzilgan ma'lumot
beradi - va bu jimgina sodir bo'ladi.
Jiddiy ishda tayyor kutubxona ishlating (masalan Apache Commons CSV yoki OpenCSV). Bu darslikdagi misol faqat oqim bilan ishlashni ko'rsatish uchun.
Fayl xatolarini boshqarish #
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
public class Xatolar {
public static void main(String[] args) {
Path yoq = Path.of("bunday-fayl-yoq-12345.txt");
try {
Files.readString(yoq, StandardCharsets.UTF_8);
} catch (NoSuchFileException x) {
System.out.println("Fayl topilmadi: " + x.getFile());
} catch (IOException x) {
System.out.println("Kirish-chiqish xatosi: " + x.getMessage());
}
System.out.println("Mavjudmi: " + Files.exists(yoq));
System.out.println("O'qish mumkinmi: " + Files.isReadable(yoq));
}
}
Fayl topilmadi: bunday-fayl-yoq-12345.txt
Mavjudmi: false
O'qish mumkinmi: false
IOException ni oxiriga qo'yingNoSuchFileException IOException dan meros oladi. Shuning uchun
IOException ni yuqoriga qo'ysangiz, aniqroq turlar hech qachon
ishlamaydi - va kompilyator bu haqda xato beradi (13-bo'lim).
Foydali maxsus turlar:
| Tur | Qachon |
|---|---|
NoSuchFileException | Fayl yo'q |
FileAlreadyExistsException | CREATE_NEW da fayl bor |
AccessDeniedException | Ruxsat yo'q |
DirectoryNotEmptyException | Bo'sh bo'lmagan katalogni o'chirish |
Eski va yangi API #
Eski (java.io) | Yangi (java.nio.file) |
|---|---|
File | Path |
new FileReader(f) | Files.readString |
new FileWriter(f) | Files.writeString |
f.delete() - boolean qaytaradi | Files.delete - istisno tashlaydi |
f.listFiles() | Files.list |
Eng muhim farq - xato haqida xabar berish.
Eski File.delete() shunchaki false qaytaradi. Nega? Fayl yo'qmi,
ruxsat yo'qmi, band'mi - bilib bo'lmaydi. Va ko'pchilik natijani
umuman tekshirmaydi.
Files.delete() esa aniq istisno tashlaydi va sababini aytadi.
Yangi kodda har doim Path va Files ishlating. Eski File
faqat eski kutubxonalar bilan ishlaganda kerak bo'ladi - bunday
holatda file.toPath() va path.toFile() yordam beradi.
Path.ofbilan yo'l yaratib, qismlarini chiqaring.- Faylga matn yozing va qaytadan o'qing.
- Kodlashni oshkora ko'rsatmasdan o'zbekcha matn yozib ko'ring.
APPENDbilan va usiz yozib, farqni ko'ring.Files.linesnitry-with-resourcesichida ishlating.- Katalog yaratib, ichida fayllar yarating va sanang.
Files.walkbilan ichki fayllarni ham sanang.- CSV faylni o'qib,
recordro'yxatiga aylantiring. - Mavjud bo'lmagan faylni o'qib,
NoSuchFileExceptionni ushlang. IOExceptionni yuqoriga qo'yib, kompilyator nima deyishini ko'ring.
Xulosa #
- Zamonaviy API -
PathvaFiles, eskiFileemas. - Yo'llarni
Path.ofbilan quring - ajratuvchi tizimga bog'liq. - Fayl bilan ishlaganda kodlashni oshkora ko'rsating
(
StandardCharsets.UTF_8). Files.writeStringsukut bo'yicha ustiga yozadi - qo'shish uchunAPPEND.- Kichik fayl uchun
readAllLines, katta fayl uchunFiles.linesvatry-with-resources. Files.deletefaqat bo'sh katalogni o'chiradi.split(",")bilan haqiqiy CSV o'qib bo'lmaydi - kutubxona ishlating.catchdaIOExceptionni oxiriga qo'ying.
Keyingi bo'limda kodni sinovdan o'tkazishni o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.