Знакомство с Microsoft .NET Framework

Часть 4. Работа с файлами и каталогами

Алексей Федоров

   Класс FileSystemInfo

   Класс FileInfo

   Класс DirectoryInfo

Перечисление Environment.SpecialFolder

   Класс File

   Класс Path

 

Мы завершаем знакомство с Microsoft .NET Framework (см. КомпьютерПресс № 11-12’2001, 1-5’2002) и библиотекой классов .NET Framework Class Library. В этом номере мы рассмотрим классы из пространства имен System.IO — FileSystemInfo, FileInfo, DirectoryInfo, File и Path, используемые для работы с файлами и каталогами.

Пространство имен System.IO содержит ряд классов, используемых для работы с файловой системой. Класс FileSystemInfo служит в качестве базового класса для классов FileInfo и DirectoryInfo. Для работы с файлами используется класс File, а для работы с каталогами — класс Directory. Упомянутые классы показаны на следующей диаграмме.

Обратите внимание на различия между показанными выше классами. Класс FileInfo предоставляет методы для создания, копирования, удаления, перемещения и открытия файлов и помогает в создании объектов типа FileStream. Класс File предоставляет статические методы — для их использования не требуется создавать экземпляр класса. Это справедливо и для классов DirectoryInfo и Directory. Классы FileInfo и DirectoryInfo являются «запечатанными» классами (sealed classes) — мы можем создавать экземпляры этих классов, но наследовать от них невозможно.

Класс FileSystemInfo

Этот класс определяет базовую функциональность для унаследованных классов — классов FileInfo и DirectoryInfo. Он содержит свойства и методы, общие для управления и файлами, и каталогами. Ниже приведен список свойств и методов класса FileSystemInfo.

  • Attributes — используется для получения или установки атрибутов файла. Это свойство имеет тип FileAttributes, который поддерживает битовые операции над значениями членов. Ниже показаны члены перечисления FileAttributes:
    • Archive — если данный атрибут установлен, значит файл готов к архивированию или к удалению,
    • Compressed — наличие его означает, что файл упакован,
    • Device — зарезервирован для будущих версий операционной системы,
    • Directory — указывает на то, что файл является каталогом,
    • Encrypted — если этот атрибут установлен, значит файл зашифрован,
    • Hidden — наличие его указывает на то, что файл скрыт от стандартных операций просмотра каталога,
    • Normal — указывает на то, что у файла не установлены другие атрибуты,
    • NotContentIndexed — файл не индексируется системой Windows Indexing System,
    • Offline — содержимое файла не доступно в режиме офлайн,
    • ReadOnly — содержимое файла не может быть изменено,
    • ReparsePoint — файл содержит блок данных, ассоциированных с файлом или каталогом,
    • SparsePoint — файл обычно содержит большой объем пустых данных,
    • System — файл является системным файлом — частью операционной системы или используется исключительно операционной системой,
    • Temporary — файл является временным файлом, созданным либо операционной системой, либо пользовательским приложением;
  • CreationTime — используется для получения или изменения даты создания файла. Это свойство имеет тип DateTime;
  • Exists — это булево свойство используется для подтверждения того, что файл или каталог существует;
  • Extension — возвращает строку, содержащую расширение имени файла;
  • FullName — это свойство используется для нахождения полного имени каталога или файла;
  • LastAccessTime и LastWriteTime — два этих свойства типа DateTime используются для получения или изменения даты последнего доступа или последней записи в файл или каталог соответственно;
  • Name — это свойство используется для нахождения имени файла или последнего каталога в иерархии каталогов;
  • Delete() — этот метод используется для удаления файла или каталога.

Вышеперечисленные свойства и методы доступны в классах, базирующихся на классе FileSystemInfo, — классах FileInfo и DirectoryInfo.

В начало В начало

Класс FileInfo

