Last active
December 24, 2025 22:41
-
-
Save sunmeat/d53abc35c4667538c3db558180842d32 to your computer and use it in GitHub Desktop.
fixed example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Runtime.InteropServices; | |
| using System.Text; | |
| class Cat | |
| { | |
| public int paws = 4; | |
| // якщо зробити властивість, то не вдасться застосувати оператор & | |
| } | |
| class CopyMaker | |
| { | |
| // ключове слово unsafe дозволяє використовувати вказівники всередині методу | |
| public static unsafe void Copy(byte[] src, int srcIndex, byte[] dst, int dstIndex, int count) | |
| { | |
| if (src == null || srcIndex < 0 || | |
| dst == null || dstIndex < 0 || count < 0) | |
| { | |
| throw new ArgumentException(); // перевірка на коректність параметрів | |
| } | |
| int srcLen = src.Length; | |
| int dstLen = dst.Length; | |
| if (srcLen - srcIndex < count || | |
| dstLen - dstIndex < count) | |
| { | |
| throw new ArgumentException(); // перевірка на розмір даних | |
| } | |
| // оператор fixed "прикріплює" вказівники на масиви src і dst | |
| // щоб збирач сміття не переміщав їх у пам’яті | |
| fixed (byte* pSrc = src, pDst = dst) | |
| { | |
| byte* ps = pSrc; // вказівник на вихідний масив | |
| byte* pd = pDst; // вказівник на цільовий масив | |
| // цикл копіювання по 4 байти за раз | |
| for (int n = 0; n < count / 4; n++) | |
| { | |
| *((int*)pd) = *((int*)ps); // копіюємо по 4 байти (ціле число) | |
| pd += 4; // зсуваємо вказівник на 4 байти | |
| ps += 4; // зсуваємо вказівник на 4 байти | |
| } | |
| // завершення копіювання залишкових байтів, якщо їх менше 4 | |
| for (int n = 0; n < count % 4; n++) | |
| { | |
| *pd = *ps; // копіюємо по 1 байту | |
| pd++; | |
| ps++; | |
| } | |
| } | |
| } | |
| } | |
| class FileReader | |
| { | |
| const uint GENERIC_READ = 0x80000000; // прапорець для читання | |
| const uint OPEN_EXISTING = 3; // прапор для відкриття існуючого файлу | |
| IntPtr handle; // дескриптор файлу | |
| // метод для створення файлу (або відкриття існуючого) | |
| [DllImport("kernel32", SetLastError = true)] | |
| static extern unsafe IntPtr CreateFile( | |
| string FileName, // ім’я файлу | |
| uint DesiredAccess, // режим доступу | |
| uint ShareMode, // режим спільного доступу | |
| uint SecurityAttributes, // атрибути безпеки | |
| uint CreationDisposition, // як створювати файл | |
| uint FlagsAndAttributes, // атрибути файлу | |
| int hTemplateFile // дескриптор шаблонного файлу | |
| ); | |
| // метод для читання файлу | |
| [DllImport("kernel32", SetLastError = true)] | |
| static extern unsafe bool ReadFile( | |
| IntPtr hFile, // дескриптор файлу | |
| void* pBuffer, // буфер для даних | |
| int NumberOfBytesToRead, // кількість байтів для читання | |
| int* pNumberOfBytesRead, // кількість фактично прочитаних байтів | |
| int Overlapped // буфер для асинхронного читання | |
| ); | |
| // метод для закриття файлу | |
| [DllImport("kernel32", SetLastError = true)] | |
| static extern unsafe bool CloseHandle( | |
| IntPtr hObject // дескриптор об’єкта | |
| ); | |
| // метод для відкриття файлу | |
| public bool Open(string FileName) | |
| { | |
| // відкриваємо існуючий файл для читання | |
| handle = CreateFile( | |
| FileName, | |
| GENERIC_READ, | |
| 0, | |
| 0, | |
| OPEN_EXISTING, | |
| 0, | |
| 0); | |
| if (handle != IntPtr.Zero) | |
| return true; | |
| else | |
| return false; | |
| } | |
| // метод для читання даних із файлу | |
| public unsafe int Read(byte[] buffer, int index, int count) | |
| { | |
| int n = 0; | |
| // !!! FIXED !!! | |
| fixed (byte* p = buffer) | |
| { | |
| if (!ReadFile(handle, p + index, count, &n, 0)) | |
| return 0; // якщо читання не вдалося, повертаємо 0 | |
| } | |
| return n; // повертаємо кількість прочитаних байтів | |
| } | |
| // метод для закриття файлу | |
| public bool Close() | |
| { | |
| // закриваємо дескриптор файлу | |
| return CloseHandle(handle); | |
| } | |
| } | |
| class Program | |
| { | |
| // метод для зміни значення за вказівником | |
| unsafe static void SetIntegerValue(int* x) | |
| { | |
| Console.WriteLine("Розіменування вказівника для зміни cat.paws..."); | |
| *x = 5; // змінюємо значення за вказівником | |
| } | |
| unsafe static void Main() | |
| { | |
| Console.OutputEncoding = Encoding.UTF8; | |
| var cat = new Cat(); | |
| Console.WriteLine("cat.paws ініціалізовано значенням {0}", cat.paws); // виводимо початкове значення 4 | |
| // оператор fixed фіксує об’єкт cat у межах | |
| // включаючого його оператора, щоб збирач сміття не перемістив його | |
| fixed (int* ptr = &cat.paws) | |
| { | |
| Console.WriteLine("Виклик SetIntegerValue із передачею вказівника на cat.paws"); | |
| SetIntegerValue(ptr); // передаємо вказівник на paws методу | |
| } | |
| // переконуємося, що компонент через вказівник змінився | |
| Console.WriteLine("Після повернення з SetIntegerValue, cat.paws = {0}", cat.paws); | |
| ////////////////////////////////////////////////////////////////////////////////////// | |
| var a = new byte[100]; | |
| var b = new byte[100]; | |
| // заповнюємо масив a значеннями від 0 до 99 | |
| for (int i = 0; i < 100; ++i) | |
| a[i] = (byte)i; | |
| // викликаємо метод копіювання | |
| CopyMaker.Copy(a, 0, b, 0, 100); | |
| // виводимо перші 10 елементів масиву b | |
| Console.WriteLine("Перші 10 елементів:"); | |
| for (int i = 0; i < 10; ++i) | |
| Console.Write(b[i] + " "); | |
| Console.WriteLine("\n"); | |
| ////////////////////////////////////////////////////////////////////////////////////// | |
| string path = "1.txt"; | |
| var buffer = new byte[128]; | |
| var fr = new FileReader(); | |
| if (File.Exists(path)) | |
| { | |
| fr.Open(path); | |
| // припускаємо, що файл у форматі ASCII | |
| var Encoding = new ASCIIEncoding(); | |
| int bytesRead; | |
| do | |
| { | |
| bytesRead = fr.Read(buffer, 0, buffer.Length); // читаємо дані | |
| string content = Encoding.GetString(buffer, 0, bytesRead); // перетворюємо в рядок | |
| Console.Write("{0}", content); // виводимо дані | |
| } | |
| while (bytesRead > 0); | |
| fr.Close(); // закриваємо файл | |
| } | |
| else | |
| { | |
| Console.WriteLine("Не вдалося відкрити запитаний файл"); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment