Bagaimana cara menghapus semua file dan folder dalam direktori?


663

Dengan menggunakan C #, bagaimana saya bisa menghapus semua file dan folder dari direktori, tetapi masih menyimpan direktori root?


11
Apa yang akan menyenangkan jika DirectoryInfo memiliki metode seperti .Clean ();
JL.

6
atau .DeleteFolders, dan metode DeleteFiles.
JL.

18
Anda ingin mengetahui bahwa Menghapus Anda dapat dengan mudah melempar pengecualian jika file terkunci (atau jika Anda tidak memiliki hak). Lihat FileInfo.Delete untuk daftar pengecualian.
Shane Courtrille

Jawaban:


834
System.IO.DirectoryInfo di = new DirectoryInfo("YourPath");

foreach (FileInfo file in di.GetFiles())
{
    file.Delete(); 
}
foreach (DirectoryInfo dir in di.GetDirectories())
{
    dir.Delete(true); 
}

Jika direktori Anda mungkin memiliki banyak file, EnumerateFiles()lebih efisien daripada GetFiles(), karena ketika Anda menggunakan EnumerateFiles()Anda dapat mulai menghitungnya sebelum seluruh koleksi dikembalikan, sebagai lawan di GetFiles()mana Anda perlu memuat seluruh koleksi dalam memori sebelum mulai menghitungnya. Lihat kutipan ini di sini :

Karenanya, saat Anda bekerja dengan banyak file dan direktori, EnumerateFiles () dapat lebih efisien.

Hal yang sama berlaku untuk EnumerateDirectories()dan GetDirectories(). Jadi kodenya adalah:

foreach (FileInfo file in di.EnumerateFiles())
{
    file.Delete(); 
}
foreach (DirectoryInfo dir in di.EnumerateDirectories())
{
    dir.Delete(true); 
}

Untuk keperluan pertanyaan ini, sebenarnya tidak ada alasan untuk menggunakan GetFiles()dan GetDirectories().


6
Apa itu tentang stackoverflow.com/questions/12415105/... "Ketika Anda memanggil Directory.Delete dan sebuah file terbuka sedemikian rupa, Directory.Delete berhasil menghapus semua file tetapi ketika Directory.Delete memanggil RemoveDirectory sebuah" direktori tidak kosong " pengecualian dilemparkan karena ada file yang ditandai untuk dihapus tetapi sebenarnya tidak dihapus. "
Kiquenet

74
DirectoryInfo lambat karena ini mengumpulkan lebih banyak data lainnya. BTW: Directory.Delete(path, true)akan mengurus semuanya :)
AcidJunkie

57
@AcidJunkie, Itu juga akan menghapus direktori yang dimaksud, sedangkan OP secara khusus meminta direktori root untuk disimpan.
Marc L.

5
Perhatikan bahwa ini tidak akan berfungsi jika ada file yang hanya baca. Anda harus menghapus tanda baca-saja sebelum menelepon file.Delete().
Ben

8
Ini tampaknya tidak berfungsi jika sub-direktori berisi file.
cdiggins

174

Ya, itulah cara yang benar untuk melakukannya. Jika Anda ingin memberi diri Anda fungsi "Bersihkan" (atau, seperti saya lebih suka menyebutnya, fungsi "Kosong"), Anda dapat membuat metode ekstensi.

public static void Empty(this System.IO.DirectoryInfo directory)
{
    foreach(System.IO.FileInfo file in directory.GetFiles()) file.Delete();
    foreach(System.IO.DirectoryInfo subDirectory in directory.GetDirectories()) subDirectory.Delete(true);
}

Ini kemudian akan memungkinkan Anda untuk melakukan sesuatu seperti ..

System.IO.DirectoryInfo directory = new System.IO.DirectoryInfo(@"C:\...");

directory.Empty();

4
Baris terakhir adalah subDirectory.Delete (true), bukan direktori.Delete (true). Saya hanya memotong dan menempelkan kode dan menghapus direktori utama itu sendiri. Terima kasih untuk kodenya bagus!
Aximili

26
catatan yang sudah Emptyada di C #, untuk string. Jika saya melihat sesuatu yang bernama Emptysaya akan terkejut jika itu memodifikasi objek (atau filesystem) daripada memberi saya boolyang mengatakan apakah itu kosong atau tidak. Karena itu, saya akan menggunakan nama itu Clean.
Default