Этот класс, выполняющий роль «оболочки» вокруг маршрута к файлу, расширяет класс FileSystemInfo, добавляя к нему свойства и методы для манипуляции файлами. Класс FileInfo добавляет следующие свойства и методы:

  • Directory — это свойство возвращает объект DirectoryInfo, содержащий информацию о родительском каталоге;
  • DirectoryName — возвращает полный маршрут к файлу;
  • Length — возвращает размер текущего файла в виде значения типа Long;
  • AppendText() — этот метод создает класс StreamWriter, используемый для добавления к файлу текстовой информации;
  • CopyTo(String), или CopyTo(String, Boolean) — мы используем эти методы для копирования существующего файла в новый файл;
  • Create() — мы используем этот метод для создания файла — этот метод возвращает объект FileStream;
  • CreateText() — этот метод создает объект типа StreamWriter, используемый для записи в новый текстовый файл;
  • MoveTo(String) — этот метод используется для переименования файла или перемещения файла в другой каталог;
  • Open(FileMode), или Open(FileMode, FileAccess), или Open(FileMode, FileAccess, FileShare) — этот метод открывает файл и возвращает объект типа FileStream;
  • OpenRead() — мы используем данный метод для создания объекта FileStream с доступом к файлу только для чтения;
  • OpenText() — этот метод создает объект StreamReader с кодировкой UTF8, который используется для чтения из существующего файла;
  • OpenWrite() — мы используем данный метод для создания объекта FileStream с доступом к файлу как для чтения, так и для записи.

Диаграмма показывает, как методы класса FileInfo соотносятся с потоковыми классами.

Следующий пример демонстрирует, как использовать класс FileInfo для отображения размеров и атрибутов файлов в каталоге:

'----------------------------------------  
' Использование класса FileInfo  
'----------------------------------------  
   
Imports System  
Imports System.IO  
   
Module VBDemo  
   
 Sub Main()  
    
  Dim Path As String = GetPersonalFolder() & "\MyText"  
  Dim DirInfo As New DirectoryInfo(Path)  
  Dim Files As FileInfo() = DirInfo.GetFiles("*.TXT")  
  Dim I As Integer  
  Console.WriteLine(Path & ControlChars.CrLf)  
  For I = Files.GetLowerBound(0) To Files.GetUpperBound(0)  
   Console.Write((Files(I).Name.PadRight(15)) & _  
    (Files(I).Length).ToString.PadRight(15))  
   Console.Write(ControlChars.Tab)  
   Console.WriteLine(ShowAttribs(Files(I)))  
  Next  
   
 End Sub  
   
 Function GetPersonalFolder() As String  
   
  Dim E As Environment  
  Return E.GetFolderPath(Environment.SpecialFolder.Personal)  
   
 End Function  
   
 Function ShowAttribs(ByVal F As FileInfo) As String  
   
  Dim S As String  
  With F  
   If .Attributes And FileAttributes.Archive Then  
     S = "A"  
   Else  
     S = "-"  
   End If  
   If .Attributes And FileAttributes.Hidden Then  
     S += "H"  
   Else  
     S += "-"  
   End If  
   If .Attributes And FileAttributes.Normal Then  
     S += "N"  
   Else  
     S += "-"  
   End If  
   If .Attributes And FileAttributes.ReadOnly Then  
     S += "R"  
   Else  
     S += "-"  
   End If  
  End With  
  Return S  
   
 End Function  
   
End Module  

Приведем еще один пример — ниже показано, как использовать метод CreateText для создания объекта StreamWriter и записи в новый текстовый файл:

'----------------------------------------  
' Использование класса FileInfo  
'----------------------------------------  
   
Imports System  
Imports System.IO  
   
Module VBDemo  
   
 Sub Main()  
  Dim FileName As String = "c:\temp\mytext01.txt"  
  Dim Writer As StreamWriter  
  Dim MyFile As New FileInfo(FileName)  
   
  Writer = MyFile.CreateText()  
   
  Writer.WriteLine("Created by " & MyFile.GetType.ToString)  
  Writer.WriteLine("Written by " & Writer.ToString)  
   
  Writer.Close()  
   
End Sub  

В результате мы получим следующий текстовый файл.

Примеры использования других методов класса FileInfo приведены в разделе, посвященном классу File.

В начало В начало

Класс DirectoryInfo

Этот класс позволяет создавать и перемещать каталоги, а также получать содержимое каталогов и подкаталогов. Класс DirectoryInfo содержит следующие свойства:

  • Parent — возвращает родительский каталог для данного подкаталога. Это свойство имеет тип DirectoryInfo;
  • Root — возвращает корневой каталог для данного маршрута как тип DirectoryInfo.

Следующий пример показывает, как использовать свойства Parent и Root для восстановления корневого каталога для данного каталога:

'----------------------------------------  
' Использование класса DirectoryInfo  
'----------------------------------------  
   
