#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

void main() {

	try {
		fs::path folde_path(R"(c:\temp)");

		for (const fs::directory_entry entry : fs::recursive_directory_iterator(folde_path)) {
			if (fs::is_regular_file(entry.path())) {
				std::cout << "file  :" << entry.path() << std::endl;
			}
			else if (fs::is_directory(entry.path())) {
				std::cout << "folder:" << entry.path() << std::endl;
			}
		}
	}
	catch (const fs::filesystem_error& e) {
		std::cout << e.what() << std::endl;
	}
	catch (const std::exception& e) {
		std::cout << e.what() << std::endl;
	}

	return;
}
file  :"c:\\temp\\file_1.txt"
file  :"c:\\temp\\file_2.txt"
folder:"c:\\temp\\folder_1"
file  :"c:\\temp\\folder_1\\file_1.txt"
folder:"c:\\temp\\folder_1\\folder_1"
folder:"c:\\temp\\folder_1\\folder_1\\folder_1"
folder:"c:\\temp\\folder_1\\folder_2"
folder:"c:\\temp\\folder_2"
folder:"c:\\temp\\folder_3"

削除する場合、fs::romoveで特定のファイル、 fs::romove_allでフォルダ配下すべてを削除
ただ、ファイルが開けれていて削除できないような場合こんな感じになります

フォルダ構成は、以下のとおりでbbb.xlsxは開いています。
c/\temp\file\aaa.txt
c/\temp\file\bbb.xlsx
c/\temp\file\ccc.txt

bbb.xlsxを消すときに、エラーとなるのでそこで例外が発生します。
エラーメッセージは、削除のメソッドに指定したパスが表示されるだけなので、どのファイルでエラーが発生したのかわかりにくいです

remove_all: プロセスはファイルにアクセスできません。別のプロセスが使用中です。: "c:\temp"

そこで、一つずつファイル、フォルダを消していくとなると、階層の深い方から順に消していくので
ソートで入れ替え、消せるファイルはすべてけすことにすると


remove: プロセスはファイルにアクセスできません。別のプロセスが使用中です。: "c:\temp\file\~$bbb.xlsx"
remove: プロセスはファイルにアクセスできません。別のプロセスが使用中です。: "c:\temp\file\bbb.xlsx"
remove: ディレクトリが空ではありません。: "c:\temp\file"
投稿日時: 2024-10-06 08:25:06
更新日時: 2024-10-10 16:40:10

ファイルもフォルダも同じくexistsでチェック

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

void main() {
	// ファイルパスの存在チェック
	fs::path file_path(R"(c:\temp\file_1.txt)");

	bool result_file_path = fs::exists(file_path);	
	if (result_file_path) {
		std::cout << "存在する" << std::endl;
	}
	else {
		std::cout << "存在しない" << std::endl;
	}


	// フォルダパスの存在チェック
	fs::path folder_path(R"(c:\temp\folder_1)");

	bool result_folder_path = fs::exists(folder_path);
	if (result_file_path) {
		std::cout << "存在する" << std::endl;
	}
	else {
		std::cout << "存在しない" << std::endl;
	}

	return;
}

例外を含めて記載するとこんな感じ。

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

void main() {

	try {
		// ファイルパスの存在チェック
		fs::path file_path(R"(c:\temp\file_1.txt)");

		bool result_file_path = fs::exists(file_path);
		if (result_file_path) {
			std::cout << "存在する" << std::endl;
		}
		else {
			std::cout << "存在しない" << std::endl;
		}

		// 他いろんな処理...

	}
	catch (const fs::filesystem_error& e) {
		std::cout << e.what() << std::endl;
	}
	catch (const std::exception& e) {
		std::cout << e.what() << std::endl;
	}

	return;
}
投稿日時: 2024-10-06 07:47:06

パスの\をエスケープするのが手間なので C#でいうとこの @"c:\temp\file.txt" に該当する機能ってなんだろうと調べてみたら
生文字列リテラルという名称のものがあるのね。

R"(c:\temp\file.txt)"
かっこで、かこうまでがセット。

投稿日時: 2024-10-06 07:31:06
C++

SHA256を調べてみたらひとまず、OPENSSLインストールして・・・
のように、何かインストールしてといった話から始まるわけですが、
諸事情によりインストールを避けたいというのとWindows限定でしか使わないということから以下のコードにたどり着いた。

#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>