5
@ Kesalahan: Saya tidak berpikir fakta bahwa satu jenis memiliki properti sudah harus memiliki kaitan pada apakah jenis lain (sama sekali tidak terkait) harus memilikinya; dan konvensi untuk properti dan fungsi yang mengindikasikan status untuk kata-kata yang juga bisa menjadi kata kerja adalah untuk mengawali kata-kata tersebut Is(yaitu, IsEmptybukan Empty).
Adam Robinson

3
@AdamRobinson Hanya ingin mencatatnya. Bagi saya , apa yang dimiliki Microsoft dalam kode mereka memiliki kaitan. Tapi itu untuk semua orang menafsirkan :)
Default

4
@simonhaines: Inti pertanyaannya adalah mengosongkan direktori (mis. hapus semua yang ada di dalamnya ), bukan untuk menghapus direktori itu sendiri.
Adam Robinson

77

Kode berikut akan menghapus folder secara rekursif:

private void clearFolder(string FolderName)
{
    DirectoryInfo dir = new DirectoryInfo(FolderName);

    foreach(FileInfo fi in dir.GetFiles())
    {
        fi.Delete();
    }

    foreach (DirectoryInfo di in dir.GetDirectories())
    {
        clearFolder(di.FullName);
        di.Delete();
    }
}

Bekerja untuk saya, sementara Directory.Delete (path, true); melemparkan mengeluh bahwa folder itu tidak kosong
Jack Griffin

40
 new System.IO.DirectoryInfo(@"C:\Temp").Delete(true);

 //Or

 System.IO.Directory.Delete(@"C:\Temp", true);

1
Opsi kedua, Directory.Delete (String, Boolean) bekerja untuk saya.
Stephen MacDougall

15
Ini menghapus direktori root, di mana OP secara khusus meminta itu dipertahankan.
Marc L.

2
Deleteakan melempar jika direktori tidak ada, jadi akan lebih aman untuk melakukan Directory.Existspemeriksaan terlebih dahulu.
James

1
@ James Directory.Existstidak cukup; setelah pemeriksaan, utas lainnya mungkin telah mengganti nama atau menghapus direktori. Itu lebih aman try-catch.
andre_ss6

2
@Marv Hati-hati dengan hanya menambahkan Directory.Createkarena rekursif Directory.Deletesayangnya tidak dijamin sinkron ..
Andrew Hanlon

38

Kami juga dapat menunjukkan cinta untuk LINQ :

using System.IO;
using System.Linq;

var directory = Directory.GetParent(TestContext.TestDir);

directory.EnumerateFiles()
    .ToList().ForEach(f => f.Delete());

directory.EnumerateDirectories()
    .ToList().ForEach(d => d.Delete(true));

Perhatikan bahwa solusi saya di sini bukan Get*().ToList().ForEach(...)pemain , karena saya menggunakan yang menghasilkan IEnumerabledua kali sama . Saya menggunakan metode ekstensi untuk menghindari masalah ini:

using System.IO;
using System.Linq;

var directory = Directory.GetParent(TestContext.TestDir);

directory.EnumerateFiles()
    .ForEachInEnumerable(f => f.Delete());

directory.EnumerateDirectories()
    .ForEachInEnumerable(d => d.Delete(true));

Ini adalah metode ekstensi:

/// <summary>
/// Extensions for <see cref="System.Collections.Generic.IEnumerable"/>.
/// </summary>
public static class IEnumerableOfTExtensions
{
    /// <summary>
    /// Performs the <see cref="System.Action"/>
    /// on each item in the enumerable object.
    /// </summary>
    /// <typeparam name="TEnumerable">The type of the enumerable.</typeparam>
    /// <param name="enumerable">The enumerable.</param>
    /// <param name="action">The action.</param>
    /// <remarks>
    /// “I am philosophically opposed to providing such a method, for two reasons.
    /// …The first reason is that doing so violates the functional programming principles
    /// that all the other sequence operators are based upon. Clearly the sole purpose of a call
    /// to this method is to cause side effects.”
    /// —Eric Lippert, “foreach” vs “ForEach” [http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx]
    /// </remarks>
    public static void ForEachInEnumerable<TEnumerable>(this IEnumerable<TEnumerable> enumerable, Action<TEnumerable> action)
    {
        foreach (var item in enumerable)
        {
            action(item);
        }
    }
}