Imports System  
Imports System.IO  
   
Module VBDemo  
   
 Sub Main()  
   
  Dim Path As String = GetPersonalFolder() & "\MyText"  
  Dim DirInfo As New DirectoryInfo(Path)  
  Dim Parent As String  
   
  Console.WriteLine("Initial Directory : " & DirInfo.FullName)  
  Parent = DirInfo.Parent.FullName  
  While Parent <> DirInfo.Root.FullName  
    Console.WriteLine("Parent Directory  : " & _  
     DirInfo.Parent.FullName)  
    Parent = DirInfo.Parent.FullName  
    DirInfo = New DirectoryInfo(Parent)  
   End While  
   
 End Sub  
   
 Function GetPersonalFolder() As String  
   
  Dim E As Environment  
  Return E.GetFolderPath(Environment.SpecialFolder.Personal)  
   
 End Function  
   
End Module  

Ниже приведены методы, доступные в классе DirectoryInfo:

  • Create() — этот метод используется для создания каталога;
  • CreateSubDirectory(String) — метод используется для создания подкаталога. Он возвращает объект DirectoryInfo для вновь созданного каталога. Следующий пример демонстрирует, как использовать методы Create и CreateSubDirectory:
'----------------------------------------  
' Использование класса DirectoryInfo  
'----------------------------------------  
   
Imports System  
Imports System.IO  
   
Module VBDemo  
   
 Sub Main()  
   
  Dim Path As String = "c:\temp\demos"  
  Dim DirInfo As New DirectoryInfo(Path)  
  DirInfo.Create()  
  DirInfo.CreateSubdirectory("ch04")  
   
 End Sub  
   
End Module  
  • GetDirectories() — этот метод возвращает подкаталоги текущего каталога как массив элементов DirectoryInfo. Ниже показано использование метода GetDirectories для получения списка каталогов на диске C:\:
'----------------------------------------  
' Использование класса DirectoryInfo  
'----------------------------------------  
   
Imports System  
Imports System.IO  
   
Module VBDemo  
   
 Sub Main()  
   
  Dim Path As String = "c:\"  
  Dim DirInfo As New DirectoryInfo(Path)  
  Dim Dirs() As DirectoryInfo  
  Dim I As Integer  
   
  Console.WriteLine("Initial Directory : " & DirInfo.FullName)  
  Dirs = DirInfo.GetDirectories  
  For I = 0 To Dirs.GetUpperBound(0)  
   Console.WriteLine(Dirs(I).FullName)  
  Next  
   
 End Sub  
   
End Module  
  • GetFiles() — данный метод возвращает массив элементов FileInfo для файлов в текущем каталоге. Мы уже видели пример использования этого метода в предыдущем разделе, когда обсуждали класс FileInfo;
  • GetFileSystemInfos() — метод возвращает массив элементов FileSystemInfo для файлов в текущем каталоге;
  • MoveTo(String) — метод перемещает каталог и его содержимое в новое место.
В начало В начало

Перечисление Environment.SpecialFolder

Данное перечисление используется для получения маршрутов к специальным системным каталогам типа Program Files, Programs, System, Startup и т.п. Ниже показаны члены перечисления SpecialFolder:

  • ApplicationData — возвращает маршрут к каталогу, используемому как общее хранилище данных для приложений;
  • CommonApplicationData — возвращает маршрут к каталогу, используемому как общее хранилище данных для приложений, доступное всем пользователям;
  • CommonProgramFiles — возвращает маршрут к каталогу, используемому как хранилище общих компонентов приложений;
  • Cookies — возвращает маршрут к каталогу, используемому для хранения cookies;
  • DesktopDirectory — возвращает маршрут к каталогу, используемому для хранения файлов и объектов на desktop;
  • Favorities — возвращает маршрут к каталогу, используемому для хранения пользовательских закладок;
  • History — возвращает маршрут к каталогу, используемому для хранения ссылок на ранее посещавшиеся узлы Internet;
  • InternetCache — возвращает маршрут к каталогу, используемому для хранения временных Internet-файлов;
  • LocalApplicationData — возвращает маршрут к каталогу, используемому для хранения данных приложений;
  • Personal — возвращает маршрут к каталогу, используемому для хранения пользовательских документов;
  • ProgramFiles — возвращает маршрут к каталогу, используемому для хранения программ;
  • Programs — возвращает маршрут к каталогу, используемому для хранения программных групп;
  • Recent — возвращает маршрут к каталогу, используемому для хранения документов, с которыми пользователь работал в последнее время;
  • SendTo — возвращает маршрут к каталогу, используемому для хранения элементов меню SendTo;
  • StartMenu — возвращает маршрут к каталогу, используемому для хранения элементов меню Start;
  • Startup — возвращает маршрут к каталогу, используемому для хранения элементов группы Startup;
  • System — возвращает маршрут к каталогу System;
  • Templates — возвращает маршрут к каталогу, используемому для хранения шаблонов документов.