int SHA256(BYTE* data, DWORD dataSize, BYTE* hash, DWORD* hashSize) {

	int result = 0;
	HCRYPTPROV hProv = 0;
	HCRYPTHASH hHash = 0;

	if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){ goto LAST; }

	if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) { goto LAST; }

	if (!CryptHashData(hHash, data, dataSize, 0)) { goto LAST; }

	if (!CryptGetHashParam(hHash, HP_HASHVAL, hash, hashSize, 0)) { goto LAST; }

	result = 1;

LAST:
	if (hHash) { CryptDestroyHash(hHash); }
	if (hProv) { CryptReleaseContext(hProv, 0); }

	return result;
}

int main() {

	const char* str = "Hello SHA256";

	BYTE hash[32] = { 0 };
	DWORD hashSize = sizeof(hash);
	
	if (SHA256((BYTE*)str, strlen(str), hash, &hashSize)) {
		for (DWORD i = 0; i < hashSize; i++) {
			printf("%02x", hash[i]);
		}
		
		printf("\n");
	}
		return 0;
}

ただし、CryptHashData 関数 は、非推奨とのこと。

大事な この API は非推奨です。 新規および既存のソフトウェアでは 、暗号化次世代 API の 使用を開始する必要があります。Microsoft は、今後のリリースでこの API を削除する可能性があります。 CryptHashData 関数 (wincrypt.h)

70725d0f78cb0967c0e5171f733619712d239e28f2d279e4b3c3ed97f7456fa3



そんなわけで、書き換えるとこんな感じらしい。

#include <stdio.h>
#include <windows.h>
#include <bcrypt.h>
#include <ntstatus.h>
#include <vector>
#include <string.h>

#pragma comment(lib, "bcrypt.lib")

std::vector<BYTE> SHA256(const BYTE* data, DWORD dataSize)
{
    BCRYPT_ALG_HANDLE hAlg = NULL;
    BCRYPT_HASH_HANDLE hHash = NULL;
    std::vector<BYTE> hash;
    DWORD hashSize = 0, cbData = 0;
    NTSTATUS status = STATUS_UNSUCCESSFUL;

    do {
        // アルゴリズムプロバイダーを開く
        status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA256_ALGORITHM, NULL, 0);
        if (!BCRYPT_SUCCESS(status)) break;

        // ハッシュオブジェクトのサイズを取得
        status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbData, sizeof(DWORD), &hashSize, 0);
        if (!BCRYPT_SUCCESS(status)) break;

        // ハッシュオブジェクトを作成
        std::vector<BYTE> hashObject(cbData);
        status = BCryptCreateHash(hAlg, &hHash, hashObject.data(), (ULONG)hashObject.size(), NULL, 0, 0);
        if (!BCRYPT_SUCCESS(status)) break;

        // データをハッシュ化
        status = BCryptHashData(hHash, (PBYTE)data, dataSize, 0);
        if (!BCRYPT_SUCCESS(status)) break;

        // ハッシュサイズを取得
        status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PBYTE)&hashSize, sizeof(DWORD), &cbData, 0);
        if (!BCRYPT_SUCCESS(status)) break;

        // 最終的なハッシュ値を取得
        hash.resize(hashSize);
        status = BCryptFinishHash(hHash, hash.data(), hashSize, 0);
        if (!BCRYPT_SUCCESS(status)) hash.clear();

    } while (false);

    if (hHash) BCryptDestroyHash(hHash);
    if (hAlg) BCryptCloseAlgorithmProvider(hAlg, 0);

    return hash;
}

int main() {
    const char* str = "Hello SHA256";
    DWORD dataSize = strlen(str);  // 正しい入力データサイズを使用

    std::vector<BYTE> hash = SHA256((BYTE*)str, dataSize);

    for (BYTE b : hash) {
        printf("%02x", b);
    }

    printf("\n");

    return 0;
}

gotoで最後にまとめて解放するコードにしていたら、初期化(std::vector hashObject(cbData);)をバイパスしてますエラーがでるので あまりきれいじゃなけど、初期化をまとめたかったので、この書き方に・・・

70725d0f78cb0967c0e5171f733619712d239e28f2d279e4b3c3ed97f7456fa3
投稿日時: 2024-09-22 10:41:22
更新日時: 2024-09-22 10:43:22

最近の投稿

最近のコメント

タグ

アーカイブ

その他