1
Dan jika Anda mencoba untuk menghapus subdirektori juga, foreach (var dir in info.GetDirectories("*", SearchOption.AllDirectories).OrderByDescending(dir => dir.FullName.Length)) dir.Delete();mungkin berguna.
Warty

1
Jika Anda menyukai kinerja, pertimbangkan untuk menggunakan directory.EnumerateFiles()dan directory.EnumerateDirectories()alih-alih directory.Get*()metode.
Tinister

1
Lucu, IEnumerable<T>.ForEach()ekstensi saya sendiri memiliki ringkasan komentar XML, "Pelanggaran! Pelanggaran! Tidak bersih!".
Marc L.

Hei apa alasan ke-2? Ke 3? Dll?
Bill Roberts

lol @RASX - dia berbicara kepada Anda: "Jika Anda tidak setuju dengan keberatan filosofis ini dan menemukan nilai praktis dalam pola ini, dengan segala cara, silakan dan tulis sendiri satu-liner sepele ini sendiri."
Bill Roberts

37

Cara paling sederhana:

Directory.Delete(path,true);  
Directory.CreateDirectory(path);

Ketahuilah bahwa ini dapat menghapus beberapa izin pada folder.


9
Ketahuilah bahwa ini akan menghapus izin khusus yang dimiliki jalur tersebut
Matthew Lock

6
Anda perlu menambahkan batas waktu antara kedua tindakan tersebut. coba jalankan kode ini dan Anda akan mendapatkan Pengecualian: while (true) {Directory.Delete (@ "C: \ Myfolder", true); Directory.CreateDirectory (@ "C: \ Myfolder"); }
RcMan

31
private void ClearFolder(string FolderName)
{
    DirectoryInfo dir = new DirectoryInfo(FolderName);

    foreach(FileInfo fi in dir.GetFiles())
    {
        try
        {
            fi.Delete();
        }
        catch(Exception) { } // Ignore all exceptions
    }

    foreach(DirectoryInfo di in dir.GetDirectories())
    {
        ClearFolder(di.FullName);
        try
        {
            di.Delete();
        }
        catch(Exception) { } // Ignore all exceptions
    }
}

Jika Anda tahu tidak ada sub-folder, sesuatu seperti ini mungkin yang paling mudah:

    Directory.GetFiles(folderName).ForEach(File.Delete)

Saya menggunakan fungsi ini untuk menghapus folder temp sistem. Saya baru saja menambahkan coba-tangkap di sekitar Hapus () dan IsReadOnly untuk mengabaikan semua pengecualian, dan itu berhasil.
humbads

@Humbads, dapatkah Anda memperbarui jawaban ini, atau memasukkan kode di sini, dan saya akan memperbarui dengan perubahan Anda?
zumalifeguard

13
System.IO.Directory.Delete(installPath, true);
System.IO.Directory.CreateDirectory(installPath);

3
sama seperti di atas: perlu diketahui bahwa ini akan menghapus izin khusus yang dimiliki jalur.
hB0

8

Setiap metode yang saya coba, mereka gagal di beberapa titik dengan kesalahan System.IO. Metode berikut ini berfungsi dengan pasti, meskipun folder kosong atau tidak, hanya baca atau tidak, dll.

ProcessStartInfo Info = new ProcessStartInfo();  
Info.Arguments = "/C rd /s /q \"C:\\MyFolder"";  
Info.WindowStyle = ProcessWindowStyle.Hidden;  
Info.CreateNoWindow = true;  
Info.FileName = "cmd.exe";  
Process.Start(Info); 

1
Saya selalu lebih suka rd / s / q + mkdir dalam hal pengosongan direktori.
Dawid Ohia

7
Ini bukan solusi lintas platform. Sistem mirip Unix jelas tidak memiliki cmd.exe, mereka bahkan tidak menjalankan file .exe. C # bukan hanya Windows, ada juga Mono, yang merupakan cross-platform.
Nama Tampilan