Ниже показаны типичные имена для специальных системных каталогов в системе Windows 2000:

'------------------------------------------------------  
' Использование перечисления Environment.SpecialFolder   
'------------------------------------------------------  
   
Imports System  
Imports System.IO  
   
Module VBDemo  
   
 Sub Main()  
  Dim E As Environment  
  Dim Names As String()  
  Dim Values() As Integer  
  Dim I As Integer  
   
  Console.WriteLine("SpecialFolder Enumeration")  
  Names  = SpecialFolder.System.GetNames(SpecialFolder.System.GetType)  
  Values = SpecialFolder.GetValues(SpecialFolder.System.GetType)  
   
  For I = 0 To Names.GetUpperBound(0)  
    Console.WriteLine(ControlChars.Tab & Names(I) & "=" & _  
     E.GetFolderPath(Values(I)))  
  Next  
   
End Sub  

 

В начало В начало

Класс File

Этот класс обеспечивает набор статических методов, которые могут быть использованы для создания, копирования, удаления, перемещения и открытия файлов. Некоторые из методов класса File создают объекты StreamWriter и FileStream.

Метод Create(String), или Create (String, Integer), используется для создания файла в указанном каталоге с указанным размером буфера. Этот метод возвращает объект FileStream. Метод CreateText(String) создает объект StreamWriter, который записывает в новый текстовый файл с указанным полным именем. Мы используем метод AppendText(String) для создания объекта StreamWriter, используемого для добавления текста к существующему файлу или для создания нового файла. Для проверки того, существует файл или нет, используется метод Exists(String).

Метод Open(String, FileMode), или Open(String, FileMode, FileAccess), или Open(String, FileMode, FileAccess, FileShare), открывает объект FileStream для указанного файла, метод OpenRead(String) создает объект FileStream для чтения из существующего файла, а метод OpenWrite(String) создает объект FileStream с доступом к файлу через операции чтения и записи. Метод OpenText(String) создает объект StreamReader, используемый для чтения из файла.

На следующей диаграмме показано, как методы класса File соотносятся с потоковыми классами.

Метод Copy(String, String), или Copy(String, String, Boolean) используется для копирования существующего файла в новый файл либо с перезаписью содержимого файла, либо без таковой. Для удаления файла мы используем метод Delete(String), а для перемещения указанного файла в новое место и для опционального изменения имени файла — метод Move(String, String).

Класс File имеет четыре пары методов Get/Set, используемых для управления атрибутами, временем создания, временем доступа и временем последней записи в файл. Эти методы перечислены в следующей таблице.

Ниже демонстрируется использование метода Open для открытия потока FileStream для указанного файла:

'----------------------------  
' Использование класса File   
'----------------------------  
   
Imports System  
Imports System.IO  
   
Module VBDemo  
   
 Sub Main()  
  Dim MyFile As String = "c:\temp\mytext\mytext01.txt"  
  Dim FS As FileStream  
  Dim Reader As StreamReader  
   
  FS = File.Open(MyFile, FileMode.Open)  
  Reader = New StreamReader(FS)  
   
  While Reader.Peek() > -1  
    Console.WriteLine(Reader.ReadLine())  
  End While  
  Reader.Close()  
  FS.Close()  
   
 End Sub  
   
End Module  

Обратите внимание на то, что при вызове метода Open объекта File мы указали способ доступа к файлу. Возможные модификаторы доступа к файлу доступны через перечисление FileMode и показаны ниже:

  • Append — указывает на то, что файл открывается в режиме добавления — в этом режиме чтение из файла невозможно;
  • Create — указывает на то, что новый файл должен быть создан операционной системой. Если указанный файл существует, он будет перезаписан;
  • CreateNew — указывает на то, что новый файл должен быть создан операционной системой;
  • Open — указывает на то, что указанный файл должен быть открыт;
  • OpenOrCreate — указывает на то, что файл должен быть открыт. Если файл не существует, операционная система создает новый файл;
  • Truncate — указывает на то, что существующий файл должен быть открыт и его размер должен быть уменьшен до 0 байт.

