Добавил:
Кафедра ВТ Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

1 лаба / main2

.cpp
Скачиваний:
5
Добавлен:
04.02.2022
Размер:
5.49 Кб
Скачать
#include <iostream>
#include <windows.h>

using std::cout;
using std::endl;
using std::cin;

int callback = 0;
// хэндлы на файлы, учавствующие в операции копирования
HANDLE firstHandle, secondHandle;

// Функция завершения, которая будет вызываться всякий раз при завершении операции ввода-вывода (для ReadFileEx и WriteFileEx)
VOID CALLBACK FileIOCompletionRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) {
    // количество вызовов
    callback++;
}
void ReadFileOverlapped(long long, DWORD, int, OVERLAPPED*, char**);
void WriteFileOverlapped(long long, DWORD, int, OVERLAPPED*, char**);
// Функция асинхронного копирования
void copyFile(DWORD, int);

void menu(int&);
int safe_cin();
bool isFile(LPCSTR strFileName);

int main(){
    int part = 0, operations = 0, sizeToCopy;
    char fileName[256], filePath[256];
    DWORD startTime;

    // Ввод множителя для размера блока
    cout << "Enter the read-write block size(in bytes):\n";
    do {
        cout << "> 4096*";
        part = safe_cin();
        if (part <= 0) cout << "Try again!\n";
    } while (part <= 0);
    //Ввод количества операций
    cout << "Enter number of operations(multiple of two): ";
    do {
        operations = safe_cin();
        if (operations <= 0) cout << "Try again!\n";
    } while (operations <= 0);

    cout << "Enter the name of copied file(e.g. test.txt or dir\\test.txt(make sure the directory exists)): ";
    do{
        //проверяет как по абсолютному, так и по относительному пути
        cin >> fileName;
        if (!isFile(fileName))
            cout << "This file doesn't exist\nTry again\n";
    } while (!isFile(fileName));
    cout << "Enter the path to copy to(e.g. test1.txt or dir1\\test1.txt): ";
    cin >> filePath;

    if (strlen(fileName) < MAX_PATH && strlen(filePath) < MAX_PATH){
        firstHandle = CreateFile(fileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL);
        secondHandle = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL);

        if (firstHandle != INVALID_HANDLE_VALUE){
            sizeToCopy = 4096 * part;
            startTime = GetTickCount();
            copyFile(sizeToCopy, operations);
            cout << "Copying took " << GetTickCount() - startTime << " milliseconds\n";
        }
        else cout << "Error 0x" << GetLastError() << endl;
    }

    if (!CloseHandle(firstHandle)) cout << "Unable to close first file\n";
    if (!CloseHandle(secondHandle))cout << "Unable to close second file\n";
}

int safe_cin(){
    int choice = -1;
    char str[50];
    cin >> str;
    while (sscanf(str, "%d", &choice) != 1){
        printf("Incorrect input! Try again use only numbers: ");
        cin >> str;
    }
    return choice;
}
bool isFile(LPCSTR strFileName){
    DWORD ret = GetFileAttributesA(strFileName);
    return ((ret != INVALID_FILE_ATTRIBUTES) && !(ret & FILE_ATTRIBUTE_DIRECTORY));
}

void copyFile(DWORD blockSize, int count){
    DWORD high = 0;
    long long fileSize = GetFileSize(firstHandle, &high),
              curSize = fileSize;
    char** buffer = new char*[count];
    OVERLAPPED *over_1 = new OVERLAPPED[count],
               *over_2 = new OVERLAPPED[count];
    
    for (int i=0; i < count; i++){
        buffer[i] = new char[blockSize];

        over_1[i].Offset = over_2[i].Offset = i*blockSize;
        over_1[i].OffsetHigh = over_2[i].OffsetHigh = i*high;
        over_1[i].hEvent = over_2[i].hEvent = NULL;
    }
    do{
        ReadFileOverlapped(fileSize, blockSize, count, over_1, buffer);
        WriteFileOverlapped(fileSize, blockSize, count, over_2, buffer);
        curSize -= (long long)(blockSize*count);
    }while(curSize > 0);

    SetFilePointer(secondHandle, fileSize, NULL, FILE_BEGIN);
    SetEndOfFile(secondHandle);

    for (int i = 0; i < count; i++)
        delete[] buffer[i];
    delete[] buffer;
    delete[] over_1;
    delete[] over_2;
}

void ReadFileOverlapped(long long fileSize, DWORD blockSize, int operationsCount, OVERLAPPED* overlappeds, char** buffer){
    int operations_counter = 0;
    for (int i=0; i<operationsCount; i++)
        if (fileSize>0){
            operations_counter++;
            ReadFileEx(firstHandle, buffer[i], blockSize, &overlappeds[i], FileIOCompletionRoutine);
            fileSize -= blockSize;
        }
    while (callback < operations_counter)
        SleepEx(-1, true);
    for (int i=0; i<operationsCount; i++)
        overlappeds[i].Offset += blockSize*operationsCount;
    callback = 0;
}

void WriteFileOverlapped(long long fileSize, DWORD blockSize, int operationsCount, OVERLAPPED* overlappeds, char** buffer){
    int operations_counter = 0;
    for (int i=0; i<operationsCount; i++)
        if (fileSize>0){
            operations_counter++;
            WriteFileEx(secondHandle, buffer[i], blockSize, &overlappeds[i], FileIOCompletionRoutine);
            fileSize -= blockSize;
        }
    while (callback < operations_counter)
        SleepEx(-1, true);
    for (int i=0; i<operationsCount; i++)
        overlappeds[i].Offset += blockSize*operationsCount;
    callback = 0;
}
Соседние файлы в папке 1 лаба