1
@SargeBorsch tidak ada persyaratan lintas platform dalam pertanyaan dan menjadi C # kemungkinan besar solusinya akan digunakan untuk Windows. Tampaknya menjadi satu-satunya jawaban yang tidak menggunakan fungsi .NET, jadi itu cukup berharga sebagai alternatif.
Alex Pandrea

7

Ini adalah alat yang saya akhiri setelah membaca semua posting. Itu benar

  • Hapus semua yang bisa dihapus
  • Mengembalikan nilai false jika beberapa file tetap ada di folder

Ini berhubungan dengan

  • Hanya baca file
  • Delay penghapusan
  • File terkunci

Itu tidak menggunakan Directory.Delete karena proses dibatalkan dengan pengecualian.

    /// <summary>
    /// Attempt to empty the folder. Return false if it fails (locked files...).
    /// </summary>
    /// <param name="pathName"></param>
    /// <returns>true on success</returns>
    public static bool EmptyFolder(string pathName)
    {
        bool errors = false;
        DirectoryInfo dir = new DirectoryInfo(pathName);

        foreach (FileInfo fi in dir.EnumerateFiles())
        {
            try
            {
                fi.IsReadOnly = false;
                fi.Delete();

                //Wait for the item to disapear (avoid 'dir not empty' error).
                while (fi.Exists)
                {
                    System.Threading.Thread.Sleep(10);
                    fi.Refresh();
                }
            }
            catch (IOException e)
            {
                Debug.WriteLine(e.Message);
                errors = true;
            }
        }

        foreach (DirectoryInfo di in dir.EnumerateDirectories())
        {
            try
            {
                EmptyFolder(di.FullName);
                di.Delete();

                //Wait for the item to disapear (avoid 'dir not empty' error).
                while (di.Exists)
                {
                    System.Threading.Thread.Sleep(10);
                    di.Refresh();
                }
            }
            catch (IOException e)
            {
                Debug.WriteLine(e.Message);
                errors = true;
            }
        }

        return !errors;
    }

6

Kode berikut akan membersihkan direktori, tetapi meninggalkan direktori root di sana (rekursif).

Action<string> DelPath = null;
DelPath = p =>
{
    Directory.EnumerateFiles(p).ToList().ForEach(File.Delete);
    Directory.EnumerateDirectories(p).ToList().ForEach(DelPath);
    Directory.EnumerateDirectories(p).ToList().ForEach(Directory.Delete);
};
DelPath(path);

6

Saya menggunakan

Directory.GetFiles(picturePath).ToList().ForEach(File.Delete);

untuk menghapus gambar lama dan saya tidak memerlukan objek apa pun di folder ini


1
Tidak yakin Anda memerlukan .ToList ()
Ben Power

5

Hanya menggunakan metode statis dengan File dan Direktori, bukan FileInfo dan DirectoryInfo akan melakukan lebih cepat. (lihat jawaban yang diterima di Apa perbedaan antara File dan FileInfo di C #? ). Jawaban ditampilkan sebagai metode utilitas.

public static void Empty(string directory)
{
    foreach(string fileToDelete in System.IO.Directory.GetFiles(directory))
    {
        System.IO.File.Delete(fileToDelete);
    }
    foreach(string subDirectoryToDeleteToDelete in System.IO.Directory.GetDirectories(directory))
    {
        System.IO.Directory.Delete(subDirectoryToDeleteToDelete, true);
    }
}

5
private void ClearFolder(string FolderName)
{
    DirectoryInfo dir = new DirectoryInfo(FolderName);

    foreach (FileInfo fi in dir.GetFiles())
    {
        fi.IsReadOnly = false;
        fi.Delete();
    }

    foreach (DirectoryInfo di in dir.GetDirectories())
    {
        ClearFolder(di.FullName);
        di.Delete();
    }
}

3
string directoryPath = "C:\Temp";
Directory.GetFiles(directoryPath).ToList().ForEach(File.Delete);
Directory.GetDirectories(directoryPath).ToList().ForEach(Directory.Delete);

Pengecualian dari tipe 'System.IO.IOException' terjadi di mscorlib.dll tetapi tidak ditangani dalam kode pengguna Informasi tambahan: Direktori tidak kosong.
kipusoep

3

Di Windows 7, jika Anda baru saja membuatnya secara manual dengan Windows Explorer, struktur direktori mirip dengan yang ini:

C:
  \AAA
    \BBB
      \CCC
        \DDD

Dan menjalankan kode yang disarankan dalam pertanyaan asli untuk membersihkan direktori C: \ AAA, baris di.Delete(true)selalu gagal dengan IOException "Direktori tidak kosong" ketika mencoba untuk menghapus BBB. Mungkin karena beberapa jenis keterlambatan / caching di Windows Explorer.

Kode berikut bekerja dengan andal bagi saya:

static void Main(string[] args)
{
    DirectoryInfo di = new DirectoryInfo(@"c:\aaa");
    CleanDirectory(di);
}

private static void CleanDirectory(DirectoryInfo di)
{
    if (di == null)
        return;

    foreach (FileSystemInfo fsEntry in di.GetFileSystemInfos())
    {
        CleanDirectory(fsEntry as DirectoryInfo);
        fsEntry.Delete();
    }
    WaitForDirectoryToBecomeEmpty(di);
}

private static void WaitForDirectoryToBecomeEmpty(DirectoryInfo di)
{
    for (int i = 0; i < 5; i++)
    {
        if (di.GetFileSystemInfos().Length == 0)
            return;
        Console.WriteLine(di.FullName + i);
        Thread.Sleep(50 * i);
    }
}

Apa itu tentang stackoverflow.com/questions/12415105/... "Ketika Anda memanggil Directory.Delete dan sebuah file terbuka sedemikian rupa, Directory.Delete berhasil menghapus semua file tetapi ketika Directory.Delete memanggil RemoveDirectory sebuah" direktori tidak kosong " pengecualian dilemparkan karena ada file yang ditandai untuk dihapus tetapi sebenarnya tidak dihapus. "
Kiquenet

@Kiquenet: Sepertinya kami menemukan masalah di Windows. Windows dapat berkonsultasi daftar file yang ditandai untuk dihapus dan jika semua file dalam direktori ditandai untuk dihapus, jangan katakan direktori itu tidak kosong. Bagaimanapun, WaitForDirectoryToBecomeEmpty () saya adalah solusi.
farfareast

2

Versi ini tidak menggunakan panggilan rekursif, dan menyelesaikan masalah hanya baca.

public static void EmptyDirectory(string directory)
{
    // First delete all the files, making sure they are not readonly
    var stackA = new Stack<DirectoryInfo>();
    stackA.Push(new DirectoryInfo(directory));

    var stackB = new Stack<DirectoryInfo>();
    while (stackA.Any())
    {
        var dir = stackA.Pop();
        foreach (var file in dir.GetFiles())
        {
            file.IsReadOnly = false;
            file.Delete();
        }
        foreach (var subDir in dir.GetDirectories())
        {
            stackA.Push(subDir);
            stackB.Push(subDir);
        }
    }

    // Then delete the sub directories depth first
    while (stackB.Any())
    {
        stackB.Pop().Delete();
    }
}

1

gunakan metode GetDirectories DirectoryInfo.

foreach (DirectoryInfo subDir in new DirectoryInfo(targetDir).GetDirectories())
                    subDir.Delete(true);

1

Contoh berikut menunjukkan bagaimana Anda bisa melakukan itu. Pertama membuat beberapa direktori dan file dan kemudian menghapusnya melalui Directory.Delete(topPath, true);:

    static void Main(string[] args)
    {
        string topPath = @"C:\NewDirectory";
        string subPath = @"C:\NewDirectory\NewSubDirectory";

        try
        {
            Directory.CreateDirectory(subPath);

            using (StreamWriter writer = File.CreateText(subPath + @"\example.txt"))
            {
                writer.WriteLine("content added");
            }

            Directory.Delete(topPath, true);

            bool directoryExists = Directory.Exists(topPath);

            Console.WriteLine("top-level directory exists: " + directoryExists);
        }
        catch (Exception e)
        {
            Console.WriteLine("The process failed: {0}", e.Message);
        }
    }

Ini diambil dari https://msdn.microsoft.com/en-us/library/fxeahc5f(v=vs.110).aspx .


1

Itu bukan cara terbaik untuk menangani masalah di atas. Tapi itu alternatif ...

while (Directory.GetDirectories(dirpath).Length > 0)
 {
       //Delete all files in directory
       while (Directory.GetFiles(Directory.GetDirectories(dirpath)[0]).Length > 0)
       {
            File.Delete(Directory.GetFiles(dirpath)[0]);
       }
       Directory.Delete(Directory.GetDirectories(dirpath)[0]);
 }

0
DirectoryInfo Folder = new DirectoryInfo(Server.MapPath(path)); 
if (Folder .Exists)
{
    foreach (FileInfo fl in Folder .GetFiles())
    {
        fl.Delete();
    }

    Folder .Delete();
}

Bisakah Anda lebih spesifik dan menjelaskan bagaimana dan mengapa ini harus berhasil?
Deep Frozen

3
Jawaban hanya dengan kode tidak cocok. Anda harus menjelaskan bagaimana dan mengapa itu harus bekerja / menyelesaikan masalah.
rdurand

0

ini akan menunjukkan bagaimana kita menghapus folder dan memeriksanya kita menggunakan kotak teks

using System.IO;
namespace delete_the_folder
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Deletebt_Click(object sender, EventArgs e)
    {
        //the  first you should write the folder place
        if (Pathfolder.Text=="")
        {
            MessageBox.Show("ples write the path of the folder");
            Pathfolder.Select();
            //return;
        }

        FileAttributes attr = File.GetAttributes(@Pathfolder.Text);

        if (attr.HasFlag(FileAttributes.Directory))
            MessageBox.Show("Its a directory");
        else
            MessageBox.Show("Its a file");

        string path = Pathfolder.Text;
        FileInfo myfileinf = new FileInfo(path);
        myfileinf.Delete();

    }


}

}