Следующий пример показывает использование метода OpenFile класса StreamReader:

'----------------------------  
' Использование класса File   
'----------------------------  
   
Imports System  
Imports System.IO  
   
Module VBDemo  
   
 Sub Main()  
   
  Dim MyFile As String = "c:\temp\mytext\mytext01.txt"  
  Dim Reader As StreamReader  
   
  Reader = File.OpenText(MyFile)  
  While Reader.Peek() > -1  
   Console.WriteLine(Reader.ReadLine())  
  End While  
  Reader.Close()  
   
 End Sub  
   
End Module   
Ниже демонстрируется использование методов   GetXXX:
'----------------------------  
' Использование класса File   
'----------------------------  
   
Imports System  
Imports System.IO  
   
Module VBDemo  
   
 Sub Main()  
  Dim MyFile As String = "c:\temp\mytext\mytext01.txt"  
          
  Console.WriteLine()  
  Console.WriteLine(MyFile)  
  Console.WriteLine("Attributes       : " & _  
   ShowAttribs(File.GetAttributes(MyFile)))  
  Console.WriteLine("Creation time    : " & _  
   File.GetCreationTime(MyFile))  
  Console.WriteLine("Last access time : " & _  
   File.GetLastAccessTime(MyFile))  
  Console.WriteLine("Last write time  : " & _  
   File.GetLastWriteTime(MyFile))  
   
 End Sub  
   
 Function ShowAttribs(ByVal Attributes As FileAttributes) As String  
   
  Dim S As String  
   
        If Attributes And FileAttributes.Archive Then  
            S = "A"  
        Else  
            S = "-"  
        End If  
        If Attributes And FileAttributes.Hidden Then  
            S += "H"  
        Else  
            S += "-"  
        End If  
        If Attributes And FileAttributes.Normal Then  
            S += "N"  
        Else  
            S += "-"  
        End If  
        If Attributes And FileAttributes.ReadOnly Then  
            S += "R"  
        Else  
            S += "-"  
        End If  
   
  Return S  
   
  End Function  

И еще один пример — в нем показано, как использовать метод OpenWrite для открытия потока FileStream для указанного файла и записи в него:

'----------------------------  
' Использование класса File   
'----------------------------  
   
Imports System  
Imports System.IO  
   
Module VBDemo  
   
 Sub Main()  
  Dim MyFile As String = "c:\temp\mytext\mytext01.txt"  
  Dim FS As FileStream  
  Dim Writer As StreamWriter  
   
  FS = File.OpenWrite(MyFile)  
  Writer = New StreamWriter(FS)  
  FS.Seek(0, SeekOrigin.End)  
  Writer.WriteLine("One more line")  
  Writer.Flush()  
  Writer.Close()  
  FS.Close()  
   
 End Sub  
   
End Module  
В начало В начало

Класс Path

Класс Path предоставляет набор статических методов, используемых для обработки имен файлов и каталогов. Методы, реализованные в этом классе, следующие:

  • ChangeExtension(String, String) — этот метод используется для того, чтобы изменить расширение имени файла, и возвращает результат в виде переменной типа String;
  • Combine(String, String) — метод объединяет два имени файлов и возвращает результат в виде переменной типа String;
  • GetDirectoryName(String) — возвращает имя каталога для указанного файла;
  • GetExtension(String) — возвращает расширение имени файла;
  • GetFileName(String) — возвращает имя файла;
  • GetFileNameWithoutExtension(String) — возвращает имя файла без расширения;
  • GetFullPath(String) — возвращает полное имя файла;
  • GetPathRoot(String) — возвращает корневой каталог для заданного файла;
  • GetTempFileName() — возвращает уникальное имя временного файла и создает файл нулевой длины с данным именем;
  • GetTempPath() — возвращает маршрут к временному системному каталогу;
  • HasExtension(String) — проверяет, содержит ли имя файла расширение;
  • IsPathRooted(String) — проверяет, содержит ли полное имя файла корневой каталог.

В следующем примере демонстрируется использование ряда методов класса Path:

'----------------------------  
' Использование класса Path  
'----------------------------  
   
Imports System  
Imports System.IO  
   
Module VBDemo  
   
 Sub Main()  
  Dim FullPath As String    = "c:\book\ch04\ch04.doc"  
  Dim FullPathExt As String = "c:\book\ch04.old\ch04.doc"  
  Dim Partial1 As String    = "c:\book"  
  Dim Partial2 As String    = "ch04"  
   
  Console.WriteLine("ChangeExtension             : " & _  
   Path.ChangeExtension(FullPath, ".bak"))  
  Console.WriteLine("Combine                     : " & _  
   Path.Combine(Partial1, Partial2))  
  Console.WriteLine("GetDirectoryName            : " & _  
   Path.GetDirectoryName(FullPath))  
  Console.WriteLine("GetExtension                : " & _  
   Path.GetExtension(FullPathExt))  
  Console.WriteLine("GetFileName                 : " & _  
   Path.GetFileName(FullPath))  
  Console.WriteLine("GetFileNameWithoutExtension : " & _  
   Path.GetFileNameWithoutExtension(FullPath))  
  Console.WriteLine("GetFullPath                 : " & _  
   Path.GetFullPath(FullPath))  
  Console.WriteLine("GetPathRoot                 : " & _  
   Path.GetPathRoot(FullPath))  
  Console.WriteLine("GetTempFileName             : " & _  
   Path.GetTempFileName)  
  Console.WriteLine("GetTempPath                 : " & _  
   Path.GetTempPath)  
  Console.WriteLine("HasExtension                : " & _  
   Path.HasExtension(FullPathExt))  
  Console.WriteLine("IsPathRooted                : " & _  
   Path.IsPathRooted(Partial2))  
   
 End Sub  
   
End Module  

Пять свойств класса Path содержат специфичные для конкретной платформы символы, которые перечислены ниже:

  • AltDirectorySeparatorChar,
  • DirectorySeparatorChar,
  • InvalidPathChars,
  • PathSeparator,
  • VolumeSeparatorChar.

Следующий пример показывает содержимое этих свойств для платформы Microsoft Windows.

'----------------------------  
' Использование класса Path  
'----------------------------  
   
Imports System  
Imports System.IO  
   
Module VBDemo  
   
 Sub Main()  
   
  Console.WriteLine("AltDirectorySeparatorChar : " _  
   & Path.AltDirectorySeparatorChar)  
  Console.WriteLine("DirectorySeparatorChar    : " _  
   & Path.DirectorySeparatorChar)  
  Console.WriteLine("InvalidPathChars          : " _  
   & Path.InvalidPathChars)  
  Console.WriteLine("PathSeparator             : " _  
   & Path.PathSeparator)  
  Console.WriteLine("VolumeSeparatorChar       : " _  
   & Path.VolumeSeparatorChar)  
   
 End Sub  
   
End Module  

На этом мы завершаем знакомство с Microsoft .NET Framework — дальнейшее обсуждение этой темы выходит за рамки тематики нашего издания. Более подробную информацию о Microsoft .NET можно получить по адресу: http://hosting.gotdotnet.ru/developnet/

КомпьютерПресс 7'2002

Наш канал на Youtube

1999 1 2 3 4 5 6 7 8 9 10 11 12
2000 1 2 3 4 5 6 7 8 9 10 11 12
2001 1 2 3 4 5 6 7 8 9 10 11 12
2002 1 2 3 4 5 6 7 8 9 10 11 12
2003 1 2 3 4 5 6 7 8 9 10 11 12
2004 1 2 3 4 5 6 7 8 9 10 11 12
2005 1 2 3 4 5 6 7 8 9 10 11 12
2006 1 2 3 4 5 6 7 8 9 10 11 12
2007 1 2 3 4 5 6 7 8 9 10 11 12
2008 1 2 3 4 5 6 7 8 9 10 11 12
2009 1 2 3 4 5 6 7 8 9 10 11 12
2010 1 2 3 4 5 6 7 8 9 10 11 12
2011 1 2 3 4 5 6 7 8 9 10 11 12
2012 1 2 3 4 5 6 7 8 9 10 11 12
2013 1 2 3 4 5 6 7 8 9 10 11 12
Популярные статьи
КомпьютерПресс использует