0
using System.IO;

string[] filePaths = Directory.GetFiles(@"c:\MyDir\");

foreach (string filePath in filePaths)

File.Delete(filePath);

0

Panggilan dari utama

static void Main(string[] args)
{ 
   string Filepathe =<Your path>
   DeleteDirectory(System.IO.Directory.GetParent(Filepathe).FullName);              
}

Tambahkan metode ini

public static void DeleteDirectory(string path)
{
    if (Directory.Exists(path))
    {
        //Delete all files from the Directory
        foreach (string file in Directory.GetFiles(path))
        {
            File.Delete(file);
        }
        //Delete all child Directories
        foreach (string directory in Directory.GetDirectories(path))
        {
             DeleteDirectory(directory);
        }
        //Delete a Directory
        Directory.Delete(path);
    }
 }

0
 foreach (string file in System.IO.Directory.GetFiles(path))
 {
    System.IO.File.Delete(file);
 }

 foreach (string subDirectory in System.IO.Directory.GetDirectories(path))
 {
     System.IO.Directory.Delete(subDirectory,true); 
 } 

0

Untuk menghapus folder, ini adalah kode menggunakan kotak teks dan tombol using System.IO;:

private void Deletebt_Click(object sender, EventArgs e)
{
    System.IO.DirectoryInfo myDirInfo = new DirectoryInfo(@"" + delete.Text);

    foreach (FileInfo file in myDirInfo.GetFiles())
    {
       file.Delete();
    }
    foreach (DirectoryInfo dir in myDirInfo.GetDirectories())
    {
       dir.Delete(true);
    }
}

-2
private void ClearDirectory(string path)
{
    if (Directory.Exists(path))//if folder exists
    {
        Directory.Delete(path, true);//recursive delete (all subdirs, files)
    }
    Directory.CreateDirectory(path);//creates empty directory
}

2
Lihat di bawah ... "menghapus dan menciptakan kembali" tidak sama dengan menjaga, semua penyesuaian ACL akan hilang.
Marc L.

Saya sudah mencoba sesuatu yang sangat mirip dengan ini karena saya tidak peduli dan kustomisasi ACL dan mengalami masalah dengan folder yang tidak dibuat setelahDirectory.CreateDirectory
JG di SD

-3

Satu-satunya hal yang harus Anda lakukan adalah untuk mengatur optional recursive parameteruntuk True.

Directory.Delete("C:\MyDummyDirectory", True)

Terima kasih untuk .NET. :)


3
Ini juga menghapus direktori itu sendiri.
rajat

-4
IO.Directory.Delete(HttpContext.Current.Server.MapPath(path), True)

Anda tidak perlu lebih dari itu


2
Salah ... ini juga akan menghapus direktori root.
L-Four
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.